1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2010 - 2015 UNISYS CORPORATION 4 * All rights reserved. 5 */ 6 7/* 8 * This provides s-Par channel communication primitives, which are 9 * independent of the mechanism used to access the channel data. 10 */ 11 12#include <linux/uuid.h> 13#include <linux/io.h> 14#include <linux/slab.h> 15#include <linux/visorbus.h> 16 17#include "visorbus_private.h" 18#include "controlvmchannel.h" 19 20#define VISOR_DRV_NAME "visorchannel" 21 22#define VISOR_CONSOLEVIDEO_CHANNEL_GUID \ 23 GUID_INIT(0x3cd6e705, 0xd6a2, 0x4aa5, \ 24 0xad, 0x5c, 0x7b, 0x8, 0x88, 0x9d, 0xff, 0xe2) 25 26static const guid_t visor_video_guid = VISOR_CONSOLEVIDEO_CHANNEL_GUID; 27 28struct visorchannel { 29 u64 physaddr; 30 ulong nbytes; 31 void *mapped; 32 bool requested; 33 struct channel_header chan_hdr; 34 guid_t guid; 35 /* 36 * channel creator knows if more than one thread will be inserting or 37 * removing 38 */ 39 bool needs_lock; 40 /* protect head writes in chan_hdr */ 41 spinlock_t insert_lock; 42 /* protect tail writes in chan_hdr */ 43 spinlock_t remove_lock; 44 guid_t type; 45 guid_t inst; 46}; 47 48void visorchannel_destroy(struct visorchannel *channel) 49{ 50 if (!channel) 51 return; 52 53 if (channel->mapped) { 54 memunmap(channel->mapped); 55 if (channel->requested) 56 release_mem_region(channel->physaddr, channel->nbytes); 57 } 58 kfree(channel); 59} 60 61u64 visorchannel_get_physaddr(struct visorchannel *channel) 62{ 63 return channel->physaddr; 64} 65 66ulong visorchannel_get_nbytes(struct visorchannel *channel) 67{ 68 return channel->nbytes; 69} 70 71char *visorchannel_guid_id(const guid_t *guid, char *s) 72{ 73 sprintf(s, "%pUL", guid); 74 return s; 75} 76 77char *visorchannel_id(struct visorchannel *channel, char *s) 78{ 79 return visorchannel_guid_id(&channel->guid, s); 80} 81 82char *visorchannel_zoneid(struct visorchannel *channel, char *s) 83{ 84 return visorchannel_guid_id(&channel->chan_hdr.zone_guid, s); 85} 86 87u64 visorchannel_get_clientpartition(struct visorchannel *channel) 88{ 89 return channel->chan_hdr.partition_handle; 90} 91 92int visorchannel_set_clientpartition(struct visorchannel *channel, 93 u64 partition_handle) 94{ 95 channel->chan_hdr.partition_handle = partition_handle; 96 return 0; 97} 98 99/** 100 * visorchannel_get_guid() - queries the GUID of the designated channel 101 * @channel: the channel to query 102 * 103 * Return: the GUID of the provided channel 104 */ 105const guid_t *visorchannel_get_guid(struct visorchannel *channel) 106{ 107 return &channel->guid; 108} 109EXPORT_SYMBOL_GPL(visorchannel_get_guid); 110 111int visorchannel_read(struct visorchannel *channel, ulong offset, void *dest, 112 ulong nbytes) 113{ 114 if (offset + nbytes > channel->nbytes) 115 return -EIO; 116 117 memcpy(dest, channel->mapped + offset, nbytes); 118 return 0; 119} 120 121int visorchannel_write(struct visorchannel *channel, ulong offset, void *dest, 122 ulong nbytes) 123{ 124 size_t chdr_size = sizeof(struct channel_header); 125 size_t copy_size; 126 127 if (offset + nbytes > channel->nbytes) 128 return -EIO; 129 130 if (offset < chdr_size) { 131 copy_size = min(chdr_size - offset, nbytes); 132 memcpy(((char *)(&channel->chan_hdr)) + offset, 133 dest, copy_size); 134 } 135 memcpy(channel->mapped + offset, dest, nbytes); 136 return 0; 137} 138 139void *visorchannel_get_header(struct visorchannel *channel) 140{ 141 return &channel->chan_hdr; 142} 143 144/* 145 * Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a 146 * channel header 147 */ 148static int sig_queue_offset(struct channel_header *chan_hdr, int q) 149{ 150 return ((chan_hdr)->ch_space_offset + 151 ((q) * sizeof(struct signal_queue_header))); 152} 153 154/* 155 * Return offset of a specific queue entry (data) from the beginning of a 156 * channel header 157 */ 158static int sig_data_offset(struct channel_header *chan_hdr, int q, 159 struct signal_queue_header *sig_hdr, int slot) 160{ 161 return (sig_queue_offset(chan_hdr, q) + sig_hdr->sig_base_offset + 162 (slot * sig_hdr->signal_size)); 163} 164 165/* 166 * Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back into 167 * host memory 168 */ 169#define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \ 170 visorchannel_write(channel, \ 171 sig_queue_offset(&channel->chan_hdr, queue) + \ 172 offsetof(struct signal_queue_header, FIELD), \ 173 &((sig_hdr)->FIELD), \ 174 sizeof((sig_hdr)->FIELD)) 175 176static int sig_read_header(struct visorchannel *channel, u32 queue, 177 struct signal_queue_header *sig_hdr) 178{ 179 if (channel->chan_hdr.ch_space_offset < sizeof(struct channel_header)) 180 return -EINVAL; 181 182 /* Read the appropriate SIGNAL_QUEUE_HEADER into local memory. */ 183 return visorchannel_read(channel, 184 sig_queue_offset(&channel->chan_hdr, queue), 185 sig_hdr, sizeof(struct signal_queue_header)); 186} 187 188static int sig_read_data(struct visorchannel *channel, u32 queue, 189 struct signal_queue_header *sig_hdr, u32 slot, 190 void *data) 191{ 192 int signal_data_offset = sig_data_offset(&channel->chan_hdr, queue, 193 sig_hdr, slot); 194 195 return visorchannel_read(channel, signal_data_offset, 196 data, sig_hdr->signal_size); 197} 198 199static int sig_write_data(struct visorchannel *channel, u32 queue, 200 struct signal_queue_header *sig_hdr, u32 slot, 201 void *data) 202{ 203 int signal_data_offset = sig_data_offset(&channel->chan_hdr, queue, 204 sig_hdr, slot); 205 206 return visorchannel_write(channel, signal_data_offset, 207 data, sig_hdr->signal_size); 208} 209 210static int signalremove_inner(struct visorchannel *channel, u32 queue, 211 void *msg) 212{ 213 struct signal_queue_header sig_hdr; 214 int error; 215 216 error = sig_read_header(channel, queue, &sig_hdr); 217 if (error) 218 return error; 219 /* No signals to remove; have caller try again. */ 220 if (sig_hdr.head == sig_hdr.tail) 221 return -EAGAIN; 222 sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots; 223 error = sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg); 224 if (error) 225 return error; 226 sig_hdr.num_received++; 227 /* 228 * For each data field in SIGNAL_QUEUE_HEADER that was modified, update 229 * host memory. Required for channel sync. 230 */ 231 mb(); 232 error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail); 233 if (error) 234 return error; 235 error = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received); 236 if (error) 237 return error; 238 return 0; 239} 240 241/** 242 * visorchannel_signalremove() - removes a message from the designated 243 * channel/queue 244 * @channel: the channel the message will be removed from 245 * @queue: the queue the message will be removed from 246 * @msg: the message to remove 247 * 248 * Return: integer error code indicating the status of the removal 249 */ 250int visorchannel_signalremove(struct visorchannel *channel, u32 queue, 251 void *msg) 252{ 253 int rc; 254 unsigned long flags; 255 256 if (channel->needs_lock) { 257 spin_lock_irqsave(&channel->remove_lock, flags); 258 rc = signalremove_inner(channel, queue, msg); 259 spin_unlock_irqrestore(&channel->remove_lock, flags); 260 } else { 261 rc = signalremove_inner(channel, queue, msg); 262 } 263 264 return rc; 265} 266EXPORT_SYMBOL_GPL(visorchannel_signalremove); 267 268static bool queue_empty(struct visorchannel *channel, u32 queue) 269{ 270 struct signal_queue_header sig_hdr; 271 272 if (sig_read_header(channel, queue, &sig_hdr)) 273 return true; 274 return (sig_hdr.head == sig_hdr.tail); 275} 276 277/** 278 * visorchannel_signalempty() - checks if the designated channel/queue contains 279 * any messages 280 * @channel: the channel to query 281 * @queue: the queue in the channel to query 282 * 283 * Return: boolean indicating whether any messages in the designated 284 * channel/queue are present 285 */ 286bool visorchannel_signalempty(struct visorchannel *channel, u32 queue) 287{ 288 bool rc; 289 unsigned long flags; 290 291 if (!channel->needs_lock) 292 return queue_empty(channel, queue); 293 spin_lock_irqsave(&channel->remove_lock, flags); 294 rc = queue_empty(channel, queue); 295 spin_unlock_irqrestore(&channel->remove_lock, flags); 296 return rc; 297} 298EXPORT_SYMBOL_GPL(visorchannel_signalempty); 299 300static int signalinsert_inner(struct visorchannel *channel, u32 queue, 301 void *msg) 302{ 303 struct signal_queue_header sig_hdr; 304 int err; 305 306 err = sig_read_header(channel, queue, &sig_hdr); 307 if (err) 308 return err; 309 sig_hdr.head = (sig_hdr.head + 1) % sig_hdr.max_slots; 310 if (sig_hdr.head == sig_hdr.tail) { 311 sig_hdr.num_overflows++; 312 err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_overflows); 313 if (err) 314 return err; 315 return -EIO; 316 } 317 err = sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg); 318 if (err) 319 return err; 320 sig_hdr.num_sent++; 321 /* 322 * For each data field in SIGNAL_QUEUE_HEADER that was modified, update 323 * host memory. Required for channel sync. 324 */ 325 mb(); 326 err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, head); 327 if (err) 328 return err; 329 err = SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent); 330 if (err) 331 return err; 332 return 0; 333} 334 335/* 336 * visorchannel_create() - creates the struct visorchannel abstraction for a 337 * data area in memory, but does NOT modify this data 338 * area 339 * @physaddr: physical address of start of channel 340 * @gfp: gfp_t to use when allocating memory for the data struct 341 * @guid: GUID that identifies channel type; 342 * @needs_lock: must specify true if you have multiple threads of execution 343 * that will be calling visorchannel methods of this 344 * visorchannel at the same time 345 * 346 * Return: pointer to visorchannel that was created if successful, 347 * otherwise NULL 348 */ 349struct visorchannel *visorchannel_create(u64 physaddr, gfp_t gfp, 350 const guid_t *guid, bool needs_lock) 351{ 352 struct visorchannel *channel; 353 int err; 354 size_t size = sizeof(struct channel_header); 355 356 if (physaddr == 0) 357 return NULL; 358 359 channel = kzalloc(sizeof(*channel), gfp); 360 if (!channel) 361 return NULL; 362 channel->needs_lock = needs_lock; 363 spin_lock_init(&channel->insert_lock); 364 spin_lock_init(&channel->remove_lock); 365 /* 366 * Video driver constains the efi framebuffer so it will get a conflict 367 * resource when requesting its full mem region. Since we are only 368 * using the efi framebuffer for video we can ignore this. Remember that 369 * we haven't requested it so we don't try to release later on. 370 */ 371 channel->requested = request_mem_region(physaddr, size, VISOR_DRV_NAME); 372 if (!channel->requested && !guid_equal(guid, &visor_video_guid)) 373 /* we only care about errors if this is not the video channel */ 374 goto err_destroy_channel; 375 channel->mapped = memremap(physaddr, size, MEMREMAP_WB); 376 if (!channel->mapped) { 377 release_mem_region(physaddr, size); 378 goto err_destroy_channel; 379 } 380 channel->physaddr = physaddr; 381 channel->nbytes = size; 382 err = visorchannel_read(channel, 0, &channel->chan_hdr, size); 383 if (err) 384 goto err_destroy_channel; 385 size = (ulong)channel->chan_hdr.size; 386 memunmap(channel->mapped); 387 if (channel->requested) 388 release_mem_region(channel->physaddr, channel->nbytes); 389 channel->mapped = NULL; 390 channel->requested = request_mem_region(channel->physaddr, size, 391 VISOR_DRV_NAME); 392 if (!channel->requested && !guid_equal(guid, &visor_video_guid)) 393 /* we only care about errors if this is not the video channel */ 394 goto err_destroy_channel; 395 channel->mapped = memremap(channel->physaddr, size, MEMREMAP_WB); 396 if (!channel->mapped) { 397 release_mem_region(channel->physaddr, size); 398 goto err_destroy_channel; 399 } 400 channel->nbytes = size; 401 guid_copy(&channel->guid, guid); 402 return channel; 403 404err_destroy_channel: 405 visorchannel_destroy(channel); 406 return NULL; 407} 408 409/** 410 * visorchannel_signalinsert() - inserts a message into the designated 411 * channel/queue 412 * @channel: the channel the message will be added to 413 * @queue: the queue the message will be added to 414 * @msg: the message to insert 415 * 416 * Return: integer error code indicating the status of the insertion 417 */ 418int visorchannel_signalinsert(struct visorchannel *channel, u32 queue, 419 void *msg) 420{ 421 int rc; 422 unsigned long flags; 423 424 if (channel->needs_lock) { 425 spin_lock_irqsave(&channel->insert_lock, flags); 426 rc = signalinsert_inner(channel, queue, msg); 427 spin_unlock_irqrestore(&channel->insert_lock, flags); 428 } else { 429 rc = signalinsert_inner(channel, queue, msg); 430 } 431 432 return rc; 433} 434EXPORT_SYMBOL_GPL(visorchannel_signalinsert); 435