blob: d248c946a13b169dc877e7f53b5c5393779d479e [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
David Kershner5f3a7e32015-05-13 13:22:10 -040028#include "channel_guid.h"
Prarit Bhargava55c67dc2015-05-05 18:37:02 -040029#include "controlvmchannel.h"
30#include "controlvmcompletionstatus.h"
31#include "guestlinuxdebug.h"
32#include "periodic_work.h"
Prarit Bhargava55c67dc2015-05-05 18:37:02 -040033#include "version.h"
34#include "visorbus.h"
35#include "visorbus_private.h"
David Kershner5f3a7e32015-05-13 13:22:10 -040036#include "vmcallinterface.h"
Prarit Bhargava55c67dc2015-05-05 18:37:02 -040037
Ken Cox12e364b2014-03-04 07:58:07 -060038#define CURRENT_FILE_PC VISOR_CHIPSET_PC_visorchipset_main_c
Ken Cox12e364b2014-03-04 07:58:07 -060039
40#define MAX_NAME_SIZE 128
41#define MAX_IP_SIZE 50
42#define MAXOUTSTANDINGCHANNELCOMMAND 256
43#define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1
44#define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100
45
Bhaktipriya Shridhar2c7e1d42015-12-09 20:57:05 +053046#define MAX_CONTROLVM_PAYLOAD_BYTES (1024 * 128)
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -040047
48#define VISORCHIPSET_MMAP_CONTROLCHANOFFSET 0x00000000
49
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -040050#define UNISYS_SPAR_LEAF_ID 0x40000000
51
52/* The s-Par leaf ID returns "UnisysSpar64" encoded across ebx, ecx, edx */
53#define UNISYS_SPAR_ID_EBX 0x73696e55
54#define UNISYS_SPAR_ID_ECX 0x70537379
55#define UNISYS_SPAR_ID_EDX 0x34367261
56
Jes Sorensenb615d622015-05-05 18:35:38 -040057/*
58 * Module parameters
59 */
Jes Sorensenb615d622015-05-05 18:35:38 -040060static int visorchipset_major;
David Kershner4da33362015-05-05 18:36:39 -040061static int visorchipset_visorbusregwait = 1; /* default is on */
Erik Arfvidson46168812015-05-05 18:36:14 -040062static unsigned long controlvm_payload_bytes_buffered;
Tim Sell12c957d2016-03-01 19:45:04 -050063static u32 dump_vhba_bus;
Jes Sorensenb615d622015-05-05 18:35:38 -040064
Erik Arfvidsone3420ed2015-05-05 18:36:13 -040065static int
66visorchipset_open(struct inode *inode, struct file *file)
67{
Tim Selle4feb2f2016-04-04 23:31:11 -040068 unsigned int minor_number = iminor(inode);
Erik Arfvidsone3420ed2015-05-05 18:36:13 -040069
70 if (minor_number)
71 return -ENODEV;
72 file->private_data = NULL;
73 return 0;
74}
75
76static int
77visorchipset_release(struct inode *inode, struct file *file)
78{
79 return 0;
80}
81
Ken Cox12e364b2014-03-04 07:58:07 -060082/* When the controlvm channel is idle for at least MIN_IDLE_SECONDS,
83* we switch to slow polling mode. As soon as we get a controlvm
84* message, we switch back to fast polling mode.
85*/
86#define MIN_IDLE_SECONDS 10
Jes Sorensen52063ec2015-04-13 10:28:41 -040087static unsigned long poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
Erik Arfvidson2ee0d052016-02-08 10:41:44 -050088/* when we got our last controlvm message */
89static unsigned long most_recent_message_jiffies;
David Kershner4da33362015-05-05 18:36:39 -040090static int visorbusregistered;
Ken Cox12e364b2014-03-04 07:58:07 -060091
Erik Arfvidson46168812015-05-05 18:36:14 -040092struct parser_context {
93 unsigned long allocbytes;
94 unsigned long param_bytes;
95 u8 *curr;
96 unsigned long bytes_remaining;
97 bool byte_stream;
98 char data[0];
99};
100
Benjamin Romer9232d2d2015-03-16 13:57:57 -0400101static struct delayed_work periodic_controlvm_work;
Benjamin Romer8f1947a2015-03-16 13:57:59 -0400102static DEFINE_SEMAPHORE(notifier_lock);
Ken Cox12e364b2014-03-04 07:58:07 -0600103
Erik Arfvidsone3420ed2015-05-05 18:36:13 -0400104static struct cdev file_cdev;
105static struct visorchannel **file_controlvm_channel;
Benjamin Romer4f44b722015-03-16 13:58:02 -0400106static struct controlvm_message_packet g_devicechangestate_packet;
Ken Cox12e364b2014-03-04 07:58:07 -0600107
Benjamin Romer1390b882015-03-16 13:58:03 -0400108static LIST_HEAD(bus_info_list);
109static LIST_HEAD(dev_info_list);
Ken Cox12e364b2014-03-04 07:58:07 -0600110
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400111static struct visorchannel *controlvm_channel;
Ken Cox12e364b2014-03-04 07:58:07 -0600112
Benjamin Romer84982fb2015-03-16 13:58:07 -0400113/* Manages the request payload in the controlvm channel */
Jes Sorensenc1f834e2015-04-13 10:28:39 -0400114struct visor_controlvm_payload_info {
Dan Williams3103dc02015-08-10 23:07:06 -0400115 u8 *ptr; /* pointer to base address of payload pool */
Benjamin Romer5fc02292014-07-31 12:00:51 -0400116 u64 offset; /* offset from beginning of controlvm
Erik Arfvidson2ee0d052016-02-08 10:41:44 -0500117 * channel to beginning of payload * pool
118 */
Benjamin Romerb3c55b12014-07-31 12:00:50 -0400119 u32 bytes; /* number of bytes in payload pool */
Jes Sorensenc1f834e2015-04-13 10:28:39 -0400120};
121
122static struct visor_controlvm_payload_info controlvm_payload_info;
Ken Cox12e364b2014-03-04 07:58:07 -0600123
Ken Cox12e364b2014-03-04 07:58:07 -0600124/* The following globals are used to handle the scenario where we are unable to
125 * offload the payload from a controlvm message due to memory requirements. In
126 * this scenario, we simply stash the controlvm message, then attempt to
127 * process it again the next time controlvm_periodic_work() runs.
128 */
Benjamin Romer7166ed12015-03-16 13:58:38 -0400129static struct controlvm_message controlvm_pending_msg;
Prarit Bhargavac79b28f2015-05-05 18:36:15 -0400130static bool controlvm_pending_msg_valid;
Ken Cox12e364b2014-03-04 07:58:07 -0600131
Ken Cox12e364b2014-03-04 07:58:07 -0600132/* This identifies a data buffer that has been received via a controlvm messages
133 * in a remote --> local CONTROLVM_TRANSMIT_FILE conversation.
134 */
135struct putfile_buffer_entry {
136 struct list_head next; /* putfile_buffer_entry list */
Benjamin Romer317d9612015-03-16 13:57:51 -0400137 struct parser_context *parser_ctx; /* points to input data buffer */
Ken Cox12e364b2014-03-04 07:58:07 -0600138};
139
140/* List of struct putfile_request *, via next_putfile_request member.
141 * Each entry in this list identifies an outstanding TRANSMIT_FILE
142 * conversation.
143 */
Benjamin Romer1eee0012015-03-16 13:58:39 -0400144static LIST_HEAD(putfile_request_list);
Ken Cox12e364b2014-03-04 07:58:07 -0600145
146/* This describes a buffer and its current state of transfer (e.g., how many
147 * bytes have already been supplied as putfile data, and how many bytes are
148 * remaining) for a putfile_request.
149 */
150struct putfile_active_buffer {
151 /* a payload from a controlvm message, containing a file data buffer */
Benjamin Romer317d9612015-03-16 13:57:51 -0400152 struct parser_context *parser_ctx;
Ken Cox12e364b2014-03-04 07:58:07 -0600153 /* points within data area of parser_ctx to next byte of data */
Ken Cox12e364b2014-03-04 07:58:07 -0600154 size_t bytes_remaining;
155};
156
157#define PUTFILE_REQUEST_SIG 0x0906101302281211
158/* This identifies a single remote --> local CONTROLVM_TRANSMIT_FILE
159 * conversation. Structs of this type are dynamically linked into
160 * <Putfile_request_list>.
161 */
162struct putfile_request {
163 u64 sig; /* PUTFILE_REQUEST_SIG */
164
165 /* header from original TransmitFile request */
Benjamin Romer98d7b592014-10-23 14:30:26 -0400166 struct controlvm_message_header controlvm_header;
Ken Cox12e364b2014-03-04 07:58:07 -0600167
168 /* link to next struct putfile_request */
169 struct list_head next_putfile_request;
170
Ken Cox12e364b2014-03-04 07:58:07 -0600171 /* head of putfile_buffer_entry list, which describes the data to be
172 * supplied as putfile data;
173 * - this list is added to when controlvm messages come in that supply
174 * file data
175 * - this list is removed from via the hotplug program that is actually
Erik Arfvidson2ee0d052016-02-08 10:41:44 -0500176 * consuming these buffers to write as file data
177 */
Ken Cox12e364b2014-03-04 07:58:07 -0600178 struct list_head input_buffer_list;
179 spinlock_t req_list_lock; /* lock for input_buffer_list */
180
181 /* waiters for input_buffer_list to go non-empty */
182 wait_queue_head_t input_buffer_wq;
183
184 /* data not yet read within current putfile_buffer_entry */
185 struct putfile_active_buffer active_buf;
186
187 /* <0 = failed, 0 = in-progress, >0 = successful; */
188 /* note that this must be set with req_list_lock, and if you set <0, */
189 /* it is your responsibility to also free up all of the other objects */
190 /* in this struct (like input_buffer_list, active_buf.parser_ctx) */
191 /* before releasing the lock */
192 int completion_status;
193};
194
Ken Cox12e364b2014-03-04 07:58:07 -0600195struct parahotplug_request {
196 struct list_head list;
197 int id;
198 unsigned long expiration;
Benjamin Romer3ab47702014-10-23 14:30:31 -0400199 struct controlvm_message msg;
Ken Cox12e364b2014-03-04 07:58:07 -0600200};
201
Benjamin Romerddf5de52015-03-16 13:58:41 -0400202static LIST_HEAD(parahotplug_request_list);
203static DEFINE_SPINLOCK(parahotplug_request_list_lock); /* lock for above */
Ken Cox12e364b2014-03-04 07:58:07 -0600204static void parahotplug_process_list(void);
205
206/* Manages the info for a CONTROLVM_DUMP_CAPTURESTATE /
207 * CONTROLVM_REPORTEVENT.
208 */
David Kershner4da33362015-05-05 18:36:39 -0400209static struct visorchipset_busdev_notifiers busdev_notifiers;
Ken Cox12e364b2014-03-04 07:58:07 -0600210
Don Zickusd32517e2015-06-04 09:22:41 -0400211static void bus_create_response(struct visor_device *p, int response);
212static void bus_destroy_response(struct visor_device *p, int response);
Don Zickusa298bc02015-06-04 09:22:42 -0400213static void device_create_response(struct visor_device *p, int response);
214static void device_destroy_response(struct visor_device *p, int response);
215static void device_resume_response(struct visor_device *p, int response);
Ken Cox12e364b2014-03-04 07:58:07 -0600216
Don Zickusa298bc02015-06-04 09:22:42 -0400217static void visorchipset_device_pause_response(struct visor_device *p,
218 int response);
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -0400219
Benjamin Romer8e3fedd2015-03-16 13:58:43 -0400220static struct visorchipset_busdev_responders busdev_responders = {
Ken Cox12e364b2014-03-04 07:58:07 -0600221 .bus_create = bus_create_response,
222 .bus_destroy = bus_destroy_response,
223 .device_create = device_create_response,
224 .device_destroy = device_destroy_response,
Ken Cox927c7922014-03-05 14:52:25 -0600225 .device_pause = visorchipset_device_pause_response,
Ken Cox12e364b2014-03-04 07:58:07 -0600226 .device_resume = device_resume_response,
227};
228
229/* info for /dev/visorchipset */
Benjamin Romer5aa8ae52015-03-16 13:58:44 -0400230static dev_t major_dev = -1; /**< indicates major num for device */
Ken Cox12e364b2014-03-04 07:58:07 -0600231
Benjamin Romer19f66342014-07-22 09:56:25 -0400232/* prototypes for attributes */
233static ssize_t toolaction_show(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400234 struct device_attribute *attr, char *buf);
Benjamin Romer19f66342014-07-22 09:56:25 -0400235static ssize_t toolaction_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400236 struct device_attribute *attr,
237 const char *buf, size_t count);
Benjamin Romer19f66342014-07-22 09:56:25 -0400238static DEVICE_ATTR_RW(toolaction);
239
Benjamin Romer54b31222014-07-22 09:56:26 -0400240static ssize_t boottotool_show(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400241 struct device_attribute *attr, char *buf);
Benjamin Romer54b31222014-07-22 09:56:26 -0400242static ssize_t boottotool_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400243 struct device_attribute *attr, const char *buf,
244 size_t count);
Benjamin Romer54b31222014-07-22 09:56:26 -0400245static DEVICE_ATTR_RW(boottotool);
246
Benjamin Romer422af172014-07-24 14:08:42 -0400247static ssize_t error_show(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400248 char *buf);
Benjamin Romer422af172014-07-24 14:08:42 -0400249static ssize_t error_store(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400250 const char *buf, size_t count);
Benjamin Romer422af172014-07-24 14:08:42 -0400251static DEVICE_ATTR_RW(error);
252
253static ssize_t textid_show(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400254 char *buf);
Benjamin Romer422af172014-07-24 14:08:42 -0400255static ssize_t textid_store(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400256 const char *buf, size_t count);
Benjamin Romer422af172014-07-24 14:08:42 -0400257static DEVICE_ATTR_RW(textid);
258
259static ssize_t remaining_steps_show(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400260 struct device_attribute *attr, char *buf);
Benjamin Romer422af172014-07-24 14:08:42 -0400261static ssize_t remaining_steps_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400262 struct device_attribute *attr,
263 const char *buf, size_t count);
Benjamin Romer422af172014-07-24 14:08:42 -0400264static DEVICE_ATTR_RW(remaining_steps);
265
Benjamin Romere56fa7c2014-07-29 11:11:21 -0400266static ssize_t devicedisabled_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400267 struct device_attribute *attr,
268 const char *buf, size_t count);
Benjamin Romere56fa7c2014-07-29 11:11:21 -0400269static DEVICE_ATTR_WO(devicedisabled);
270
271static ssize_t deviceenabled_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400272 struct device_attribute *attr,
273 const char *buf, size_t count);
Benjamin Romere56fa7c2014-07-29 11:11:21 -0400274static DEVICE_ATTR_WO(deviceenabled);
275
Benjamin Romer19f66342014-07-22 09:56:25 -0400276static struct attribute *visorchipset_install_attrs[] = {
277 &dev_attr_toolaction.attr,
Benjamin Romer54b31222014-07-22 09:56:26 -0400278 &dev_attr_boottotool.attr,
Benjamin Romer422af172014-07-24 14:08:42 -0400279 &dev_attr_error.attr,
280 &dev_attr_textid.attr,
281 &dev_attr_remaining_steps.attr,
Benjamin Romer19f66342014-07-22 09:56:25 -0400282 NULL
283};
284
285static struct attribute_group visorchipset_install_group = {
286 .name = "install",
287 .attrs = visorchipset_install_attrs
288};
289
Benjamin Romere56fa7c2014-07-29 11:11:21 -0400290static struct attribute *visorchipset_parahotplug_attrs[] = {
291 &dev_attr_devicedisabled.attr,
292 &dev_attr_deviceenabled.attr,
293 NULL
294};
295
296static struct attribute_group visorchipset_parahotplug_group = {
297 .name = "parahotplug",
298 .attrs = visorchipset_parahotplug_attrs
299};
300
Benjamin Romer19f66342014-07-22 09:56:25 -0400301static const struct attribute_group *visorchipset_dev_groups[] = {
302 &visorchipset_install_group,
Benjamin Romere56fa7c2014-07-29 11:11:21 -0400303 &visorchipset_parahotplug_group,
Benjamin Romer19f66342014-07-22 09:56:25 -0400304 NULL
305};
306
Don Zickus04dacac2015-06-04 09:22:48 -0400307static void visorchipset_dev_release(struct device *dev)
308{
309}
310
Ken Cox12e364b2014-03-04 07:58:07 -0600311/* /sys/devices/platform/visorchipset */
Benjamin Romereb34e872015-03-16 13:58:45 -0400312static struct platform_device visorchipset_platform_device = {
Ken Cox12e364b2014-03-04 07:58:07 -0600313 .name = "visorchipset",
314 .id = -1,
Benjamin Romer19f66342014-07-22 09:56:25 -0400315 .dev.groups = visorchipset_dev_groups,
Don Zickus04dacac2015-06-04 09:22:48 -0400316 .dev.release = visorchipset_dev_release,
Ken Cox12e364b2014-03-04 07:58:07 -0600317};
318
319/* Function prototypes */
Benjamin Romerb3168c72015-03-16 13:58:46 -0400320static void controlvm_respond(struct controlvm_message_header *msg_hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400321 int response);
322static void controlvm_respond_chipset_init(
Benjamin Romerb3168c72015-03-16 13:58:46 -0400323 struct controlvm_message_header *msg_hdr, int response,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400324 enum ultra_chipset_feature features);
325static void controlvm_respond_physdev_changestate(
Benjamin Romerb3168c72015-03-16 13:58:46 -0400326 struct controlvm_message_header *msg_hdr, int response,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400327 struct spar_segment_state state);
Ken Cox12e364b2014-03-04 07:58:07 -0600328
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -0400329static void parser_done(struct parser_context *ctx);
330
Erik Arfvidson46168812015-05-05 18:36:14 -0400331static struct parser_context *
Jes Sorensenfbf35532015-05-05 18:37:14 -0400332parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry)
Erik Arfvidson46168812015-05-05 18:36:14 -0400333{
334 int allocbytes = sizeof(struct parser_context) + bytes;
David Kershnerd79f56b2016-03-11 17:01:40 -0500335 struct parser_context *ctx;
Erik Arfvidson46168812015-05-05 18:36:14 -0400336
337 if (retry)
338 *retry = false;
Jes Sorensencc55b5c2015-05-05 18:37:13 -0400339
340 /*
341 * alloc an 0 extra byte to ensure payload is
342 * '\0'-terminated
343 */
344 allocbytes++;
Erik Arfvidson46168812015-05-05 18:36:14 -0400345 if ((controlvm_payload_bytes_buffered + bytes)
346 > MAX_CONTROLVM_PAYLOAD_BYTES) {
347 if (retry)
348 *retry = true;
David Kershnerd79f56b2016-03-11 17:01:40 -0500349 return NULL;
Erik Arfvidson46168812015-05-05 18:36:14 -0400350 }
Erik Arfvidson8c395e72016-02-08 10:41:45 -0500351 ctx = kzalloc(allocbytes, GFP_KERNEL | __GFP_NORETRY);
Erik Arfvidson46168812015-05-05 18:36:14 -0400352 if (!ctx) {
353 if (retry)
354 *retry = true;
David Kershnerd79f56b2016-03-11 17:01:40 -0500355 return NULL;
Erik Arfvidson46168812015-05-05 18:36:14 -0400356 }
357
358 ctx->allocbytes = allocbytes;
359 ctx->param_bytes = bytes;
360 ctx->curr = NULL;
361 ctx->bytes_remaining = 0;
362 ctx->byte_stream = false;
363 if (local) {
364 void *p;
365
David Kershnerd79f56b2016-03-11 17:01:40 -0500366 if (addr > virt_to_phys(high_memory - 1))
367 goto err_finish_ctx;
Erik Arfvidson0e7bf2f2016-02-08 10:41:48 -0500368 p = __va((unsigned long)(addr));
Erik Arfvidson46168812015-05-05 18:36:14 -0400369 memcpy(ctx->data, p, bytes);
370 } else {
Tim Sella8deaef2016-03-01 19:45:02 -0500371 void *mapping = memremap(addr, bytes, MEMREMAP_WB);
Jes Sorensen712c03d2015-05-05 18:36:25 -0400372
David Kershnerd79f56b2016-03-11 17:01:40 -0500373 if (!mapping)
374 goto err_finish_ctx;
Dan Williams3103dc02015-08-10 23:07:06 -0400375 memcpy(ctx->data, mapping, bytes);
Dan Williams3103dc02015-08-10 23:07:06 -0400376 memunmap(mapping);
Erik Arfvidson46168812015-05-05 18:36:14 -0400377 }
Erik Arfvidson46168812015-05-05 18:36:14 -0400378
Jes Sorensencc55b5c2015-05-05 18:37:13 -0400379 ctx->byte_stream = true;
David Kershnerd79f56b2016-03-11 17:01:40 -0500380 controlvm_payload_bytes_buffered += ctx->param_bytes;
381
382 return ctx;
383
384err_finish_ctx:
385 parser_done(ctx);
386 return NULL;
Erik Arfvidson46168812015-05-05 18:36:14 -0400387}
388
Jes Sorensen464129e2015-05-05 18:37:12 -0400389static uuid_le
Erik Arfvidson46168812015-05-05 18:36:14 -0400390parser_id_get(struct parser_context *ctx)
391{
392 struct spar_controlvm_parameters_header *phdr = NULL;
393
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500394 if (!ctx)
Erik Arfvidson46168812015-05-05 18:36:14 -0400395 return NULL_UUID_LE;
396 phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
397 return phdr->id;
398}
399
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -0400400/** Describes the state from the perspective of which controlvm messages have
401 * been received for a bus or device.
402 */
403
404enum PARSER_WHICH_STRING {
405 PARSERSTRING_INITIATOR,
406 PARSERSTRING_TARGET,
407 PARSERSTRING_CONNECTION,
408 PARSERSTRING_NAME, /* TODO: only PARSERSTRING_NAME is used ? */
409};
410
Jes Sorensen464129e2015-05-05 18:37:12 -0400411static void
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -0400412parser_param_start(struct parser_context *ctx,
413 enum PARSER_WHICH_STRING which_string)
Erik Arfvidson46168812015-05-05 18:36:14 -0400414{
415 struct spar_controlvm_parameters_header *phdr = NULL;
416
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500417 if (!ctx)
Benjamin Romerb4d4dfb2016-02-08 10:41:53 -0500418 return;
419
Erik Arfvidson46168812015-05-05 18:36:14 -0400420 phdr = (struct spar_controlvm_parameters_header *)(ctx->data);
421 switch (which_string) {
422 case PARSERSTRING_INITIATOR:
423 ctx->curr = ctx->data + phdr->initiator_offset;
424 ctx->bytes_remaining = phdr->initiator_length;
425 break;
426 case PARSERSTRING_TARGET:
427 ctx->curr = ctx->data + phdr->target_offset;
428 ctx->bytes_remaining = phdr->target_length;
429 break;
430 case PARSERSTRING_CONNECTION:
431 ctx->curr = ctx->data + phdr->connection_offset;
432 ctx->bytes_remaining = phdr->connection_length;
433 break;
434 case PARSERSTRING_NAME:
435 ctx->curr = ctx->data + phdr->name_offset;
436 ctx->bytes_remaining = phdr->name_length;
437 break;
438 default:
439 break;
440 }
Erik Arfvidson46168812015-05-05 18:36:14 -0400441}
442
Jes Sorensen464129e2015-05-05 18:37:12 -0400443static void parser_done(struct parser_context *ctx)
Erik Arfvidson46168812015-05-05 18:36:14 -0400444{
445 if (!ctx)
446 return;
447 controlvm_payload_bytes_buffered -= ctx->param_bytes;
448 kfree(ctx);
449}
450
Jes Sorensen464129e2015-05-05 18:37:12 -0400451static void *
Erik Arfvidson46168812015-05-05 18:36:14 -0400452parser_string_get(struct parser_context *ctx)
453{
454 u8 *pscan;
455 unsigned long nscan;
456 int value_length = -1;
457 void *value = NULL;
458 int i;
459
460 if (!ctx)
461 return NULL;
462 pscan = ctx->curr;
463 nscan = ctx->bytes_remaining;
464 if (nscan == 0)
465 return NULL;
466 if (!pscan)
467 return NULL;
468 for (i = 0, value_length = -1; i < nscan; i++)
469 if (pscan[i] == '\0') {
470 value_length = i;
471 break;
472 }
473 if (value_length < 0) /* '\0' was not included in the length */
474 value_length = nscan;
Erik Arfvidson8c395e72016-02-08 10:41:45 -0500475 value = kmalloc(value_length + 1, GFP_KERNEL | __GFP_NORETRY);
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500476 if (!value)
Erik Arfvidson46168812015-05-05 18:36:14 -0400477 return NULL;
478 if (value_length > 0)
479 memcpy(value, pscan, value_length);
Erik Arfvidson0e7bf2f2016-02-08 10:41:48 -0500480 ((u8 *)(value))[value_length] = '\0';
Erik Arfvidson46168812015-05-05 18:36:14 -0400481 return value;
482}
483
Vincent Bernatd746cb52014-08-01 10:29:30 +0200484static ssize_t toolaction_show(struct device *dev,
485 struct device_attribute *attr,
486 char *buf)
Benjamin Romer19f66342014-07-22 09:56:25 -0400487{
David Binder3a56d702016-04-18 23:40:09 -0400488 u8 tool_action = 0;
Benjamin Romer19f66342014-07-22 09:56:25 -0400489
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400490 visorchannel_read(controlvm_channel,
Benjamin Romer6bb871b2015-12-07 10:58:37 -0500491 offsetof(struct spar_controlvm_channel_protocol,
492 tool_action), &tool_action, sizeof(u8));
Benjamin Romer01f4d852015-03-16 13:58:48 -0400493 return scnprintf(buf, PAGE_SIZE, "%u\n", tool_action);
Benjamin Romer19f66342014-07-22 09:56:25 -0400494}
495
Vincent Bernatd746cb52014-08-01 10:29:30 +0200496static ssize_t toolaction_store(struct device *dev,
497 struct device_attribute *attr,
498 const char *buf, size_t count)
Benjamin Romer19f66342014-07-22 09:56:25 -0400499{
Benjamin Romer01f4d852015-03-16 13:58:48 -0400500 u8 tool_action;
Benjamin Romer66e24b72014-07-25 13:55:10 -0400501 int ret;
Benjamin Romer19f66342014-07-22 09:56:25 -0400502
Jes Sorensenebec8962015-05-05 18:35:57 -0400503 if (kstrtou8(buf, 10, &tool_action))
Benjamin Romer66e24b72014-07-25 13:55:10 -0400504 return -EINVAL;
505
Tim Sella07d7c32016-04-04 23:31:12 -0400506 ret = visorchannel_write
507 (controlvm_channel,
508 offsetof(struct spar_controlvm_channel_protocol,
509 tool_action),
510 &tool_action, sizeof(u8));
Benjamin Romer66e24b72014-07-25 13:55:10 -0400511
512 if (ret)
513 return ret;
Benjamin Romere22a4a02014-08-18 09:34:54 -0400514 return count;
Benjamin Romer19f66342014-07-22 09:56:25 -0400515}
516
Vincent Bernatd746cb52014-08-01 10:29:30 +0200517static ssize_t boottotool_show(struct device *dev,
518 struct device_attribute *attr,
519 char *buf)
Benjamin Romer54b31222014-07-22 09:56:26 -0400520{
Benjamin Romer365522d2015-03-16 13:58:49 -0400521 struct efi_spar_indication efi_spar_indication;
Benjamin Romer54b31222014-07-22 09:56:26 -0400522
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400523 visorchannel_read(controlvm_channel,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400524 offsetof(struct spar_controlvm_channel_protocol,
525 efi_spar_ind), &efi_spar_indication,
526 sizeof(struct efi_spar_indication));
Benjamin Romer54b31222014-07-22 09:56:26 -0400527 return scnprintf(buf, PAGE_SIZE, "%u\n",
Benjamin Romer8e76e692015-03-16 13:58:52 -0400528 efi_spar_indication.boot_to_tool);
Benjamin Romer54b31222014-07-22 09:56:26 -0400529}
530
Vincent Bernatd746cb52014-08-01 10:29:30 +0200531static ssize_t boottotool_store(struct device *dev,
532 struct device_attribute *attr,
533 const char *buf, size_t count)
Benjamin Romer54b31222014-07-22 09:56:26 -0400534{
Benjamin Romer66e24b72014-07-25 13:55:10 -0400535 int val, ret;
Benjamin Romer365522d2015-03-16 13:58:49 -0400536 struct efi_spar_indication efi_spar_indication;
Benjamin Romer54b31222014-07-22 09:56:26 -0400537
Jes Sorensenebec8962015-05-05 18:35:57 -0400538 if (kstrtoint(buf, 10, &val))
Benjamin Romer66e24b72014-07-25 13:55:10 -0400539 return -EINVAL;
540
Benjamin Romer365522d2015-03-16 13:58:49 -0400541 efi_spar_indication.boot_to_tool = val;
Tim Sella07d7c32016-04-04 23:31:12 -0400542 ret = visorchannel_write
543 (controlvm_channel,
544 offsetof(struct spar_controlvm_channel_protocol,
545 efi_spar_ind), &(efi_spar_indication),
546 sizeof(struct efi_spar_indication));
Benjamin Romer66e24b72014-07-25 13:55:10 -0400547
548 if (ret)
549 return ret;
Benjamin Romere22a4a02014-08-18 09:34:54 -0400550 return count;
Benjamin Romer54b31222014-07-22 09:56:26 -0400551}
Benjamin Romer422af172014-07-24 14:08:42 -0400552
553static ssize_t error_show(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400554 char *buf)
Benjamin Romer422af172014-07-24 14:08:42 -0400555{
David Binder3a56d702016-04-18 23:40:09 -0400556 u32 error = 0;
Benjamin Romer422af172014-07-24 14:08:42 -0400557
Benjamin Romer8e76e692015-03-16 13:58:52 -0400558 visorchannel_read(controlvm_channel,
559 offsetof(struct spar_controlvm_channel_protocol,
560 installation_error),
561 &error, sizeof(u32));
Benjamin Romer422af172014-07-24 14:08:42 -0400562 return scnprintf(buf, PAGE_SIZE, "%i\n", error);
563}
564
565static ssize_t error_store(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400566 const char *buf, size_t count)
Benjamin Romer422af172014-07-24 14:08:42 -0400567{
568 u32 error;
Benjamin Romer66e24b72014-07-25 13:55:10 -0400569 int ret;
Benjamin Romer422af172014-07-24 14:08:42 -0400570
Jes Sorensenebec8962015-05-05 18:35:57 -0400571 if (kstrtou32(buf, 10, &error))
Benjamin Romer66e24b72014-07-25 13:55:10 -0400572 return -EINVAL;
573
Tim Sella07d7c32016-04-04 23:31:12 -0400574 ret = visorchannel_write
575 (controlvm_channel,
576 offsetof(struct spar_controlvm_channel_protocol,
577 installation_error),
578 &error, sizeof(u32));
Benjamin Romer66e24b72014-07-25 13:55:10 -0400579 if (ret)
580 return ret;
Benjamin Romere22a4a02014-08-18 09:34:54 -0400581 return count;
Benjamin Romer422af172014-07-24 14:08:42 -0400582}
583
584static ssize_t textid_show(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400585 char *buf)
Benjamin Romer422af172014-07-24 14:08:42 -0400586{
David Binder3a56d702016-04-18 23:40:09 -0400587 u32 text_id = 0;
Benjamin Romer422af172014-07-24 14:08:42 -0400588
Tim Sella07d7c32016-04-04 23:31:12 -0400589 visorchannel_read
590 (controlvm_channel,
591 offsetof(struct spar_controlvm_channel_protocol,
592 installation_text_id),
593 &text_id, sizeof(u32));
Benjamin Romer10dbf0e2015-03-16 13:58:50 -0400594 return scnprintf(buf, PAGE_SIZE, "%i\n", text_id);
Benjamin Romer422af172014-07-24 14:08:42 -0400595}
596
597static ssize_t textid_store(struct device *dev, struct device_attribute *attr,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400598 const char *buf, size_t count)
Benjamin Romer422af172014-07-24 14:08:42 -0400599{
Benjamin Romer10dbf0e2015-03-16 13:58:50 -0400600 u32 text_id;
Benjamin Romer66e24b72014-07-25 13:55:10 -0400601 int ret;
Benjamin Romer422af172014-07-24 14:08:42 -0400602
Jes Sorensenebec8962015-05-05 18:35:57 -0400603 if (kstrtou32(buf, 10, &text_id))
Benjamin Romer66e24b72014-07-25 13:55:10 -0400604 return -EINVAL;
605
Tim Sella07d7c32016-04-04 23:31:12 -0400606 ret = visorchannel_write
607 (controlvm_channel,
608 offsetof(struct spar_controlvm_channel_protocol,
609 installation_text_id),
610 &text_id, sizeof(u32));
Benjamin Romer66e24b72014-07-25 13:55:10 -0400611 if (ret)
612 return ret;
Benjamin Romere22a4a02014-08-18 09:34:54 -0400613 return count;
Benjamin Romer422af172014-07-24 14:08:42 -0400614}
615
Benjamin Romer422af172014-07-24 14:08:42 -0400616static ssize_t remaining_steps_show(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400617 struct device_attribute *attr, char *buf)
Benjamin Romer422af172014-07-24 14:08:42 -0400618{
David Binder3a56d702016-04-18 23:40:09 -0400619 u16 remaining_steps = 0;
Benjamin Romer422af172014-07-24 14:08:42 -0400620
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400621 visorchannel_read(controlvm_channel,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400622 offsetof(struct spar_controlvm_channel_protocol,
623 installation_remaining_steps),
624 &remaining_steps, sizeof(u16));
Benjamin Romeree8da292015-03-16 13:58:51 -0400625 return scnprintf(buf, PAGE_SIZE, "%hu\n", remaining_steps);
Benjamin Romer422af172014-07-24 14:08:42 -0400626}
627
628static ssize_t remaining_steps_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -0400629 struct device_attribute *attr,
630 const char *buf, size_t count)
Benjamin Romer422af172014-07-24 14:08:42 -0400631{
Benjamin Romeree8da292015-03-16 13:58:51 -0400632 u16 remaining_steps;
Benjamin Romer66e24b72014-07-25 13:55:10 -0400633 int ret;
Benjamin Romer422af172014-07-24 14:08:42 -0400634
Jes Sorensenebec8962015-05-05 18:35:57 -0400635 if (kstrtou16(buf, 10, &remaining_steps))
Benjamin Romer66e24b72014-07-25 13:55:10 -0400636 return -EINVAL;
637
Tim Sella07d7c32016-04-04 23:31:12 -0400638 ret = visorchannel_write
639 (controlvm_channel,
640 offsetof(struct spar_controlvm_channel_protocol,
641 installation_remaining_steps),
642 &remaining_steps, sizeof(u16));
Benjamin Romer66e24b72014-07-25 13:55:10 -0400643 if (ret)
644 return ret;
Benjamin Romere22a4a02014-08-18 09:34:54 -0400645 return count;
Benjamin Romer422af172014-07-24 14:08:42 -0400646}
647
Don Zickusab0592b2015-05-13 13:22:19 -0400648struct visor_busdev {
649 u32 bus_no;
650 u32 dev_no;
651};
652
653static int match_visorbus_dev_by_id(struct device *dev, void *data)
654{
655 struct visor_device *vdev = to_visor_device(dev);
Shraddha Barke7f445822015-10-15 00:58:23 +0530656 struct visor_busdev *id = data;
Don Zickusab0592b2015-05-13 13:22:19 -0400657 u32 bus_no = id->bus_no;
658 u32 dev_no = id->dev_no;
659
Don Zickus65bd6e42015-06-04 09:22:40 -0400660 if ((vdev->chipset_bus_no == bus_no) &&
661 (vdev->chipset_dev_no == dev_no))
Don Zickusab0592b2015-05-13 13:22:19 -0400662 return 1;
663
664 return 0;
665}
Erik Arfvidsond1e08632016-02-08 10:41:47 -0500666
Don Zickusab0592b2015-05-13 13:22:19 -0400667struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no,
668 struct visor_device *from)
669{
670 struct device *dev;
671 struct device *dev_start = NULL;
672 struct visor_device *vdev = NULL;
673 struct visor_busdev id = {
674 .bus_no = bus_no,
675 .dev_no = dev_no
676 };
677
678 if (from)
679 dev_start = &from->device;
680 dev = bus_find_device(&visorbus_type, dev_start, (void *)&id,
681 match_visorbus_dev_by_id);
682 if (dev)
683 vdev = to_visor_device(dev);
684 return vdev;
685}
686EXPORT_SYMBOL(visorbus_get_device_by_id);
687
Ken Cox12e364b2014-03-04 07:58:07 -0600688void
David Kershner4da33362015-05-05 18:36:39 -0400689visorchipset_register_busdev(
Benjamin Romerfe90d892014-10-31 09:57:32 -0400690 struct visorchipset_busdev_notifiers *notifiers,
Benjamin Romer929aa8a2014-10-31 09:57:33 -0400691 struct visorchipset_busdev_responders *responders,
Benjamin Romer1e7a59c2014-10-31 09:57:35 -0400692 struct ultra_vbus_deviceinfo *driver_info)
Ken Cox12e364b2014-03-04 07:58:07 -0600693{
Benjamin Romer8f1947a2015-03-16 13:57:59 -0400694 down(&notifier_lock);
Benjamin Romer38f736e2015-03-16 13:58:13 -0400695 if (!notifiers) {
David Kershner4da33362015-05-05 18:36:39 -0400696 memset(&busdev_notifiers, 0,
697 sizeof(busdev_notifiers));
698 visorbusregistered = 0; /* clear flag */
Ken Cox12e364b2014-03-04 07:58:07 -0600699 } else {
David Kershner4da33362015-05-05 18:36:39 -0400700 busdev_notifiers = *notifiers;
701 visorbusregistered = 1; /* set flag */
Ken Cox12e364b2014-03-04 07:58:07 -0600702 }
703 if (responders)
Benjamin Romer8e3fedd2015-03-16 13:58:43 -0400704 *responders = busdev_responders;
Benjamin Romer1e7a59c2014-10-31 09:57:35 -0400705 if (driver_info)
706 bus_device_info_init(driver_info, "chipset", "visorchipset",
Benjamin Romer8e76e692015-03-16 13:58:52 -0400707 VERSION, NULL);
Ken Cox12e364b2014-03-04 07:58:07 -0600708
Benjamin Romer8f1947a2015-03-16 13:57:59 -0400709 up(&notifier_lock);
Ken Cox12e364b2014-03-04 07:58:07 -0600710}
David Kershner4da33362015-05-05 18:36:39 -0400711EXPORT_SYMBOL_GPL(visorchipset_register_busdev);
Ken Cox12e364b2014-03-04 07:58:07 -0600712
713static void
Benjamin Romer3ab47702014-10-23 14:30:31 -0400714chipset_init(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -0600715{
716 static int chipset_inited;
Benjamin Romerb9b141e2014-10-23 14:30:24 -0400717 enum ultra_chipset_feature features = 0;
Ken Cox12e364b2014-03-04 07:58:07 -0600718 int rc = CONTROLVM_RESP_SUCCESS;
719
720 POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO);
721 if (chipset_inited) {
Ken Cox22ad57b2014-03-19 13:06:25 -0500722 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
David Kershner5233d1e2016-03-11 17:01:41 -0500723 goto out_respond;
Ken Cox12e364b2014-03-04 07:58:07 -0600724 }
725 chipset_inited = 1;
726 POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO);
727
728 /* Set features to indicate we support parahotplug (if Command
Erik Arfvidson2ee0d052016-02-08 10:41:44 -0500729 * also supports it).
730 */
Ken Cox12e364b2014-03-04 07:58:07 -0600731 features =
Benjamin Romer2ea51172014-10-23 14:30:25 -0400732 inmsg->cmd.init_chipset.
Ken Cox12e364b2014-03-04 07:58:07 -0600733 features & ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG;
734
735 /* Set the "reply" bit so Command knows this is a
Erik Arfvidson2ee0d052016-02-08 10:41:44 -0500736 * features-aware driver.
737 */
Ken Cox12e364b2014-03-04 07:58:07 -0600738 features |= ULTRA_CHIPSET_FEATURE_REPLY;
739
David Kershner5233d1e2016-03-11 17:01:41 -0500740out_respond:
Benjamin Romer98d7b592014-10-23 14:30:26 -0400741 if (inmsg->hdr.flags.response_expected)
Ken Cox12e364b2014-03-04 07:58:07 -0600742 controlvm_respond_chipset_init(&inmsg->hdr, rc, features);
743}
744
745static void
Benjamin Romer3ab47702014-10-23 14:30:31 -0400746controlvm_init_response(struct controlvm_message *msg,
Benjamin Romerb3168c72015-03-16 13:58:46 -0400747 struct controlvm_message_header *msg_hdr, int response)
Ken Cox12e364b2014-03-04 07:58:07 -0600748{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400749 memset(msg, 0, sizeof(struct controlvm_message));
Benjamin Romerb3168c72015-03-16 13:58:46 -0400750 memcpy(&msg->hdr, msg_hdr, sizeof(struct controlvm_message_header));
Benjamin Romer98d7b592014-10-23 14:30:26 -0400751 msg->hdr.payload_bytes = 0;
752 msg->hdr.payload_vm_offset = 0;
753 msg->hdr.payload_max_bytes = 0;
Ken Cox12e364b2014-03-04 07:58:07 -0600754 if (response < 0) {
Benjamin Romer98d7b592014-10-23 14:30:26 -0400755 msg->hdr.flags.failed = 1;
Erik Arfvidson0e7bf2f2016-02-08 10:41:48 -0500756 msg->hdr.completion_status = (u32)(-response);
Ken Cox12e364b2014-03-04 07:58:07 -0600757 }
758}
759
760static void
Benjamin Romerb3168c72015-03-16 13:58:46 -0400761controlvm_respond(struct controlvm_message_header *msg_hdr, int response)
Ken Cox12e364b2014-03-04 07:58:07 -0600762{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400763 struct controlvm_message outmsg;
Benjamin Romer26eb2c02014-08-18 09:34:53 -0400764
Benjamin Romerb3168c72015-03-16 13:58:46 -0400765 controlvm_init_response(&outmsg, msg_hdr, response);
Benjamin Romer2098dbd2015-03-04 12:14:22 -0500766 if (outmsg.hdr.flags.test_message == 1)
Ken Cox12e364b2014-03-04 07:58:07 -0600767 return;
Benjamin Romer2098dbd2015-03-04 12:14:22 -0500768
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400769 if (!visorchannel_signalinsert(controlvm_channel,
Ken Cox12e364b2014-03-04 07:58:07 -0600770 CONTROLVM_QUEUE_REQUEST, &outmsg)) {
Ken Cox12e364b2014-03-04 07:58:07 -0600771 return;
772 }
773}
774
775static void
Benjamin Romerb3168c72015-03-16 13:58:46 -0400776controlvm_respond_chipset_init(struct controlvm_message_header *msg_hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400777 int response,
Benjamin Romerb9b141e2014-10-23 14:30:24 -0400778 enum ultra_chipset_feature features)
Ken Cox12e364b2014-03-04 07:58:07 -0600779{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400780 struct controlvm_message outmsg;
Benjamin Romer26eb2c02014-08-18 09:34:53 -0400781
Benjamin Romerb3168c72015-03-16 13:58:46 -0400782 controlvm_init_response(&outmsg, msg_hdr, response);
Benjamin Romer2ea51172014-10-23 14:30:25 -0400783 outmsg.cmd.init_chipset.features = features;
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400784 if (!visorchannel_signalinsert(controlvm_channel,
Ken Cox12e364b2014-03-04 07:58:07 -0600785 CONTROLVM_QUEUE_REQUEST, &outmsg)) {
Ken Cox12e364b2014-03-04 07:58:07 -0600786 return;
787 }
788}
789
Benjamin Romer98d7b592014-10-23 14:30:26 -0400790static void controlvm_respond_physdev_changestate(
Benjamin Romerb3168c72015-03-16 13:58:46 -0400791 struct controlvm_message_header *msg_hdr, int response,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400792 struct spar_segment_state state)
Ken Cox12e364b2014-03-04 07:58:07 -0600793{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400794 struct controlvm_message outmsg;
Benjamin Romer26eb2c02014-08-18 09:34:53 -0400795
Benjamin Romerb3168c72015-03-16 13:58:46 -0400796 controlvm_init_response(&outmsg, msg_hdr, response);
Benjamin Romer2ea51172014-10-23 14:30:25 -0400797 outmsg.cmd.device_change_state.state = state;
798 outmsg.cmd.device_change_state.flags.phys_device = 1;
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400799 if (!visorchannel_signalinsert(controlvm_channel,
Ken Cox12e364b2014-03-04 07:58:07 -0600800 CONTROLVM_QUEUE_REQUEST, &outmsg)) {
Ken Cox12e364b2014-03-04 07:58:07 -0600801 return;
802 }
803}
804
Prarit Bhargava2ee0dee2015-05-05 18:36:16 -0400805enum crash_obj_type {
806 CRASH_DEV,
807 CRASH_BUS,
808};
809
Ken Cox12e364b2014-03-04 07:58:07 -0600810static void
Tim Sell12c957d2016-03-01 19:45:04 -0500811save_crash_message(struct controlvm_message *msg, enum crash_obj_type typ)
812{
813 u32 local_crash_msg_offset;
814 u16 local_crash_msg_count;
815
816 if (visorchannel_read(controlvm_channel,
817 offsetof(struct spar_controlvm_channel_protocol,
818 saved_crash_message_count),
819 &local_crash_msg_count, sizeof(u16)) < 0) {
820 POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
821 POSTCODE_SEVERITY_ERR);
822 return;
823 }
824
825 if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
826 POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
827 local_crash_msg_count,
828 POSTCODE_SEVERITY_ERR);
829 return;
830 }
831
832 if (visorchannel_read(controlvm_channel,
833 offsetof(struct spar_controlvm_channel_protocol,
834 saved_crash_message_offset),
835 &local_crash_msg_offset, sizeof(u32)) < 0) {
836 POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
837 POSTCODE_SEVERITY_ERR);
838 return;
839 }
840
841 if (typ == CRASH_BUS) {
842 if (visorchannel_write(controlvm_channel,
843 local_crash_msg_offset,
844 msg,
845 sizeof(struct controlvm_message)) < 0) {
846 POSTCODE_LINUX_2(SAVE_MSG_BUS_FAILURE_PC,
847 POSTCODE_SEVERITY_ERR);
848 return;
849 }
850 } else {
851 local_crash_msg_offset += sizeof(struct controlvm_message);
852 if (visorchannel_write(controlvm_channel,
853 local_crash_msg_offset,
854 msg,
855 sizeof(struct controlvm_message)) < 0) {
856 POSTCODE_LINUX_2(SAVE_MSG_DEV_FAILURE_PC,
857 POSTCODE_SEVERITY_ERR);
858 return;
859 }
860 }
861}
862
863static void
Don Zickus0274b5a2015-06-01 13:00:27 -0400864bus_responder(enum controlvm_id cmd_id,
865 struct controlvm_message_header *pending_msg_hdr,
Don Zickus3032aed2015-05-13 13:22:24 -0400866 int response)
Ken Cox12e364b2014-03-04 07:58:07 -0600867{
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500868 if (!pending_msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -0600869 return; /* no controlvm response needed */
Don Zickus0274b5a2015-06-01 13:00:27 -0400870
871 if (pending_msg_hdr->id != (u32)cmd_id)
Ken Cox12e364b2014-03-04 07:58:07 -0600872 return;
Don Zickus0274b5a2015-06-01 13:00:27 -0400873
874 controlvm_respond(pending_msg_hdr, response);
Ken Cox12e364b2014-03-04 07:58:07 -0600875}
876
877static void
Benjamin Romerfbb31f42015-03-16 13:58:16 -0400878device_changestate_responder(enum controlvm_id cmd_id,
Don Zickusa298bc02015-06-04 09:22:42 -0400879 struct visor_device *p, int response,
Benjamin Romerfbb31f42015-03-16 13:58:16 -0400880 struct spar_segment_state response_state)
Ken Cox12e364b2014-03-04 07:58:07 -0600881{
Benjamin Romer3ab47702014-10-23 14:30:31 -0400882 struct controlvm_message outmsg;
Don Zickusa298bc02015-06-04 09:22:42 -0400883 u32 bus_no = p->chipset_bus_no;
884 u32 dev_no = p->chipset_dev_no;
Ken Cox12e364b2014-03-04 07:58:07 -0600885
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500886 if (!p->pending_msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -0600887 return; /* no controlvm response needed */
Don Zickus0274b5a2015-06-01 13:00:27 -0400888 if (p->pending_msg_hdr->id != cmd_id)
Ken Cox12e364b2014-03-04 07:58:07 -0600889 return;
Ken Cox12e364b2014-03-04 07:58:07 -0600890
Don Zickus0274b5a2015-06-01 13:00:27 -0400891 controlvm_init_response(&outmsg, p->pending_msg_hdr, response);
Ken Cox12e364b2014-03-04 07:58:07 -0600892
Benjamin Romerfbb31f42015-03-16 13:58:16 -0400893 outmsg.cmd.device_change_state.bus_no = bus_no;
894 outmsg.cmd.device_change_state.dev_no = dev_no;
895 outmsg.cmd.device_change_state.state = response_state;
Ken Cox12e364b2014-03-04 07:58:07 -0600896
Benjamin Romerc3d9a222015-03-16 13:58:05 -0400897 if (!visorchannel_signalinsert(controlvm_channel,
Benjamin Romer0aca78442015-03-04 12:14:25 -0500898 CONTROLVM_QUEUE_REQUEST, &outmsg))
Ken Cox12e364b2014-03-04 07:58:07 -0600899 return;
Ken Cox12e364b2014-03-04 07:58:07 -0600900}
901
902static void
Don Zickus0274b5a2015-06-01 13:00:27 -0400903device_responder(enum controlvm_id cmd_id,
904 struct controlvm_message_header *pending_msg_hdr,
Don Zickusb4b598f2015-05-13 13:22:25 -0400905 int response)
Ken Cox12e364b2014-03-04 07:58:07 -0600906{
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -0500907 if (!pending_msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -0600908 return; /* no controlvm response needed */
Benjamin Romer0aca78442015-03-04 12:14:25 -0500909
Don Zickus0274b5a2015-06-01 13:00:27 -0400910 if (pending_msg_hdr->id != (u32)cmd_id)
Ken Cox12e364b2014-03-04 07:58:07 -0600911 return;
Benjamin Romer0aca78442015-03-04 12:14:25 -0500912
Don Zickus0274b5a2015-06-01 13:00:27 -0400913 controlvm_respond(pending_msg_hdr, response);
Ken Cox12e364b2014-03-04 07:58:07 -0600914}
915
916static void
Don Zickusd32517e2015-06-04 09:22:41 -0400917bus_epilog(struct visor_device *bus_info,
Benjamin Romer2836c6a2015-03-16 13:58:17 -0400918 u32 cmd, struct controlvm_message_header *msg_hdr,
Jes Sorensenf4c11552015-04-13 10:28:40 -0400919 int response, bool need_response)
Ken Cox12e364b2014-03-04 07:58:07 -0600920{
Don Zickus0274b5a2015-06-01 13:00:27 -0400921 struct controlvm_message_header *pmsg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -0600922
David Kershner368acb32016-03-11 17:01:43 -0500923 down(&notifier_lock);
924
Don Zickus0274b5a2015-06-01 13:00:27 -0400925 if (!bus_info) {
926 /* relying on a valid passed in response code */
927 /* be lazy and re-use msg_hdr for this failure, is this ok?? */
928 pmsg_hdr = msg_hdr;
David Kershner368acb32016-03-11 17:01:43 -0500929 goto out_respond_and_unlock;
Don Zickus0274b5a2015-06-01 13:00:27 -0400930 }
931
932 if (bus_info->pending_msg_hdr) {
933 /* only non-NULL if dev is still waiting on a response */
934 response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
935 pmsg_hdr = bus_info->pending_msg_hdr;
David Kershner368acb32016-03-11 17:01:43 -0500936 goto out_respond_and_unlock;
Don Zickus0274b5a2015-06-01 13:00:27 -0400937 }
Benjamin Romer0aca78442015-03-04 12:14:25 -0500938
Benjamin Romer2836c6a2015-03-16 13:58:17 -0400939 if (need_response) {
Don Zickus0274b5a2015-06-01 13:00:27 -0400940 pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
941 if (!pmsg_hdr) {
David Kershner368acb32016-03-11 17:01:43 -0500942 POSTCODE_LINUX_4(MALLOC_FAILURE_PC, cmd,
943 bus_info->chipset_bus_no,
944 POSTCODE_SEVERITY_ERR);
945 goto out_unlock;
Don Zickus0274b5a2015-06-01 13:00:27 -0400946 }
947
948 memcpy(pmsg_hdr, msg_hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -0400949 sizeof(struct controlvm_message_header));
Don Zickus0274b5a2015-06-01 13:00:27 -0400950 bus_info->pending_msg_hdr = pmsg_hdr;
Benjamin Romer75c1f8b2015-03-16 13:58:19 -0400951 }
Ken Cox12e364b2014-03-04 07:58:07 -0600952
Ken Cox12e364b2014-03-04 07:58:07 -0600953 if (response == CONTROLVM_RESP_SUCCESS) {
954 switch (cmd) {
955 case CONTROLVM_BUS_CREATE:
David Kershner4da33362015-05-05 18:36:39 -0400956 if (busdev_notifiers.bus_create) {
Don Zickus3032aed2015-05-13 13:22:24 -0400957 (*busdev_notifiers.bus_create) (bus_info);
David Kershner4a185e52016-04-04 23:31:39 -0400958 goto out_unlock;
Ken Cox12e364b2014-03-04 07:58:07 -0600959 }
960 break;
961 case CONTROLVM_BUS_DESTROY:
David Kershner4da33362015-05-05 18:36:39 -0400962 if (busdev_notifiers.bus_destroy) {
Don Zickus3032aed2015-05-13 13:22:24 -0400963 (*busdev_notifiers.bus_destroy) (bus_info);
David Kershner4a185e52016-04-04 23:31:39 -0400964 goto out_unlock;
Ken Cox12e364b2014-03-04 07:58:07 -0600965 }
966 break;
967 }
968 }
David Kershner368acb32016-03-11 17:01:43 -0500969
970out_respond_and_unlock:
David Kershner4a185e52016-04-04 23:31:39 -0400971 bus_responder(cmd, pmsg_hdr, response);
David Kershner368acb32016-03-11 17:01:43 -0500972
973out_unlock:
Benjamin Romer8f1947a2015-03-16 13:57:59 -0400974 up(&notifier_lock);
Ken Cox12e364b2014-03-04 07:58:07 -0600975}
976
977static void
Don Zickusa298bc02015-06-04 09:22:42 -0400978device_epilog(struct visor_device *dev_info,
Don Zickusb4b598f2015-05-13 13:22:25 -0400979 struct spar_segment_state state, u32 cmd,
Benjamin Romer2836c6a2015-03-16 13:58:17 -0400980 struct controlvm_message_header *msg_hdr, int response,
Jes Sorensenf4c11552015-04-13 10:28:40 -0400981 bool need_response, bool for_visorbus)
Ken Cox12e364b2014-03-04 07:58:07 -0600982{
Jes Sorensene82ba622015-05-05 18:35:45 -0400983 struct visorchipset_busdev_notifiers *notifiers;
Don Zickus0274b5a2015-06-01 13:00:27 -0400984 struct controlvm_message_header *pmsg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -0600985
David Kershner4da33362015-05-05 18:36:39 -0400986 notifiers = &busdev_notifiers;
987
David Kershner3cb3fa32016-04-04 23:31:38 -0400988 down(&notifier_lock);
Don Zickus0274b5a2015-06-01 13:00:27 -0400989 if (!dev_info) {
990 /* relying on a valid passed in response code */
991 /* be lazy and re-use msg_hdr for this failure, is this ok?? */
992 pmsg_hdr = msg_hdr;
David Kershner3cb3fa32016-04-04 23:31:38 -0400993 goto out_respond_and_unlock;
Don Zickus0274b5a2015-06-01 13:00:27 -0400994 }
995
996 if (dev_info->pending_msg_hdr) {
997 /* only non-NULL if dev is still waiting on a response */
998 response = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
999 pmsg_hdr = dev_info->pending_msg_hdr;
David Kershner3cb3fa32016-04-04 23:31:38 -04001000 goto out_respond_and_unlock;
Don Zickus0274b5a2015-06-01 13:00:27 -04001001 }
1002
Benjamin Romer2836c6a2015-03-16 13:58:17 -04001003 if (need_response) {
Don Zickus0274b5a2015-06-01 13:00:27 -04001004 pmsg_hdr = kzalloc(sizeof(*pmsg_hdr), GFP_KERNEL);
1005 if (!pmsg_hdr) {
1006 response = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
David Kershner3cb3fa32016-04-04 23:31:38 -04001007 goto out_respond_and_unlock;
Don Zickus0274b5a2015-06-01 13:00:27 -04001008 }
1009
1010 memcpy(pmsg_hdr, msg_hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -04001011 sizeof(struct controlvm_message_header));
Don Zickus0274b5a2015-06-01 13:00:27 -04001012 dev_info->pending_msg_hdr = pmsg_hdr;
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04001013 }
Ken Cox12e364b2014-03-04 07:58:07 -06001014
Ken Cox12e364b2014-03-04 07:58:07 -06001015 if (response >= 0) {
1016 switch (cmd) {
1017 case CONTROLVM_DEVICE_CREATE:
1018 if (notifiers->device_create) {
Don Zickusb4b598f2015-05-13 13:22:25 -04001019 (*notifiers->device_create) (dev_info);
David Kershner3cb3fa32016-04-04 23:31:38 -04001020 goto out_unlock;
Ken Cox12e364b2014-03-04 07:58:07 -06001021 }
1022 break;
1023 case CONTROLVM_DEVICE_CHANGESTATE:
1024 /* ServerReady / ServerRunning / SegmentStateRunning */
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -04001025 if (state.alive == segment_state_running.alive &&
1026 state.operating ==
1027 segment_state_running.operating) {
Ken Cox12e364b2014-03-04 07:58:07 -06001028 if (notifiers->device_resume) {
Don Zickusb4b598f2015-05-13 13:22:25 -04001029 (*notifiers->device_resume) (dev_info);
David Kershner3cb3fa32016-04-04 23:31:38 -04001030 goto out_unlock;
Ken Cox12e364b2014-03-04 07:58:07 -06001031 }
1032 }
1033 /* ServerNotReady / ServerLost / SegmentStateStandby */
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -04001034 else if (state.alive == segment_state_standby.alive &&
Benjamin Romer3f833b52014-10-23 14:30:12 -04001035 state.operating ==
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -04001036 segment_state_standby.operating) {
Ken Cox12e364b2014-03-04 07:58:07 -06001037 /* technically this is standby case
1038 * where server is lost
1039 */
1040 if (notifiers->device_pause) {
Don Zickusb4b598f2015-05-13 13:22:25 -04001041 (*notifiers->device_pause) (dev_info);
David Kershner3cb3fa32016-04-04 23:31:38 -04001042 goto out_unlock;
Ken Cox12e364b2014-03-04 07:58:07 -06001043 }
Ken Cox12e364b2014-03-04 07:58:07 -06001044 }
1045 break;
1046 case CONTROLVM_DEVICE_DESTROY:
1047 if (notifiers->device_destroy) {
Don Zickusb4b598f2015-05-13 13:22:25 -04001048 (*notifiers->device_destroy) (dev_info);
David Kershner3cb3fa32016-04-04 23:31:38 -04001049 goto out_unlock;
Ken Cox12e364b2014-03-04 07:58:07 -06001050 }
1051 break;
1052 }
1053 }
David Kershner3cb3fa32016-04-04 23:31:38 -04001054
1055out_respond_and_unlock:
1056 device_responder(cmd, pmsg_hdr, response);
1057
1058out_unlock:
Benjamin Romer8f1947a2015-03-16 13:57:59 -04001059 up(&notifier_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001060}
1061
1062static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001063bus_create(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001064{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001065 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -04001066 u32 bus_no = cmd->create_bus.bus_no;
Ken Cox12e364b2014-03-04 07:58:07 -06001067 int rc = CONTROLVM_RESP_SUCCESS;
Don Zickusd32517e2015-06-04 09:22:41 -04001068 struct visor_device *bus_info;
Don Zickusb32c4992015-06-01 13:00:26 -04001069 struct visorchannel *visorchannel;
Ken Cox12e364b2014-03-04 07:58:07 -06001070
Don Zickusd32517e2015-06-04 09:22:41 -04001071 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001072 if (bus_info && (bus_info->state.created == 1)) {
1073 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001074 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001075 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
David Kershner9fd04062016-03-11 17:01:42 -05001076 goto out_bus_epilog;
Ken Cox12e364b2014-03-04 07:58:07 -06001077 }
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001078 bus_info = kzalloc(sizeof(*bus_info), GFP_KERNEL);
1079 if (!bus_info) {
1080 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001081 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001082 rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
David Kershner9fd04062016-03-11 17:01:42 -05001083 goto out_bus_epilog;
Ken Cox12e364b2014-03-04 07:58:07 -06001084 }
1085
David Kershner4abce832015-06-04 09:22:49 -04001086 INIT_LIST_HEAD(&bus_info->list_all);
Don Zickusd32517e2015-06-04 09:22:41 -04001087 bus_info->chipset_bus_no = bus_no;
1088 bus_info->chipset_dev_no = BUS_ROOT_DEVICE;
Ken Cox12e364b2014-03-04 07:58:07 -06001089
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001090 POSTCODE_LINUX_3(BUS_CREATE_ENTRY_PC, bus_no, POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -06001091
Don Zickusb32c4992015-06-01 13:00:26 -04001092 visorchannel = visorchannel_create(cmd->create_bus.channel_addr,
1093 cmd->create_bus.channel_bytes,
1094 GFP_KERNEL,
1095 cmd->create_bus.bus_data_type_uuid);
1096
1097 if (!visorchannel) {
1098 POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no,
1099 POSTCODE_SEVERITY_ERR);
1100 rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
1101 kfree(bus_info);
1102 bus_info = NULL;
David Kershner9fd04062016-03-11 17:01:42 -05001103 goto out_bus_epilog;
Don Zickusb32c4992015-06-01 13:00:26 -04001104 }
1105 bus_info->visorchannel = visorchannel;
Tim Sell12c957d2016-03-01 19:45:04 -05001106 if (uuid_le_cmp(cmd->create_bus.bus_inst_uuid, spar_siovm_uuid) == 0) {
1107 dump_vhba_bus = bus_no;
1108 save_crash_message(inmsg, CRASH_BUS);
1109 }
Ken Cox12e364b2014-03-04 07:58:07 -06001110
Benjamin Romer6c5fed32015-03-16 13:58:20 -04001111 POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus_no, POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -06001112
David Kershner9fd04062016-03-11 17:01:42 -05001113out_bus_epilog:
Don Zickus3032aed2015-05-13 13:22:24 -04001114 bus_epilog(bus_info, CONTROLVM_BUS_CREATE, &inmsg->hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -04001115 rc, inmsg->hdr.flags.response_expected == 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001116}
1117
1118static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001119bus_destroy(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001120{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001121 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -04001122 u32 bus_no = cmd->destroy_bus.bus_no;
Don Zickusd32517e2015-06-04 09:22:41 -04001123 struct visor_device *bus_info;
Ken Cox12e364b2014-03-04 07:58:07 -06001124 int rc = CONTROLVM_RESP_SUCCESS;
1125
Don Zickusd32517e2015-06-04 09:22:41 -04001126 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romerdff54cd2015-03-16 13:58:21 -04001127 if (!bus_info)
Ken Cox22ad57b2014-03-19 13:06:25 -05001128 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
Benjamin Romerdff54cd2015-03-16 13:58:21 -04001129 else if (bus_info->state.created == 0)
Ken Cox22ad57b2014-03-19 13:06:25 -05001130 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
Ken Cox12e364b2014-03-04 07:58:07 -06001131
Don Zickus3032aed2015-05-13 13:22:24 -04001132 bus_epilog(bus_info, CONTROLVM_BUS_DESTROY, &inmsg->hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -04001133 rc, inmsg->hdr.flags.response_expected == 1);
Don Zickusd32517e2015-06-04 09:22:41 -04001134
1135 /* bus_info is freed as part of the busdevice_release function */
Ken Cox12e364b2014-03-04 07:58:07 -06001136}
1137
1138static void
Benjamin Romer317d9612015-03-16 13:57:51 -04001139bus_configure(struct controlvm_message *inmsg,
1140 struct parser_context *parser_ctx)
Ken Cox12e364b2014-03-04 07:58:07 -06001141{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001142 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensene82ba622015-05-05 18:35:45 -04001143 u32 bus_no;
Don Zickusd32517e2015-06-04 09:22:41 -04001144 struct visor_device *bus_info;
Ken Cox12e364b2014-03-04 07:58:07 -06001145 int rc = CONTROLVM_RESP_SUCCESS;
Ken Cox12e364b2014-03-04 07:58:07 -06001146
Benjamin Romer654bada2015-03-16 13:58:22 -04001147 bus_no = cmd->configure_bus.bus_no;
1148 POSTCODE_LINUX_3(BUS_CONFIGURE_ENTRY_PC, bus_no,
1149 POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -06001150
Don Zickusd32517e2015-06-04 09:22:41 -04001151 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romer654bada2015-03-16 13:58:22 -04001152 if (!bus_info) {
1153 POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001154 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001155 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
Benjamin Romer654bada2015-03-16 13:58:22 -04001156 } else if (bus_info->state.created == 0) {
1157 POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001158 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001159 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
Erik Arfvidsone4a3dd32016-02-08 10:41:46 -05001160 } else if (bus_info->pending_msg_hdr) {
Benjamin Romer654bada2015-03-16 13:58:22 -04001161 POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001162 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001163 rc = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT;
Benjamin Romer654bada2015-03-16 13:58:22 -04001164 } else {
Tim Sella07d7c32016-04-04 23:31:12 -04001165 visorchannel_set_clientpartition
1166 (bus_info->visorchannel,
1167 cmd->configure_bus.guest_handle);
Benjamin Romer654bada2015-03-16 13:58:22 -04001168 bus_info->partition_uuid = parser_id_get(parser_ctx);
1169 parser_param_start(parser_ctx, PARSERSTRING_NAME);
1170 bus_info->name = parser_string_get(parser_ctx);
1171
Benjamin Romer654bada2015-03-16 13:58:22 -04001172 POSTCODE_LINUX_3(BUS_CONFIGURE_EXIT_PC, bus_no,
1173 POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -06001174 }
Don Zickus3032aed2015-05-13 13:22:24 -04001175 bus_epilog(bus_info, CONTROLVM_BUS_CONFIGURE, &inmsg->hdr,
Benjamin Romer98d7b592014-10-23 14:30:26 -04001176 rc, inmsg->hdr.flags.response_expected == 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001177}
1178
1179static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001180my_device_create(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001181{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001182 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -04001183 u32 bus_no = cmd->create_device.bus_no;
1184 u32 dev_no = cmd->create_device.dev_no;
Don Zickusa298bc02015-06-04 09:22:42 -04001185 struct visor_device *dev_info = NULL;
Don Zickusd32517e2015-06-04 09:22:41 -04001186 struct visor_device *bus_info;
Don Zickusb32c4992015-06-01 13:00:26 -04001187 struct visorchannel *visorchannel;
Ken Cox12e364b2014-03-04 07:58:07 -06001188 int rc = CONTROLVM_RESP_SUCCESS;
1189
Don Zickusa298bc02015-06-04 09:22:42 -04001190 bus_info = visorbus_get_device_by_id(bus_no, BUS_ROOT_DEVICE, NULL);
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001191 if (!bus_info) {
1192 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001193 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001194 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
David Kershnerc6af7a92016-03-11 17:01:44 -05001195 goto out_respond;
Ken Cox12e364b2014-03-04 07:58:07 -06001196 }
Don Zickusa298bc02015-06-04 09:22:42 -04001197
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001198 if (bus_info->state.created == 0) {
1199 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001200 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001201 rc = -CONTROLVM_RESP_ERROR_BUS_INVALID;
David Kershnerc6af7a92016-03-11 17:01:44 -05001202 goto out_respond;
Ken Cox12e364b2014-03-04 07:58:07 -06001203 }
Don Zickusa298bc02015-06-04 09:22:42 -04001204
1205 dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
1206 if (dev_info && (dev_info->state.created == 1)) {
1207 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
1208 POSTCODE_SEVERITY_ERR);
1209 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
David Kershnerc6af7a92016-03-11 17:01:44 -05001210 goto out_respond;
Don Zickusa298bc02015-06-04 09:22:42 -04001211 }
1212
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001213 dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
1214 if (!dev_info) {
1215 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001216 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001217 rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
David Kershnerc6af7a92016-03-11 17:01:44 -05001218 goto out_respond;
Ken Cox12e364b2014-03-04 07:58:07 -06001219 }
Andreea-Cristina Bernat97a84f12014-03-14 04:20:06 +02001220
Don Zickusa298bc02015-06-04 09:22:42 -04001221 dev_info->chipset_bus_no = bus_no;
1222 dev_info->chipset_dev_no = dev_no;
1223 dev_info->inst = cmd->create_device.dev_inst_uuid;
1224
1225 /* not sure where the best place to set the 'parent' */
1226 dev_info->device.parent = &bus_info->device;
1227
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001228 POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001229 POSTCODE_SEVERITY_INFO);
1230
David Kershnera3ef1a82015-07-14 14:43:29 -04001231 visorchannel =
1232 visorchannel_create_with_lock(cmd->create_device.channel_addr,
1233 cmd->create_device.channel_bytes,
1234 GFP_KERNEL,
1235 cmd->create_device.data_type_uuid);
Don Zickusb32c4992015-06-01 13:00:26 -04001236
1237 if (!visorchannel) {
1238 POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
1239 POSTCODE_SEVERITY_ERR);
1240 rc = -CONTROLVM_RESP_ERROR_KMALLOC_FAILED;
1241 kfree(dev_info);
1242 dev_info = NULL;
David Kershnerc6af7a92016-03-11 17:01:44 -05001243 goto out_respond;
Don Zickusb32c4992015-06-01 13:00:26 -04001244 }
1245 dev_info->visorchannel = visorchannel;
1246 dev_info->channel_type_guid = cmd->create_device.data_type_uuid;
Tim Sell12c957d2016-03-01 19:45:04 -05001247 if (uuid_le_cmp(cmd->create_device.data_type_uuid,
1248 spar_vhba_channel_protocol_uuid) == 0)
1249 save_crash_message(inmsg, CRASH_DEV);
1250
Benjamin Romerc60c8e22015-03-16 13:58:23 -04001251 POSTCODE_LINUX_4(DEVICE_CREATE_EXIT_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001252 POSTCODE_SEVERITY_INFO);
David Kershnerc6af7a92016-03-11 17:01:44 -05001253out_respond:
Don Zickusb4b598f2015-05-13 13:22:25 -04001254 device_epilog(dev_info, segment_state_running,
Ken Cox12e364b2014-03-04 07:58:07 -06001255 CONTROLVM_DEVICE_CREATE, &inmsg->hdr, rc,
David Kershner4da33362015-05-05 18:36:39 -04001256 inmsg->hdr.flags.response_expected == 1, 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001257}
1258
1259static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001260my_device_changestate(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001261{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001262 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -04001263 u32 bus_no = cmd->device_change_state.bus_no;
1264 u32 dev_no = cmd->device_change_state.dev_no;
Benjamin Romer2ea51172014-10-23 14:30:25 -04001265 struct spar_segment_state state = cmd->device_change_state.state;
Don Zickusa298bc02015-06-04 09:22:42 -04001266 struct visor_device *dev_info;
Ken Cox12e364b2014-03-04 07:58:07 -06001267 int rc = CONTROLVM_RESP_SUCCESS;
1268
Don Zickusa298bc02015-06-04 09:22:42 -04001269 dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
Benjamin Romer0278a902015-03-16 13:58:24 -04001270 if (!dev_info) {
1271 POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001272 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001273 rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
Benjamin Romer0278a902015-03-16 13:58:24 -04001274 } else if (dev_info->state.created == 0) {
1275 POSTCODE_LINUX_4(DEVICE_CHANGESTATE_FAILURE_PC, dev_no, bus_no,
Ken Cox12e364b2014-03-04 07:58:07 -06001276 POSTCODE_SEVERITY_ERR);
Ken Cox22ad57b2014-03-19 13:06:25 -05001277 rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
Ken Cox12e364b2014-03-04 07:58:07 -06001278 }
Benjamin Romer0278a902015-03-16 13:58:24 -04001279 if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info)
Don Zickusb4b598f2015-05-13 13:22:25 -04001280 device_epilog(dev_info, state,
Benjamin Romer0278a902015-03-16 13:58:24 -04001281 CONTROLVM_DEVICE_CHANGESTATE, &inmsg->hdr, rc,
David Kershner4da33362015-05-05 18:36:39 -04001282 inmsg->hdr.flags.response_expected == 1, 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001283}
1284
1285static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001286my_device_destroy(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001287{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001288 struct controlvm_message_packet *cmd = &inmsg->cmd;
Jes Sorensen52063ec2015-04-13 10:28:41 -04001289 u32 bus_no = cmd->destroy_device.bus_no;
1290 u32 dev_no = cmd->destroy_device.dev_no;
Don Zickusa298bc02015-06-04 09:22:42 -04001291 struct visor_device *dev_info;
Ken Cox12e364b2014-03-04 07:58:07 -06001292 int rc = CONTROLVM_RESP_SUCCESS;
1293
Don Zickusa298bc02015-06-04 09:22:42 -04001294 dev_info = visorbus_get_device_by_id(bus_no, dev_no, NULL);
Benjamin Romer61715c82015-03-16 13:58:25 -04001295 if (!dev_info)
Ken Cox22ad57b2014-03-19 13:06:25 -05001296 rc = -CONTROLVM_RESP_ERROR_DEVICE_INVALID;
Benjamin Romer61715c82015-03-16 13:58:25 -04001297 else if (dev_info->state.created == 0)
Ken Cox22ad57b2014-03-19 13:06:25 -05001298 rc = -CONTROLVM_RESP_ERROR_ALREADY_DONE;
Ken Cox12e364b2014-03-04 07:58:07 -06001299
Benjamin Romer61715c82015-03-16 13:58:25 -04001300 if ((rc >= CONTROLVM_RESP_SUCCESS) && dev_info)
Don Zickusb4b598f2015-05-13 13:22:25 -04001301 device_epilog(dev_info, segment_state_running,
Ken Cox12e364b2014-03-04 07:58:07 -06001302 CONTROLVM_DEVICE_DESTROY, &inmsg->hdr, rc,
David Kershner4da33362015-05-05 18:36:39 -04001303 inmsg->hdr.flags.response_expected == 1, 1);
Ken Cox12e364b2014-03-04 07:58:07 -06001304}
1305
1306/* When provided with the physical address of the controlvm channel
1307 * (phys_addr), the offset to the payload area we need to manage
1308 * (offset), and the size of this payload area (bytes), fills in the
Jes Sorensenf4c11552015-04-13 10:28:40 -04001309 * controlvm_payload_info struct. Returns true for success or false
Ken Cox12e364b2014-03-04 07:58:07 -06001310 * for failure.
1311 */
1312static int
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001313initialize_controlvm_payload_info(u64 phys_addr, u64 offset, u32 bytes,
Jes Sorensenc1f834e2015-04-13 10:28:39 -04001314 struct visor_controlvm_payload_info *info)
Ken Cox12e364b2014-03-04 07:58:07 -06001315{
Dan Williams3103dc02015-08-10 23:07:06 -04001316 u8 *payload = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06001317
David Kershnerdde29992016-03-11 17:01:39 -05001318 if (!info)
1319 return -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID;
1320
Jes Sorensenc1f834e2015-04-13 10:28:39 -04001321 memset(info, 0, sizeof(struct visor_controlvm_payload_info));
David Kershnerdde29992016-03-11 17:01:39 -05001322 if ((offset == 0) || (bytes == 0))
1323 return -CONTROLVM_RESP_ERROR_PAYLOAD_INVALID;
1324
Dan Williams3103dc02015-08-10 23:07:06 -04001325 payload = memremap(phys_addr + offset, bytes, MEMREMAP_WB);
David Kershnerdde29992016-03-11 17:01:39 -05001326 if (!payload)
1327 return -CONTROLVM_RESP_ERROR_IOREMAP_FAILED;
Ken Cox12e364b2014-03-04 07:58:07 -06001328
1329 info->offset = offset;
1330 info->bytes = bytes;
1331 info->ptr = payload;
Ken Cox12e364b2014-03-04 07:58:07 -06001332
David Kershnerdde29992016-03-11 17:01:39 -05001333 return CONTROLVM_RESP_SUCCESS;
Ken Cox12e364b2014-03-04 07:58:07 -06001334}
1335
1336static void
Jes Sorensenc1f834e2015-04-13 10:28:39 -04001337destroy_controlvm_payload_info(struct visor_controlvm_payload_info *info)
Ken Cox12e364b2014-03-04 07:58:07 -06001338{
Benjamin Romer597c3382015-03-16 13:58:27 -04001339 if (info->ptr) {
Dan Williams3103dc02015-08-10 23:07:06 -04001340 memunmap(info->ptr);
Ken Cox12e364b2014-03-04 07:58:07 -06001341 info->ptr = NULL;
1342 }
Jes Sorensenc1f834e2015-04-13 10:28:39 -04001343 memset(info, 0, sizeof(struct visor_controlvm_payload_info));
Ken Cox12e364b2014-03-04 07:58:07 -06001344}
1345
1346static void
1347initialize_controlvm_payload(void)
1348{
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001349 u64 phys_addr = visorchannel_get_physaddr(controlvm_channel);
Benjamin Romercafefc02015-03-16 13:58:28 -04001350 u64 payload_offset = 0;
1351 u32 payload_bytes = 0;
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001352
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001353 if (visorchannel_read(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04001354 offsetof(struct spar_controlvm_channel_protocol,
1355 request_payload_offset),
Benjamin Romercafefc02015-03-16 13:58:28 -04001356 &payload_offset, sizeof(payload_offset)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001357 POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
1358 POSTCODE_SEVERITY_ERR);
1359 return;
1360 }
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001361 if (visorchannel_read(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04001362 offsetof(struct spar_controlvm_channel_protocol,
1363 request_payload_bytes),
Benjamin Romercafefc02015-03-16 13:58:28 -04001364 &payload_bytes, sizeof(payload_bytes)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001365 POSTCODE_LINUX_2(CONTROLVM_INIT_FAILURE_PC,
1366 POSTCODE_SEVERITY_ERR);
1367 return;
1368 }
1369 initialize_controlvm_payload_info(phys_addr,
Benjamin Romercafefc02015-03-16 13:58:28 -04001370 payload_offset, payload_bytes,
Benjamin Romer84982fb2015-03-16 13:58:07 -04001371 &controlvm_payload_info);
Ken Cox12e364b2014-03-04 07:58:07 -06001372}
1373
1374/* Send ACTION=online for DEVPATH=/sys/devices/platform/visorchipset.
1375 * Returns CONTROLVM_RESP_xxx code.
1376 */
Jes Sorensend3368a52015-05-13 13:21:57 -04001377static int
Ken Cox12e364b2014-03-04 07:58:07 -06001378visorchipset_chipset_ready(void)
1379{
Benjamin Romereb34e872015-03-16 13:58:45 -04001380 kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_ONLINE);
Ken Cox12e364b2014-03-04 07:58:07 -06001381 return CONTROLVM_RESP_SUCCESS;
1382}
Ken Cox12e364b2014-03-04 07:58:07 -06001383
Jes Sorensend3368a52015-05-13 13:21:57 -04001384static int
Ken Cox12e364b2014-03-04 07:58:07 -06001385visorchipset_chipset_selftest(void)
1386{
1387 char env_selftest[20];
1388 char *envp[] = { env_selftest, NULL };
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001389
Ken Cox12e364b2014-03-04 07:58:07 -06001390 sprintf(env_selftest, "SPARSP_SELFTEST=%d", 1);
Benjamin Romereb34e872015-03-16 13:58:45 -04001391 kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE,
Ken Cox12e364b2014-03-04 07:58:07 -06001392 envp);
1393 return CONTROLVM_RESP_SUCCESS;
1394}
Ken Cox12e364b2014-03-04 07:58:07 -06001395
1396/* Send ACTION=offline for DEVPATH=/sys/devices/platform/visorchipset.
1397 * Returns CONTROLVM_RESP_xxx code.
1398 */
Jes Sorensend3368a52015-05-13 13:21:57 -04001399static int
Ken Cox12e364b2014-03-04 07:58:07 -06001400visorchipset_chipset_notready(void)
1401{
Benjamin Romereb34e872015-03-16 13:58:45 -04001402 kobject_uevent(&visorchipset_platform_device.dev.kobj, KOBJ_OFFLINE);
Ken Cox12e364b2014-03-04 07:58:07 -06001403 return CONTROLVM_RESP_SUCCESS;
1404}
Ken Cox12e364b2014-03-04 07:58:07 -06001405
1406static void
Benjamin Romer77a04492015-03-16 13:58:47 -04001407chipset_ready(struct controlvm_message_header *msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -06001408{
1409 int rc = visorchipset_chipset_ready();
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001410
Ken Cox12e364b2014-03-04 07:58:07 -06001411 if (rc != CONTROLVM_RESP_SUCCESS)
1412 rc = -rc;
Erik Arfvidson260d8992016-04-19 08:11:52 -04001413 if (msg_hdr->flags.response_expected)
Benjamin Romer77a04492015-03-16 13:58:47 -04001414 controlvm_respond(msg_hdr, rc);
Ken Cox12e364b2014-03-04 07:58:07 -06001415}
1416
1417static void
Benjamin Romer77a04492015-03-16 13:58:47 -04001418chipset_selftest(struct controlvm_message_header *msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -06001419{
1420 int rc = visorchipset_chipset_selftest();
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001421
Ken Cox12e364b2014-03-04 07:58:07 -06001422 if (rc != CONTROLVM_RESP_SUCCESS)
1423 rc = -rc;
Benjamin Romer77a04492015-03-16 13:58:47 -04001424 if (msg_hdr->flags.response_expected)
1425 controlvm_respond(msg_hdr, rc);
Ken Cox12e364b2014-03-04 07:58:07 -06001426}
1427
1428static void
Benjamin Romer77a04492015-03-16 13:58:47 -04001429chipset_notready(struct controlvm_message_header *msg_hdr)
Ken Cox12e364b2014-03-04 07:58:07 -06001430{
1431 int rc = visorchipset_chipset_notready();
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001432
Ken Cox12e364b2014-03-04 07:58:07 -06001433 if (rc != CONTROLVM_RESP_SUCCESS)
1434 rc = -rc;
Benjamin Romer77a04492015-03-16 13:58:47 -04001435 if (msg_hdr->flags.response_expected)
1436 controlvm_respond(msg_hdr, rc);
Ken Cox12e364b2014-03-04 07:58:07 -06001437}
1438
1439/* This is your "one-stop" shop for grabbing the next message from the
1440 * CONTROLVM_QUEUE_EVENT queue in the controlvm channel.
1441 */
Jes Sorensenf4c11552015-04-13 10:28:40 -04001442static bool
Benjamin Romer3ab47702014-10-23 14:30:31 -04001443read_controlvm_event(struct controlvm_message *msg)
Ken Cox12e364b2014-03-04 07:58:07 -06001444{
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001445 if (visorchannel_signalremove(controlvm_channel,
Ken Cox12e364b2014-03-04 07:58:07 -06001446 CONTROLVM_QUEUE_EVENT, msg)) {
1447 /* got a message */
Benjamin Romer0aca78442015-03-04 12:14:25 -05001448 if (msg->hdr.flags.test_message == 1)
Jes Sorensenf4c11552015-04-13 10:28:40 -04001449 return false;
1450 return true;
Ken Cox12e364b2014-03-04 07:58:07 -06001451 }
Jes Sorensenf4c11552015-04-13 10:28:40 -04001452 return false;
Ken Cox12e364b2014-03-04 07:58:07 -06001453}
1454
1455/*
1456 * The general parahotplug flow works as follows. The visorchipset
1457 * driver receives a DEVICE_CHANGESTATE message from Command
1458 * specifying a physical device to enable or disable. The CONTROLVM
1459 * message handler calls parahotplug_process_message, which then adds
1460 * the message to a global list and kicks off a udev event which
1461 * causes a user level script to enable or disable the specified
1462 * device. The udev script then writes to
1463 * /proc/visorchipset/parahotplug, which causes parahotplug_proc_write
1464 * to get called, at which point the appropriate CONTROLVM message is
1465 * retrieved from the list and responded to.
1466 */
1467
1468#define PARAHOTPLUG_TIMEOUT_MS 2000
1469
1470/*
1471 * Generate unique int to match an outstanding CONTROLVM message with a
1472 * udev script /proc response
1473 */
1474static int
1475parahotplug_next_id(void)
1476{
1477 static atomic_t id = ATOMIC_INIT(0);
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001478
Ken Cox12e364b2014-03-04 07:58:07 -06001479 return atomic_inc_return(&id);
1480}
1481
1482/*
1483 * Returns the time (in jiffies) when a CONTROLVM message on the list
1484 * should expire -- PARAHOTPLUG_TIMEOUT_MS in the future
1485 */
1486static unsigned long
1487parahotplug_next_expiration(void)
1488{
Nicholas Mc Guire2cc1a1b2015-01-31 12:02:08 +01001489 return jiffies + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS);
Ken Cox12e364b2014-03-04 07:58:07 -06001490}
1491
1492/*
1493 * Create a parahotplug_request, which is basically a wrapper for a
1494 * CONTROLVM_MESSAGE that we can stick on a list
1495 */
1496static struct parahotplug_request *
Benjamin Romer3ab47702014-10-23 14:30:31 -04001497parahotplug_request_create(struct controlvm_message *msg)
Ken Cox12e364b2014-03-04 07:58:07 -06001498{
Quentin Lambertea0dcfc2015-02-10 15:12:07 +01001499 struct parahotplug_request *req;
1500
Benjamin Romer6a55e3c2015-03-16 13:58:30 -04001501 req = kmalloc(sizeof(*req), GFP_KERNEL | __GFP_NORETRY);
Benjamin Romer38f736e2015-03-16 13:58:13 -04001502 if (!req)
Ken Cox12e364b2014-03-04 07:58:07 -06001503 return NULL;
1504
1505 req->id = parahotplug_next_id();
1506 req->expiration = parahotplug_next_expiration();
1507 req->msg = *msg;
1508
1509 return req;
1510}
1511
1512/*
1513 * Free a parahotplug_request.
1514 */
1515static void
1516parahotplug_request_destroy(struct parahotplug_request *req)
1517{
1518 kfree(req);
1519}
1520
1521/*
1522 * Cause uevent to run the user level script to do the disable/enable
1523 * specified in (the CONTROLVM message in) the specified
1524 * parahotplug_request
1525 */
1526static void
1527parahotplug_request_kickoff(struct parahotplug_request *req)
1528{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001529 struct controlvm_message_packet *cmd = &req->msg.cmd;
Ken Cox12e364b2014-03-04 07:58:07 -06001530 char env_cmd[40], env_id[40], env_state[40], env_bus[40], env_dev[40],
1531 env_func[40];
1532 char *envp[] = {
1533 env_cmd, env_id, env_state, env_bus, env_dev, env_func, NULL
1534 };
1535
1536 sprintf(env_cmd, "SPAR_PARAHOTPLUG=1");
1537 sprintf(env_id, "SPAR_PARAHOTPLUG_ID=%d", req->id);
1538 sprintf(env_state, "SPAR_PARAHOTPLUG_STATE=%d",
Benjamin Romer2ea51172014-10-23 14:30:25 -04001539 cmd->device_change_state.state.active);
Ken Cox12e364b2014-03-04 07:58:07 -06001540 sprintf(env_bus, "SPAR_PARAHOTPLUG_BUS=%d",
Benjamin Romer2ea51172014-10-23 14:30:25 -04001541 cmd->device_change_state.bus_no);
Ken Cox12e364b2014-03-04 07:58:07 -06001542 sprintf(env_dev, "SPAR_PARAHOTPLUG_DEVICE=%d",
Benjamin Romer2ea51172014-10-23 14:30:25 -04001543 cmd->device_change_state.dev_no >> 3);
Ken Cox12e364b2014-03-04 07:58:07 -06001544 sprintf(env_func, "SPAR_PARAHOTPLUG_FUNCTION=%d",
Benjamin Romer2ea51172014-10-23 14:30:25 -04001545 cmd->device_change_state.dev_no & 0x7);
Ken Cox12e364b2014-03-04 07:58:07 -06001546
Benjamin Romereb34e872015-03-16 13:58:45 -04001547 kobject_uevent_env(&visorchipset_platform_device.dev.kobj, KOBJ_CHANGE,
Ken Cox12e364b2014-03-04 07:58:07 -06001548 envp);
1549}
1550
1551/*
1552 * Remove any request from the list that's been on there too long and
1553 * respond with an error.
1554 */
1555static void
1556parahotplug_process_list(void)
1557{
Jes Sorensene82ba622015-05-05 18:35:45 -04001558 struct list_head *pos;
1559 struct list_head *tmp;
Ken Cox12e364b2014-03-04 07:58:07 -06001560
Benjamin Romerddf5de52015-03-16 13:58:41 -04001561 spin_lock(&parahotplug_request_list_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001562
Benjamin Romerddf5de52015-03-16 13:58:41 -04001563 list_for_each_safe(pos, tmp, &parahotplug_request_list) {
Ken Cox12e364b2014-03-04 07:58:07 -06001564 struct parahotplug_request *req =
1565 list_entry(pos, struct parahotplug_request, list);
Benjamin Romer55b33412015-03-16 13:58:29 -04001566
1567 if (!time_after_eq(jiffies, req->expiration))
1568 continue;
1569
1570 list_del(pos);
1571 if (req->msg.hdr.flags.response_expected)
1572 controlvm_respond_physdev_changestate(
1573 &req->msg.hdr,
1574 CONTROLVM_RESP_ERROR_DEVICE_UDEV_TIMEOUT,
1575 req->msg.cmd.device_change_state.state);
1576 parahotplug_request_destroy(req);
Ken Cox12e364b2014-03-04 07:58:07 -06001577 }
1578
Benjamin Romerddf5de52015-03-16 13:58:41 -04001579 spin_unlock(&parahotplug_request_list_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001580}
1581
1582/*
1583 * Called from the /proc handler, which means the user script has
1584 * finished the enable/disable. Find the matching identifier, and
1585 * respond to the CONTROLVM message with success.
1586 */
1587static int
Benjamin Romerb06bdf72014-07-31 12:00:49 -04001588parahotplug_request_complete(int id, u16 active)
Ken Cox12e364b2014-03-04 07:58:07 -06001589{
Jes Sorensene82ba622015-05-05 18:35:45 -04001590 struct list_head *pos;
1591 struct list_head *tmp;
Ken Cox12e364b2014-03-04 07:58:07 -06001592
Benjamin Romerddf5de52015-03-16 13:58:41 -04001593 spin_lock(&parahotplug_request_list_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001594
1595 /* Look for a request matching "id". */
Benjamin Romerddf5de52015-03-16 13:58:41 -04001596 list_for_each_safe(pos, tmp, &parahotplug_request_list) {
Ken Cox12e364b2014-03-04 07:58:07 -06001597 struct parahotplug_request *req =
1598 list_entry(pos, struct parahotplug_request, list);
1599 if (req->id == id) {
1600 /* Found a match. Remove it from the list and
1601 * respond.
1602 */
1603 list_del(pos);
Benjamin Romerddf5de52015-03-16 13:58:41 -04001604 spin_unlock(&parahotplug_request_list_lock);
Benjamin Romer2ea51172014-10-23 14:30:25 -04001605 req->msg.cmd.device_change_state.state.active = active;
Benjamin Romer98d7b592014-10-23 14:30:26 -04001606 if (req->msg.hdr.flags.response_expected)
Ken Cox12e364b2014-03-04 07:58:07 -06001607 controlvm_respond_physdev_changestate(
1608 &req->msg.hdr, CONTROLVM_RESP_SUCCESS,
Benjamin Romer2ea51172014-10-23 14:30:25 -04001609 req->msg.cmd.device_change_state.state);
Ken Cox12e364b2014-03-04 07:58:07 -06001610 parahotplug_request_destroy(req);
1611 return 0;
1612 }
1613 }
1614
Benjamin Romerddf5de52015-03-16 13:58:41 -04001615 spin_unlock(&parahotplug_request_list_lock);
Erik Arfvidson119296e2016-05-13 23:17:20 -04001616 return -EINVAL;
Ken Cox12e364b2014-03-04 07:58:07 -06001617}
1618
1619/*
1620 * Enables or disables a PCI device by kicking off a udev script
1621 */
Ken Coxbd5b9b32014-03-13 15:39:22 -05001622static void
Benjamin Romer3ab47702014-10-23 14:30:31 -04001623parahotplug_process_message(struct controlvm_message *inmsg)
Ken Cox12e364b2014-03-04 07:58:07 -06001624{
1625 struct parahotplug_request *req;
1626
1627 req = parahotplug_request_create(inmsg);
1628
Benjamin Romer38f736e2015-03-16 13:58:13 -04001629 if (!req)
Ken Cox12e364b2014-03-04 07:58:07 -06001630 return;
Ken Cox12e364b2014-03-04 07:58:07 -06001631
Benjamin Romer2ea51172014-10-23 14:30:25 -04001632 if (inmsg->cmd.device_change_state.state.active) {
Ken Cox12e364b2014-03-04 07:58:07 -06001633 /* For enable messages, just respond with success
1634 * right away. This is a bit of a hack, but there are
1635 * issues with the early enable messages we get (with
1636 * either the udev script not detecting that the device
1637 * is up, or not getting called at all). Fortunately
1638 * the messages that get lost don't matter anyway, as
1639 * devices are automatically enabled at
1640 * initialization.
1641 */
1642 parahotplug_request_kickoff(req);
Tim Sella07d7c32016-04-04 23:31:12 -04001643 controlvm_respond_physdev_changestate
1644 (&inmsg->hdr,
1645 CONTROLVM_RESP_SUCCESS,
1646 inmsg->cmd.device_change_state.state);
Ken Cox12e364b2014-03-04 07:58:07 -06001647 parahotplug_request_destroy(req);
1648 } else {
1649 /* For disable messages, add the request to the
1650 * request list before kicking off the udev script. It
1651 * won't get responded to until the script has
1652 * indicated it's done.
1653 */
Benjamin Romerddf5de52015-03-16 13:58:41 -04001654 spin_lock(&parahotplug_request_list_lock);
1655 list_add_tail(&req->list, &parahotplug_request_list);
1656 spin_unlock(&parahotplug_request_list_lock);
Ken Cox12e364b2014-03-04 07:58:07 -06001657
1658 parahotplug_request_kickoff(req);
1659 }
1660}
1661
Ken Cox12e364b2014-03-04 07:58:07 -06001662/* Process a controlvm message.
1663 * Return result:
Prarit Bhargava779d0752015-05-05 18:37:01 -04001664 * false - this function will return false only in the case where the
Ken Cox12e364b2014-03-04 07:58:07 -06001665 * controlvm message was NOT processed, but processing must be
1666 * retried before reading the next controlvm message; a
1667 * scenario where this can occur is when we need to throttle
1668 * the allocation of memory in which to copy out controlvm
1669 * payload data
Jes Sorensenf4c11552015-04-13 10:28:40 -04001670 * true - processing of the controlvm message completed,
Ken Cox12e364b2014-03-04 07:58:07 -06001671 * either successfully or with an error.
1672 */
Jes Sorensenf4c11552015-04-13 10:28:40 -04001673static bool
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001674handle_command(struct controlvm_message inmsg, u64 channel_addr)
Ken Cox12e364b2014-03-04 07:58:07 -06001675{
Benjamin Romer2ea51172014-10-23 14:30:25 -04001676 struct controlvm_message_packet *cmd = &inmsg.cmd;
Jes Sorensene82ba622015-05-05 18:35:45 -04001677 u64 parm_addr;
1678 u32 parm_bytes;
Benjamin Romer317d9612015-03-16 13:57:51 -04001679 struct parser_context *parser_ctx = NULL;
Jes Sorensene82ba622015-05-05 18:35:45 -04001680 bool local_addr;
Benjamin Romer3ab47702014-10-23 14:30:31 -04001681 struct controlvm_message ackmsg;
Ken Cox12e364b2014-03-04 07:58:07 -06001682
1683 /* create parsing context if necessary */
Benjamin Romer818352a2015-03-16 13:58:31 -04001684 local_addr = (inmsg.hdr.flags.test_message == 1);
Benjamin Romer0aca78442015-03-04 12:14:25 -05001685 if (channel_addr == 0)
Jes Sorensenf4c11552015-04-13 10:28:40 -04001686 return true;
Benjamin Romer818352a2015-03-16 13:58:31 -04001687 parm_addr = channel_addr + inmsg.hdr.payload_vm_offset;
1688 parm_bytes = inmsg.hdr.payload_bytes;
Ken Cox12e364b2014-03-04 07:58:07 -06001689
1690 /* Parameter and channel addresses within test messages actually lie
1691 * within our OS-controlled memory. We need to know that, because it
1692 * makes a difference in how we compute the virtual address.
1693 */
Jes Sorensenebec8962015-05-05 18:35:57 -04001694 if (parm_addr && parm_bytes) {
Jes Sorensenf4c11552015-04-13 10:28:40 -04001695 bool retry = false;
Benjamin Romer26eb2c02014-08-18 09:34:53 -04001696
Ken Cox12e364b2014-03-04 07:58:07 -06001697 parser_ctx =
Benjamin Romer818352a2015-03-16 13:58:31 -04001698 parser_init_byte_stream(parm_addr, parm_bytes,
1699 local_addr, &retry);
Benjamin Romer1b088722015-03-04 12:14:26 -05001700 if (!parser_ctx && retry)
Jes Sorensenf4c11552015-04-13 10:28:40 -04001701 return false;
Ken Cox12e364b2014-03-04 07:58:07 -06001702 }
1703
Benjamin Romer818352a2015-03-16 13:58:31 -04001704 if (!local_addr) {
Ken Cox12e364b2014-03-04 07:58:07 -06001705 controlvm_init_response(&ackmsg, &inmsg.hdr,
1706 CONTROLVM_RESP_SUCCESS);
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001707 if (controlvm_channel)
1708 visorchannel_signalinsert(controlvm_channel,
Benjamin Romer1b088722015-03-04 12:14:26 -05001709 CONTROLVM_QUEUE_ACK,
1710 &ackmsg);
Ken Cox12e364b2014-03-04 07:58:07 -06001711 }
Benjamin Romer98d7b592014-10-23 14:30:26 -04001712 switch (inmsg.hdr.id) {
Ken Cox12e364b2014-03-04 07:58:07 -06001713 case CONTROLVM_CHIPSET_INIT:
Ken Cox12e364b2014-03-04 07:58:07 -06001714 chipset_init(&inmsg);
1715 break;
1716 case CONTROLVM_BUS_CREATE:
Ken Cox12e364b2014-03-04 07:58:07 -06001717 bus_create(&inmsg);
1718 break;
1719 case CONTROLVM_BUS_DESTROY:
Ken Cox12e364b2014-03-04 07:58:07 -06001720 bus_destroy(&inmsg);
1721 break;
1722 case CONTROLVM_BUS_CONFIGURE:
Ken Cox12e364b2014-03-04 07:58:07 -06001723 bus_configure(&inmsg, parser_ctx);
1724 break;
1725 case CONTROLVM_DEVICE_CREATE:
Ken Cox12e364b2014-03-04 07:58:07 -06001726 my_device_create(&inmsg);
1727 break;
1728 case CONTROLVM_DEVICE_CHANGESTATE:
Benjamin Romer2ea51172014-10-23 14:30:25 -04001729 if (cmd->device_change_state.flags.phys_device) {
Ken Cox12e364b2014-03-04 07:58:07 -06001730 parahotplug_process_message(&inmsg);
1731 } else {
Ken Cox12e364b2014-03-04 07:58:07 -06001732 /* save the hdr and cmd structures for later use */
1733 /* when sending back the response to Command */
1734 my_device_changestate(&inmsg);
Benjamin Romer4f44b722015-03-16 13:58:02 -04001735 g_devicechangestate_packet = inmsg.cmd;
Ken Cox12e364b2014-03-04 07:58:07 -06001736 break;
1737 }
1738 break;
1739 case CONTROLVM_DEVICE_DESTROY:
Ken Cox12e364b2014-03-04 07:58:07 -06001740 my_device_destroy(&inmsg);
1741 break;
1742 case CONTROLVM_DEVICE_CONFIGURE:
Ken Cox12e364b2014-03-04 07:58:07 -06001743 /* no op for now, just send a respond that we passed */
Benjamin Romer98d7b592014-10-23 14:30:26 -04001744 if (inmsg.hdr.flags.response_expected)
Ken Cox12e364b2014-03-04 07:58:07 -06001745 controlvm_respond(&inmsg.hdr, CONTROLVM_RESP_SUCCESS);
1746 break;
1747 case CONTROLVM_CHIPSET_READY:
Ken Cox12e364b2014-03-04 07:58:07 -06001748 chipset_ready(&inmsg.hdr);
1749 break;
1750 case CONTROLVM_CHIPSET_SELFTEST:
Ken Cox12e364b2014-03-04 07:58:07 -06001751 chipset_selftest(&inmsg.hdr);
1752 break;
1753 case CONTROLVM_CHIPSET_STOP:
Ken Cox12e364b2014-03-04 07:58:07 -06001754 chipset_notready(&inmsg.hdr);
1755 break;
1756 default:
Benjamin Romer98d7b592014-10-23 14:30:26 -04001757 if (inmsg.hdr.flags.response_expected)
Tim Sella07d7c32016-04-04 23:31:12 -04001758 controlvm_respond
1759 (&inmsg.hdr,
1760 -CONTROLVM_RESP_ERROR_MESSAGE_ID_UNKNOWN);
Ken Cox12e364b2014-03-04 07:58:07 -06001761 break;
1762 }
1763
Benjamin Romer38f736e2015-03-16 13:58:13 -04001764 if (parser_ctx) {
Ken Cox12e364b2014-03-04 07:58:07 -06001765 parser_done(parser_ctx);
1766 parser_ctx = NULL;
1767 }
Jes Sorensenf4c11552015-04-13 10:28:40 -04001768 return true;
Ken Cox12e364b2014-03-04 07:58:07 -06001769}
1770
David Kershner5f3a7e32015-05-13 13:22:10 -04001771static inline unsigned int
1772issue_vmcall_io_controlvm_addr(u64 *control_addr, u32 *control_bytes)
1773{
1774 struct vmcall_io_controlvm_addr_params params;
1775 int result = VMCALL_SUCCESS;
1776 u64 physaddr;
1777
1778 physaddr = virt_to_phys(&params);
1779 ISSUE_IO_VMCALL(VMCALL_IO_CONTROLVM_ADDR, physaddr, result);
1780 if (VMCALL_SUCCESSFUL(result)) {
1781 *control_addr = params.address;
1782 *control_bytes = params.channel_bytes;
1783 }
1784 return result;
1785}
1786
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04001787static u64 controlvm_get_channel_address(void)
Benjamin Romer524b0b62014-07-17 12:39:57 -04001788{
Benjamin Romer5fc02292014-07-31 12:00:51 -04001789 u64 addr = 0;
Benjamin Romerb3c55b12014-07-31 12:00:50 -04001790 u32 size = 0;
Benjamin Romer524b0b62014-07-17 12:39:57 -04001791
Benjamin Romer0aca78442015-03-04 12:14:25 -05001792 if (!VMCALL_SUCCESSFUL(issue_vmcall_io_controlvm_addr(&addr, &size)))
Benjamin Romer524b0b62014-07-17 12:39:57 -04001793 return 0;
Benjamin Romer0aca78442015-03-04 12:14:25 -05001794
Benjamin Romer524b0b62014-07-17 12:39:57 -04001795 return addr;
1796}
1797
Ken Cox12e364b2014-03-04 07:58:07 -06001798static void
1799controlvm_periodic_work(struct work_struct *work)
1800{
Benjamin Romer3ab47702014-10-23 14:30:31 -04001801 struct controlvm_message inmsg;
Jes Sorensenf4c11552015-04-13 10:28:40 -04001802 bool got_command = false;
1803 bool handle_command_failed = false;
Ken Cox12e364b2014-03-04 07:58:07 -06001804
1805 /* make sure visorbus server is registered for controlvm callbacks */
David Kershner4da33362015-05-05 18:36:39 -04001806 if (visorchipset_visorbusregwait && !visorbusregistered)
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001807 goto cleanup;
Ken Cox12e364b2014-03-04 07:58:07 -06001808
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001809 while (visorchannel_signalremove(controlvm_channel,
Benjamin Romer8a1182e2014-07-17 12:39:58 -04001810 CONTROLVM_QUEUE_RESPONSE,
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001811 &inmsg))
1812 ;
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001813 if (!got_command) {
Benjamin Romer7166ed12015-03-16 13:58:38 -04001814 if (controlvm_pending_msg_valid) {
Benjamin Romer8a1182e2014-07-17 12:39:58 -04001815 /* we throttled processing of a prior
1816 * msg, so try to process it again
1817 * rather than reading a new one
1818 */
Benjamin Romer7166ed12015-03-16 13:58:38 -04001819 inmsg = controlvm_pending_msg;
Jes Sorensenf4c11552015-04-13 10:28:40 -04001820 controlvm_pending_msg_valid = false;
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001821 got_command = true;
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04001822 } else {
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001823 got_command = read_controlvm_event(&inmsg);
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04001824 }
Ken Cox12e364b2014-03-04 07:58:07 -06001825 }
1826
Jes Sorensenf4c11552015-04-13 10:28:40 -04001827 handle_command_failed = false;
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001828 while (got_command && (!handle_command_failed)) {
Benjamin Romerb53e0e92015-03-16 13:57:56 -04001829 most_recent_message_jiffies = jiffies;
Benjamin Romer8a1182e2014-07-17 12:39:58 -04001830 if (handle_command(inmsg,
1831 visorchannel_get_physaddr
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001832 (controlvm_channel)))
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001833 got_command = read_controlvm_event(&inmsg);
Benjamin Romer8a1182e2014-07-17 12:39:58 -04001834 else {
1835 /* this is a scenario where throttling
1836 * is required, but probably NOT an
1837 * error...; we stash the current
1838 * controlvm msg so we will attempt to
1839 * reprocess it on our next loop
1840 */
Jes Sorensenf4c11552015-04-13 10:28:40 -04001841 handle_command_failed = true;
Benjamin Romer7166ed12015-03-16 13:58:38 -04001842 controlvm_pending_msg = inmsg;
Jes Sorensenf4c11552015-04-13 10:28:40 -04001843 controlvm_pending_msg_valid = true;
Ken Cox12e364b2014-03-04 07:58:07 -06001844 }
1845 }
1846
1847 /* parahotplug_worker */
1848 parahotplug_process_list();
1849
Benjamin Romer1c1ed292015-03-16 13:58:32 -04001850cleanup:
Ken Cox12e364b2014-03-04 07:58:07 -06001851
1852 if (time_after(jiffies,
Benjamin Romerb53e0e92015-03-16 13:57:56 -04001853 most_recent_message_jiffies + (HZ * MIN_IDLE_SECONDS))) {
Ken Cox12e364b2014-03-04 07:58:07 -06001854 /* it's been longer than MIN_IDLE_SECONDS since we
1855 * processed our last controlvm message; slow down the
1856 * polling
1857 */
Benjamin Romer911e2132015-03-16 13:57:47 -04001858 if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_SLOW)
1859 poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
Ken Cox12e364b2014-03-04 07:58:07 -06001860 } else {
Benjamin Romer911e2132015-03-16 13:57:47 -04001861 if (poll_jiffies != POLLJIFFIES_CONTROLVMCHANNEL_FAST)
1862 poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
Ken Cox12e364b2014-03-04 07:58:07 -06001863 }
1864
Amitoj Kaur Chawla0bde2972016-02-28 18:14:16 +05301865 schedule_delayed_work(&periodic_controlvm_work, poll_jiffies);
Ken Cox12e364b2014-03-04 07:58:07 -06001866}
1867
1868static void
1869setup_crash_devices_work_queue(struct work_struct *work)
1870{
Benjamin Romere6bdb902015-03-16 13:58:33 -04001871 struct controlvm_message local_crash_bus_msg;
1872 struct controlvm_message local_crash_dev_msg;
Benjamin Romer3ab47702014-10-23 14:30:31 -04001873 struct controlvm_message msg;
Benjamin Romere6bdb902015-03-16 13:58:33 -04001874 u32 local_crash_msg_offset;
1875 u16 local_crash_msg_count;
Ken Cox12e364b2014-03-04 07:58:07 -06001876
David Kershner4da33362015-05-05 18:36:39 -04001877 /* make sure visorbus is registered for controlvm callbacks */
David Kershnerb8999632016-03-11 17:01:38 -05001878 if (visorchipset_visorbusregwait && !visorbusregistered) {
1879 poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_SLOW;
1880 schedule_delayed_work(&periodic_controlvm_work, poll_jiffies);
1881 return;
1882 }
Ken Cox12e364b2014-03-04 07:58:07 -06001883
1884 POSTCODE_LINUX_2(CRASH_DEV_ENTRY_PC, POSTCODE_SEVERITY_INFO);
1885
1886 /* send init chipset msg */
Benjamin Romer98d7b592014-10-23 14:30:26 -04001887 msg.hdr.id = CONTROLVM_CHIPSET_INIT;
Benjamin Romer2ea51172014-10-23 14:30:25 -04001888 msg.cmd.init_chipset.bus_count = 23;
1889 msg.cmd.init_chipset.switch_count = 0;
Ken Cox12e364b2014-03-04 07:58:07 -06001890
1891 chipset_init(&msg);
1892
Ken Cox12e364b2014-03-04 07:58:07 -06001893 /* get saved message count */
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001894 if (visorchannel_read(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04001895 offsetof(struct spar_controlvm_channel_protocol,
1896 saved_crash_message_count),
Benjamin Romere6bdb902015-03-16 13:58:33 -04001897 &local_crash_msg_count, sizeof(u16)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001898 POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
1899 POSTCODE_SEVERITY_ERR);
1900 return;
1901 }
1902
Benjamin Romere6bdb902015-03-16 13:58:33 -04001903 if (local_crash_msg_count != CONTROLVM_CRASHMSG_MAX) {
Ken Cox12e364b2014-03-04 07:58:07 -06001904 POSTCODE_LINUX_3(CRASH_DEV_COUNT_FAILURE_PC,
Benjamin Romere6bdb902015-03-16 13:58:33 -04001905 local_crash_msg_count,
Ken Cox12e364b2014-03-04 07:58:07 -06001906 POSTCODE_SEVERITY_ERR);
1907 return;
1908 }
1909
1910 /* get saved crash message offset */
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001911 if (visorchannel_read(controlvm_channel,
Benjamin Romerd19642f2014-10-23 14:30:34 -04001912 offsetof(struct spar_controlvm_channel_protocol,
1913 saved_crash_message_offset),
Benjamin Romere6bdb902015-03-16 13:58:33 -04001914 &local_crash_msg_offset, sizeof(u32)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001915 POSTCODE_LINUX_2(CRASH_DEV_CTRL_RD_FAILURE_PC,
1916 POSTCODE_SEVERITY_ERR);
1917 return;
1918 }
1919
1920 /* read create device message for storage bus offset */
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001921 if (visorchannel_read(controlvm_channel,
Benjamin Romere6bdb902015-03-16 13:58:33 -04001922 local_crash_msg_offset,
1923 &local_crash_bus_msg,
Benjamin Romer3ab47702014-10-23 14:30:31 -04001924 sizeof(struct controlvm_message)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001925 POSTCODE_LINUX_2(CRASH_DEV_RD_BUS_FAIULRE_PC,
1926 POSTCODE_SEVERITY_ERR);
1927 return;
1928 }
1929
1930 /* read create device message for storage device */
Benjamin Romerc3d9a222015-03-16 13:58:05 -04001931 if (visorchannel_read(controlvm_channel,
Benjamin Romere6bdb902015-03-16 13:58:33 -04001932 local_crash_msg_offset +
Benjamin Romer3ab47702014-10-23 14:30:31 -04001933 sizeof(struct controlvm_message),
Benjamin Romere6bdb902015-03-16 13:58:33 -04001934 &local_crash_dev_msg,
Benjamin Romer3ab47702014-10-23 14:30:31 -04001935 sizeof(struct controlvm_message)) < 0) {
Ken Cox12e364b2014-03-04 07:58:07 -06001936 POSTCODE_LINUX_2(CRASH_DEV_RD_DEV_FAIULRE_PC,
1937 POSTCODE_SEVERITY_ERR);
1938 return;
1939 }
1940
1941 /* reuse IOVM create bus message */
Jes Sorensenebec8962015-05-05 18:35:57 -04001942 if (local_crash_bus_msg.cmd.create_bus.channel_addr) {
Benjamin Romere6bdb902015-03-16 13:58:33 -04001943 bus_create(&local_crash_bus_msg);
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04001944 } else {
Ken Cox12e364b2014-03-04 07:58:07 -06001945 POSTCODE_LINUX_2(CRASH_DEV_BUS_NULL_FAILURE_PC,
1946 POSTCODE_SEVERITY_ERR);
1947 return;
1948 }
1949
1950 /* reuse create device message for storage device */
Jes Sorensenebec8962015-05-05 18:35:57 -04001951 if (local_crash_dev_msg.cmd.create_device.channel_addr) {
Benjamin Romere6bdb902015-03-16 13:58:33 -04001952 my_device_create(&local_crash_dev_msg);
Benjamin Romer75c1f8b2015-03-16 13:58:19 -04001953 } else {
Ken Cox12e364b2014-03-04 07:58:07 -06001954 POSTCODE_LINUX_2(CRASH_DEV_DEV_NULL_FAILURE_PC,
1955 POSTCODE_SEVERITY_ERR);
1956 return;
1957 }
Ken Cox12e364b2014-03-04 07:58:07 -06001958 POSTCODE_LINUX_2(CRASH_DEV_EXIT_PC, POSTCODE_SEVERITY_INFO);
Ken Cox12e364b2014-03-04 07:58:07 -06001959}
1960
1961static void
Don Zickusd32517e2015-06-04 09:22:41 -04001962bus_create_response(struct visor_device *bus_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06001963{
Alessandro Parini4b4fd432015-06-13 17:40:48 +02001964 if (response >= 0)
Don Zickus0274b5a2015-06-01 13:00:27 -04001965 bus_info->state.created = 1;
Don Zickus0274b5a2015-06-01 13:00:27 -04001966
1967 bus_responder(CONTROLVM_BUS_CREATE, bus_info->pending_msg_hdr,
1968 response);
1969
1970 kfree(bus_info->pending_msg_hdr);
1971 bus_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06001972}
1973
1974static void
Don Zickusd32517e2015-06-04 09:22:41 -04001975bus_destroy_response(struct visor_device *bus_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06001976{
Don Zickus0274b5a2015-06-01 13:00:27 -04001977 bus_responder(CONTROLVM_BUS_DESTROY, bus_info->pending_msg_hdr,
1978 response);
1979
1980 kfree(bus_info->pending_msg_hdr);
1981 bus_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06001982}
1983
1984static void
Don Zickusa298bc02015-06-04 09:22:42 -04001985device_create_response(struct visor_device *dev_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06001986{
Don Zickus0274b5a2015-06-01 13:00:27 -04001987 if (response >= 0)
1988 dev_info->state.created = 1;
1989
1990 device_responder(CONTROLVM_DEVICE_CREATE, dev_info->pending_msg_hdr,
1991 response);
1992
1993 kfree(dev_info->pending_msg_hdr);
Tim Selladdce192015-07-09 13:27:41 -04001994 dev_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06001995}
1996
1997static void
Don Zickusa298bc02015-06-04 09:22:42 -04001998device_destroy_response(struct visor_device *dev_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06001999{
Don Zickus0274b5a2015-06-01 13:00:27 -04002000 device_responder(CONTROLVM_DEVICE_DESTROY, dev_info->pending_msg_hdr,
2001 response);
2002
2003 kfree(dev_info->pending_msg_hdr);
2004 dev_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06002005}
2006
Jes Sorensend3368a52015-05-13 13:21:57 -04002007static void
Don Zickusa298bc02015-06-04 09:22:42 -04002008visorchipset_device_pause_response(struct visor_device *dev_info,
Don Zickusb4b598f2015-05-13 13:22:25 -04002009 int response)
Ken Cox12e364b2014-03-04 07:58:07 -06002010{
Ken Cox12e364b2014-03-04 07:58:07 -06002011 device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
Don Zickusb4b598f2015-05-13 13:22:25 -04002012 dev_info, response,
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -04002013 segment_state_standby);
Don Zickus0274b5a2015-06-01 13:00:27 -04002014
2015 kfree(dev_info->pending_msg_hdr);
2016 dev_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06002017}
Ken Cox12e364b2014-03-04 07:58:07 -06002018
2019static void
Don Zickusa298bc02015-06-04 09:22:42 -04002020device_resume_response(struct visor_device *dev_info, int response)
Ken Cox12e364b2014-03-04 07:58:07 -06002021{
2022 device_changestate_responder(CONTROLVM_DEVICE_CHANGESTATE,
Don Zickusb4b598f2015-05-13 13:22:25 -04002023 dev_info, response,
Benjamin Romerbd0d2dc2014-10-23 14:30:13 -04002024 segment_state_running);
Don Zickus0274b5a2015-06-01 13:00:27 -04002025
2026 kfree(dev_info->pending_msg_hdr);
2027 dev_info->pending_msg_hdr = NULL;
Ken Cox12e364b2014-03-04 07:58:07 -06002028}
2029
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002030/* The parahotplug/devicedisabled interface gets called by our support script
2031 * when an SR-IOV device has been shut down. The ID is passed to the script
2032 * and then passed back when the device has been removed.
2033 */
2034static ssize_t devicedisabled_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -04002035 struct device_attribute *attr,
2036 const char *buf, size_t count)
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002037{
Jes Sorensen94217362015-05-05 18:35:46 -04002038 unsigned int id;
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002039
Jes Sorensenebec8962015-05-05 18:35:57 -04002040 if (kstrtouint(buf, 10, &id))
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002041 return -EINVAL;
2042
2043 parahotplug_request_complete(id, 0);
2044 return count;
2045}
2046
2047/* The parahotplug/deviceenabled interface gets called by our support script
2048 * when an SR-IOV device has been recovered. The ID is passed to the script
2049 * and then passed back when the device has been brought back up.
2050 */
2051static ssize_t deviceenabled_store(struct device *dev,
Benjamin Romer8e76e692015-03-16 13:58:52 -04002052 struct device_attribute *attr,
2053 const char *buf, size_t count)
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002054{
Jes Sorensen94217362015-05-05 18:35:46 -04002055 unsigned int id;
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002056
Jes Sorensenebec8962015-05-05 18:35:57 -04002057 if (kstrtouint(buf, 10, &id))
Benjamin Romere56fa7c2014-07-29 11:11:21 -04002058 return -EINVAL;
2059
2060 parahotplug_request_complete(id, 1);
2061 return count;
2062}
2063
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002064static int
2065visorchipset_mmap(struct file *file, struct vm_area_struct *vma)
2066{
2067 unsigned long physaddr = 0;
2068 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
Erik Arfvidson780fcad2015-05-05 18:36:35 -04002069 u64 addr = 0;
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002070
2071 /* sv_enable_dfp(); */
2072 if (offset & (PAGE_SIZE - 1))
2073 return -ENXIO; /* need aligned offsets */
2074
2075 switch (offset) {
2076 case VISORCHIPSET_MMAP_CONTROLCHANOFFSET:
2077 vma->vm_flags |= VM_IO;
2078 if (!*file_controlvm_channel)
2079 return -ENXIO;
2080
Tim Sella07d7c32016-04-04 23:31:12 -04002081 visorchannel_read
2082 (*file_controlvm_channel,
2083 offsetof(struct spar_controlvm_channel_protocol,
2084 gp_control_channel),
2085 &addr, sizeof(addr));
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002086 if (!addr)
2087 return -ENXIO;
2088
2089 physaddr = (unsigned long)addr;
2090 if (remap_pfn_range(vma, vma->vm_start,
2091 physaddr >> PAGE_SHIFT,
2092 vma->vm_end - vma->vm_start,
2093 /*pgprot_noncached */
2094 (vma->vm_page_prot))) {
2095 return -EAGAIN;
2096 }
2097 break;
2098 default:
2099 return -ENXIO;
2100 }
2101 return 0;
2102}
2103
David Kershner5f3a7e32015-05-13 13:22:10 -04002104static inline s64 issue_vmcall_query_guest_virtual_time_offset(void)
2105{
2106 u64 result = VMCALL_SUCCESS;
2107 u64 physaddr = 0;
2108
2109 ISSUE_IO_VMCALL(VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET, physaddr,
2110 result);
2111 return result;
2112}
2113
2114static inline int issue_vmcall_update_physical_time(u64 adjustment)
2115{
2116 int result = VMCALL_SUCCESS;
2117
2118 ISSUE_IO_VMCALL(VMCALL_UPDATE_PHYSICAL_TIME, adjustment, result);
2119 return result;
2120}
2121
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002122static long visorchipset_ioctl(struct file *file, unsigned int cmd,
2123 unsigned long arg)
2124{
David Kershner25002762016-03-03 13:00:38 -05002125 u64 adjustment;
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002126 s64 vrtc_offset;
2127
2128 switch (cmd) {
2129 case VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET:
2130 /* get the physical rtc offset */
2131 vrtc_offset = issue_vmcall_query_guest_virtual_time_offset();
2132 if (copy_to_user((void __user *)arg, &vrtc_offset,
2133 sizeof(vrtc_offset))) {
2134 return -EFAULT;
2135 }
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002136 return 0;
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002137 case VMCALL_UPDATE_PHYSICAL_TIME:
2138 if (copy_from_user(&adjustment, (void __user *)arg,
2139 sizeof(adjustment))) {
2140 return -EFAULT;
2141 }
2142 return issue_vmcall_update_physical_time(adjustment);
2143 default:
2144 return -EFAULT;
2145 }
2146}
2147
2148static const struct file_operations visorchipset_fops = {
2149 .owner = THIS_MODULE,
2150 .open = visorchipset_open,
2151 .read = NULL,
2152 .write = NULL,
2153 .unlocked_ioctl = visorchipset_ioctl,
2154 .release = visorchipset_release,
2155 .mmap = visorchipset_mmap,
2156};
2157
Jes Sorensen0f570fc2015-05-13 13:21:55 -04002158static int
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002159visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel)
2160{
2161 int rc = 0;
2162
2163 file_controlvm_channel = controlvm_channel;
2164 cdev_init(&file_cdev, &visorchipset_fops);
2165 file_cdev.owner = THIS_MODULE;
2166 if (MAJOR(major_dev) == 0) {
Erik Arfvidson46168812015-05-05 18:36:14 -04002167 rc = alloc_chrdev_region(&major_dev, 0, 1, "visorchipset");
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002168 /* dynamic major device number registration required */
2169 if (rc < 0)
2170 return rc;
2171 } else {
2172 /* static major device number registration required */
Erik Arfvidson46168812015-05-05 18:36:14 -04002173 rc = register_chrdev_region(major_dev, 1, "visorchipset");
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002174 if (rc < 0)
2175 return rc;
2176 }
2177 rc = cdev_add(&file_cdev, MKDEV(MAJOR(major_dev), 0), 1);
2178 if (rc < 0) {
2179 unregister_chrdev_region(major_dev, 1);
2180 return rc;
2181 }
2182 return 0;
2183}
2184
David Kershner1366a3d2016-04-04 23:31:37 -04002185static void
2186visorchipset_file_cleanup(dev_t major_dev)
2187{
2188 if (file_cdev.ops)
2189 cdev_del(&file_cdev);
2190 file_cdev.ops = NULL;
2191 unregister_chrdev_region(major_dev, 1);
2192}
2193
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002194static int
2195visorchipset_init(struct acpi_device *acpi_device)
Ken Cox12e364b2014-03-04 07:58:07 -06002196{
David Kershner1366a3d2016-04-04 23:31:37 -04002197 int err = -ENODEV;
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002198 u64 addr;
Jes Sorensend3368a52015-05-13 13:21:57 -04002199 uuid_le uuid = SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID;
2200
2201 addr = controlvm_get_channel_address();
2202 if (!addr)
David Kershner1366a3d2016-04-04 23:31:37 -04002203 goto error;
Ken Cox12e364b2014-03-04 07:58:07 -06002204
David Kershner4da33362015-05-05 18:36:39 -04002205 memset(&busdev_notifiers, 0, sizeof(busdev_notifiers));
Benjamin Romer84982fb2015-03-16 13:58:07 -04002206 memset(&controlvm_payload_info, 0, sizeof(controlvm_payload_info));
Ken Cox12e364b2014-03-04 07:58:07 -06002207
Tim Sellc732623b2016-03-01 19:45:03 -05002208 controlvm_channel = visorchannel_create_with_lock(addr, 0,
Jes Sorensend3368a52015-05-13 13:21:57 -04002209 GFP_KERNEL, uuid);
Tim Sellc732623b2016-03-01 19:45:03 -05002210 if (!controlvm_channel)
David Kershner1366a3d2016-04-04 23:31:37 -04002211 goto error;
2212
Jes Sorensend3368a52015-05-13 13:21:57 -04002213 if (SPAR_CONTROLVM_CHANNEL_OK_CLIENT(
2214 visorchannel_get_header(controlvm_channel))) {
2215 initialize_controlvm_payload();
Benjamin Romer8a1182e2014-07-17 12:39:58 -04002216 } else {
David Kershner1366a3d2016-04-04 23:31:37 -04002217 goto error_destroy_channel;
Benjamin Romer8a1182e2014-07-17 12:39:58 -04002218 }
2219
Benjamin Romer5aa8ae52015-03-16 13:58:44 -04002220 major_dev = MKDEV(visorchipset_major, 0);
David Kershner1366a3d2016-04-04 23:31:37 -04002221 err = visorchipset_file_init(major_dev, &controlvm_channel);
2222 if (err < 0)
2223 goto error_destroy_payload;
Ken Cox12e364b2014-03-04 07:58:07 -06002224
David Kershner4da33362015-05-05 18:36:39 -04002225 /* if booting in a crash kernel */
2226 if (is_kdump_kernel())
2227 INIT_DELAYED_WORK(&periodic_controlvm_work,
2228 setup_crash_devices_work_queue);
2229 else
2230 INIT_DELAYED_WORK(&periodic_controlvm_work,
2231 controlvm_periodic_work);
Ken Cox12e364b2014-03-04 07:58:07 -06002232
David Kershner4da33362015-05-05 18:36:39 -04002233 most_recent_message_jiffies = jiffies;
2234 poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
Amitoj Kaur Chawla0bde2972016-02-28 18:14:16 +05302235 schedule_delayed_work(&periodic_controlvm_work, poll_jiffies);
Ken Cox12e364b2014-03-04 07:58:07 -06002236
Benjamin Romereb34e872015-03-16 13:58:45 -04002237 visorchipset_platform_device.dev.devt = major_dev;
2238 if (platform_device_register(&visorchipset_platform_device) < 0) {
Ken Cox4cb005a2014-03-19 13:06:20 -05002239 POSTCODE_LINUX_2(DEVICE_REGISTER_FAILURE_PC, DIAG_SEVERITY_ERR);
David Kershner1366a3d2016-04-04 23:31:37 -04002240 err = -ENODEV;
2241 goto error_cancel_work;
Ken Cox4cb005a2014-03-19 13:06:20 -05002242 }
Ken Cox12e364b2014-03-04 07:58:07 -06002243 POSTCODE_LINUX_2(CHIPSET_INIT_SUCCESS_PC, POSTCODE_SEVERITY_INFO);
Prarit Bhargavac79b28f2015-05-05 18:36:15 -04002244
David Kershner1366a3d2016-04-04 23:31:37 -04002245 err = visorbus_init();
2246 if (err < 0)
2247 goto error_unregister;
Ken Cox12e364b2014-03-04 07:58:07 -06002248
David Kershner1366a3d2016-04-04 23:31:37 -04002249 return 0;
2250
2251error_unregister:
2252 platform_device_unregister(&visorchipset_platform_device);
2253
2254error_cancel_work:
2255 cancel_delayed_work_sync(&periodic_controlvm_work);
2256 visorchipset_file_cleanup(major_dev);
2257
2258error_destroy_payload:
2259 destroy_controlvm_payload_info(&controlvm_payload_info);
2260
2261error_destroy_channel:
2262 visorchannel_destroy(controlvm_channel);
2263
2264error:
2265 POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, err, POSTCODE_SEVERITY_ERR);
2266 return err;
Erik Arfvidsone3420ed2015-05-05 18:36:13 -04002267}
2268
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002269static int
2270visorchipset_exit(struct acpi_device *acpi_device)
Ken Cox12e364b2014-03-04 07:58:07 -06002271{
Ken Cox12e364b2014-03-04 07:58:07 -06002272 POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
2273
Prarit Bhargavac79b28f2015-05-05 18:36:15 -04002274 visorbus_exit();
2275
Amitoj Kaur Chawla0bde2972016-02-28 18:14:16 +05302276 cancel_delayed_work_sync(&periodic_controlvm_work);
David Kershner4da33362015-05-05 18:36:39 -04002277 destroy_controlvm_payload_info(&controlvm_payload_info);
Benjamin Romer17833192014-07-15 13:30:41 -04002278
Benjamin Romerc3d9a222015-03-16 13:58:05 -04002279 visorchannel_destroy(controlvm_channel);
Benjamin Romer8a1182e2014-07-17 12:39:58 -04002280
Sudip Mukherjeeaddceb12015-03-24 20:47:28 +05302281 visorchipset_file_cleanup(visorchipset_platform_device.dev.devt);
Don Zickus04dacac2015-06-04 09:22:48 -04002282 platform_device_unregister(&visorchipset_platform_device);
Ken Cox12e364b2014-03-04 07:58:07 -06002283 POSTCODE_LINUX_2(DRIVER_EXIT_PC, POSTCODE_SEVERITY_INFO);
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002284
2285 return 0;
2286}
2287
2288static const struct acpi_device_id unisys_device_ids[] = {
2289 {"PNP0A07", 0},
2290 {"", 0},
2291};
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002292
2293static struct acpi_driver unisys_acpi_driver = {
2294 .name = "unisys_acpi",
2295 .class = "unisys_acpi_class",
2296 .owner = THIS_MODULE,
2297 .ids = unisys_device_ids,
2298 .ops = {
2299 .add = visorchipset_init,
2300 .remove = visorchipset_exit,
2301 },
2302};
David Kershner1fc07f92015-07-09 13:27:53 -04002303
2304MODULE_DEVICE_TABLE(acpi, unisys_device_ids);
2305
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002306static __init uint32_t visorutil_spar_detect(void)
2307{
2308 unsigned int eax, ebx, ecx, edx;
2309
Borislav Petkov0c9f3532016-03-29 17:41:55 +02002310 if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002311 /* check the ID */
2312 cpuid(UNISYS_SPAR_LEAF_ID, &eax, &ebx, &ecx, &edx);
2313 return (ebx == UNISYS_SPAR_ID_EBX) &&
2314 (ecx == UNISYS_SPAR_ID_ECX) &&
2315 (edx == UNISYS_SPAR_ID_EDX);
2316 } else {
2317 return 0;
2318 }
2319}
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002320
2321static int init_unisys(void)
2322{
2323 int result;
Alessandro Parini35e606d2015-06-13 17:40:49 +02002324
Erik Arfvidsond5b3f1d2015-05-05 18:37:04 -04002325 if (!visorutil_spar_detect())
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002326 return -ENODEV;
2327
2328 result = acpi_bus_register_driver(&unisys_acpi_driver);
2329 if (result)
2330 return -ENODEV;
2331
2332 pr_info("Unisys Visorchipset Driver Loaded.\n");
2333 return 0;
2334};
2335
2336static void exit_unisys(void)
2337{
2338 acpi_bus_unregister_driver(&unisys_acpi_driver);
Ken Cox12e364b2014-03-04 07:58:07 -06002339}
2340
Ken Cox12e364b2014-03-04 07:58:07 -06002341module_param_named(major, visorchipset_major, int, S_IRUGO);
Jes Sorensenb615d622015-05-05 18:35:38 -04002342MODULE_PARM_DESC(visorchipset_major,
2343 "major device number to use for the device node");
David Kershner4da33362015-05-05 18:36:39 -04002344module_param_named(visorbusregwait, visorchipset_visorbusregwait, int, S_IRUGO);
David Binder80bee262016-05-06 13:11:16 -04002345MODULE_PARM_DESC(visorchipset_visorbusregwait,
Ken Cox12e364b2014-03-04 07:58:07 -06002346 "1 to have the module wait for the visor bus to register");
Jes Sorensenb615d622015-05-05 18:35:38 -04002347
Prarit Bhargava55c67dc2015-05-05 18:37:02 -04002348module_init(init_unisys);
2349module_exit(exit_unisys);
Ken Cox12e364b2014-03-04 07:58:07 -06002350
2351MODULE_AUTHOR("Unisys");
2352MODULE_LICENSE("GPL");
2353MODULE_DESCRIPTION("Supervisor chipset driver for service partition: ver "
2354 VERSION);
2355MODULE_VERSION(VERSION);