*/
/*
- * This provides Supervisor channel communication primitives, which are
+ * This provides s-Par channel communication primitives, which are
* independent of the mechanism used to access the channel data.
*/
uuid_le inst;
};
-/* Creates the struct visorchannel abstraction for a data area in memory,
- * but does NOT modify this data area.
- */
-static struct visorchannel *
-visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes,
- gfp_t gfp, unsigned long off,
- uuid_le guid, bool needs_lock)
-{
- struct visorchannel *channel;
- int err;
- size_t size = sizeof(struct channel_header);
-
- if (physaddr == 0)
- return NULL;
-
- channel = kzalloc(sizeof(*channel), gfp);
- if (!channel)
- return NULL;
-
- channel->needs_lock = needs_lock;
- spin_lock_init(&channel->insert_lock);
- spin_lock_init(&channel->remove_lock);
-
- /* Video driver constains the efi framebuffer so it will get a
- * conflict resource when requesting its full mem region. Since
- * we are only using the efi framebuffer for video we can ignore
- * this. Remember that we haven't requested it so we don't try to
- * release later on.
- */
- channel->requested = request_mem_region(physaddr, size, MYDRVNAME);
- if (!channel->requested) {
- if (uuid_le_cmp(guid, spar_video_guid)) {
- /* Not the video channel we care about this */
- goto err_destroy_channel;
- }
- }
-
- channel->mapped = memremap(physaddr, size, MEMREMAP_WB);
- if (!channel->mapped) {
- release_mem_region(physaddr, size);
- goto err_destroy_channel;
- }
-
- channel->physaddr = physaddr;
- channel->nbytes = size;
-
- err = visorchannel_read(channel, 0, &channel->chan_hdr,
- sizeof(struct channel_header));
- if (err)
- goto err_destroy_channel;
-
- /* we had better be a CLIENT of this channel */
- if (channel_bytes == 0)
- channel_bytes = (ulong)channel->chan_hdr.size;
- if (uuid_le_cmp(guid, NULL_UUID_LE) == 0)
- guid = channel->chan_hdr.chtype;
-
- memunmap(channel->mapped);
- if (channel->requested)
- release_mem_region(channel->physaddr, channel->nbytes);
- channel->mapped = NULL;
- channel->requested = request_mem_region(channel->physaddr,
- channel_bytes, MYDRVNAME);
- if (!channel->requested) {
- if (uuid_le_cmp(guid, spar_video_guid)) {
- /* Different we care about this */
- goto err_destroy_channel;
- }
- }
-
- channel->mapped = memremap(channel->physaddr, channel_bytes,
- MEMREMAP_WB);
- if (!channel->mapped) {
- release_mem_region(channel->physaddr, channel_bytes);
- goto err_destroy_channel;
- }
-
- channel->nbytes = channel_bytes;
- channel->guid = guid;
- return channel;
-
-err_destroy_channel:
- visorchannel_destroy(channel);
- return NULL;
-}
-
-struct visorchannel *
-visorchannel_create(u64 physaddr, unsigned long channel_bytes,
- gfp_t gfp, uuid_le guid)
-{
- return visorchannel_create_guts(physaddr, channel_bytes, gfp, 0, guid,
- false);
-}
-EXPORT_SYMBOL_GPL(visorchannel_create);
-
-struct visorchannel *
-visorchannel_create_with_lock(u64 physaddr, unsigned long channel_bytes,
- gfp_t gfp, uuid_le guid)
-{
- return visorchannel_create_guts(physaddr, channel_bytes, gfp, 0, guid,
- true);
-}
-EXPORT_SYMBOL_GPL(visorchannel_create_with_lock);
-
void
visorchannel_destroy(struct visorchannel *channel)
{
}
kfree(channel);
}
-EXPORT_SYMBOL_GPL(visorchannel_destroy);
u64
visorchannel_get_physaddr(struct visorchannel *channel)
{
return channel->physaddr;
}
-EXPORT_SYMBOL_GPL(visorchannel_get_physaddr);
ulong
visorchannel_get_nbytes(struct visorchannel *channel)
{
return channel->nbytes;
}
-EXPORT_SYMBOL_GPL(visorchannel_get_nbytes);
char *
visorchannel_uuid_id(uuid_le *guid, char *s)
sprintf(s, "%pUL", guid);
return s;
}
-EXPORT_SYMBOL_GPL(visorchannel_uuid_id);
char *
visorchannel_id(struct visorchannel *channel, char *s)
{
return visorchannel_uuid_id(&channel->guid, s);
}
-EXPORT_SYMBOL_GPL(visorchannel_id);
char *
visorchannel_zoneid(struct visorchannel *channel, char *s)
{
return visorchannel_uuid_id(&channel->chan_hdr.zone_uuid, s);
}
-EXPORT_SYMBOL_GPL(visorchannel_zoneid);
u64
visorchannel_get_clientpartition(struct visorchannel *channel)
{
return channel->chan_hdr.partition_handle;
}
-EXPORT_SYMBOL_GPL(visorchannel_get_clientpartition);
int
visorchannel_set_clientpartition(struct visorchannel *channel,
channel->chan_hdr.partition_handle = partition_handle;
return 0;
}
-EXPORT_SYMBOL_GPL(visorchannel_set_clientpartition);
+/**
+ * visorchannel_get_uuid() - queries the UUID of the designated channel
+ * @channel: the channel to query
+ *
+ * Return: the UUID of the provided channel
+ */
uuid_le
visorchannel_get_uuid(struct visorchannel *channel)
{
return 0;
}
-EXPORT_SYMBOL_GPL(visorchannel_read);
int
visorchannel_write(struct visorchannel *channel, ulong offset,
return 0;
}
-EXPORT_SYMBOL_GPL(visorchannel_write);
-
-int
-visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch,
- ulong nbytes)
-{
- int err;
- int bufsize = PAGE_SIZE;
- int written = 0;
- u8 *buf;
-
- buf = (u8 *)__get_free_page(GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- memset(buf, ch, bufsize);
-
- while (nbytes > 0) {
- int thisbytes = bufsize;
-
- if (nbytes < thisbytes)
- thisbytes = nbytes;
- err = visorchannel_write(channel, offset + written,
- buf, thisbytes);
- if (err)
- goto out_free_page;
-
- written += thisbytes;
- nbytes -= thisbytes;
- }
- err = 0;
-
-out_free_page:
- free_page((unsigned long)buf);
- return err;
-}
-EXPORT_SYMBOL_GPL(visorchannel_clear);
void __iomem *
visorchannel_get_header(struct visorchannel *channel)
{
return (void __iomem *)&channel->chan_hdr;
}
-EXPORT_SYMBOL_GPL(visorchannel_get_header);
-/** Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
- * channel header
+/*
+ * Return offset of a specific SIGNAL_QUEUE_HEADER from the beginning of a
+ * channel header
*/
#define SIG_QUEUE_OFFSET(chan_hdr, q) \
((chan_hdr)->ch_space_offset + \
((q) * sizeof(struct signal_queue_header)))
-/** Return offset of a specific queue entry (data) from the beginning of a
- * channel header
+/*
+ * Return offset of a specific queue entry (data) from the beginning of a
+ * channel header
*/
#define SIG_DATA_OFFSET(chan_hdr, q, sig_hdr, slot) \
(SIG_QUEUE_OFFSET(chan_hdr, q) + (sig_hdr)->sig_base_offset + \
((slot) * (sig_hdr)->signal_size))
-/** Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back
- * into host memory
+/*
+ * Write the contents of a specific field within a SIGNAL_QUEUE_HEADER back
+ * into host memory
*/
#define SIG_WRITE_FIELD(channel, queue, sig_hdr, FIELD) \
(visorchannel_write(channel, \
return false;
sig_hdr.num_received++;
- /* For each data field in SIGNAL_QUEUE_HEADER that was modified,
+ /*
+ * For each data field in SIGNAL_QUEUE_HEADER that was modified,
* update host memory.
*/
mb(); /* required for channel synch */
return true;
}
+/**
+ * visorchannel_signalremove() - removes a message from the designated
+ * channel/queue
+ * @channel: the channel the message will be removed from
+ * @queue: the queue the message will be removed from
+ * @msg: the message to remove
+ *
+ * Return: boolean indicating whether the removal succeeded or failed
+ */
bool
visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg)
{
}
EXPORT_SYMBOL_GPL(visorchannel_signalremove);
+/**
+ * visorchannel_signalempty() - checks if the designated channel/queue
+ * contains any messages
+ * @channel: the channel to query
+ * @queue: the queue in the channel to query
+ *
+ * Return: boolean indicating whether any messages in the designated
+ * channel/queue are present
+ */
bool
visorchannel_signalempty(struct visorchannel *channel, u32 queue)
{
sig_hdr.num_sent++;
- /* For each data field in SIGNAL_QUEUE_HEADER that was modified,
+ /*
+ * For each data field in SIGNAL_QUEUE_HEADER that was modified,
* update host memory.
*/
mb(); /* required for channel synch */
return true;
}
-bool
-visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg)
+/**
+ * visorchannel_create_guts() - creates the struct visorchannel abstraction
+ * for a data area in memory, but does NOT modify
+ * this data area
+ * @physaddr: physical address of start of channel
+ * @channel_bytes: size of the channel in bytes; this may 0 if the channel has
+ * already been initialized in memory (which is true for all
+ * channels provided to guest environments by the s-Par
+ * back-end), in which case the actual channel size will be
+ * read from the channel header in memory
+ * @gfp: gfp_t to use when allocating memory for the data struct
+ * @guid: uuid that identifies channel type; this may 0 if the channel
+ * has already been initialized in memory (which is true for all
+ * channels provided to guest environments by the s-Par
+ * back-end), in which case the actual channel guid will be
+ * read from the channel header in memory
+ * @needs_lock: must specify true if you have multiple threads of execution
+ * that will be calling visorchannel methods of this
+ * visorchannel at the same time
+ *
+ * Return: pointer to visorchannel that was created if successful,
+ * otherwise NULL
+ */
+static struct visorchannel *
+visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes,
+ gfp_t gfp, uuid_le guid, bool needs_lock)
{
- bool rc;
- unsigned long flags;
+ struct visorchannel *channel;
+ int err;
+ size_t size = sizeof(struct channel_header);
- if (channel->needs_lock) {
- spin_lock_irqsave(&channel->insert_lock, flags);
- rc = signalinsert_inner(channel, queue, msg);
- spin_unlock_irqrestore(&channel->insert_lock, flags);
- } else {
- rc = signalinsert_inner(channel, queue, msg);
+ if (physaddr == 0)
+ return NULL;
+
+ channel = kzalloc(sizeof(*channel), gfp);
+ if (!channel)
+ return NULL;
+
+ channel->needs_lock = needs_lock;
+ spin_lock_init(&channel->insert_lock);
+ spin_lock_init(&channel->remove_lock);
+
+ /*
+ * Video driver constains the efi framebuffer so it will get a
+ * conflict resource when requesting its full mem region. Since
+ * we are only using the efi framebuffer for video we can ignore
+ * this. Remember that we haven't requested it so we don't try to
+ * release later on.
+ */
+ channel->requested = request_mem_region(physaddr, size, MYDRVNAME);
+ if (!channel->requested) {
+ if (uuid_le_cmp(guid, spar_video_guid)) {
+ /* Not the video channel we care about this */
+ goto err_destroy_channel;
+ }
}
- return rc;
-}
-EXPORT_SYMBOL_GPL(visorchannel_signalinsert);
+ channel->mapped = memremap(physaddr, size, MEMREMAP_WB);
+ if (!channel->mapped) {
+ release_mem_region(physaddr, size);
+ goto err_destroy_channel;
+ }
-int
-visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue)
-{
- struct signal_queue_header sig_hdr;
- u32 slots_avail, slots_used;
- u32 head, tail;
+ channel->physaddr = physaddr;
+ channel->nbytes = size;
- if (!sig_read_header(channel, queue, &sig_hdr))
- return 0;
- head = sig_hdr.head;
- tail = sig_hdr.tail;
- if (head < tail)
- head = head + sig_hdr.max_slots;
- slots_used = head - tail;
- slots_avail = sig_hdr.max_signals - slots_used;
- return (int)slots_avail;
-}
-EXPORT_SYMBOL_GPL(visorchannel_signalqueue_slots_avail);
+ err = visorchannel_read(channel, 0, &channel->chan_hdr,
+ sizeof(struct channel_header));
+ if (err)
+ goto err_destroy_channel;
-int
-visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue)
-{
- struct signal_queue_header sig_hdr;
+ /* we had better be a CLIENT of this channel */
+ if (channel_bytes == 0)
+ channel_bytes = (ulong)channel->chan_hdr.size;
+ if (uuid_le_cmp(guid, NULL_UUID_LE) == 0)
+ guid = channel->chan_hdr.chtype;
- if (!sig_read_header(channel, queue, &sig_hdr))
- return 0;
- return (int)sig_hdr.max_signals;
+ memunmap(channel->mapped);
+ if (channel->requested)
+ release_mem_region(channel->physaddr, channel->nbytes);
+ channel->mapped = NULL;
+ channel->requested = request_mem_region(channel->physaddr,
+ channel_bytes, MYDRVNAME);
+ if (!channel->requested) {
+ if (uuid_le_cmp(guid, spar_video_guid)) {
+ /* Different we care about this */
+ goto err_destroy_channel;
+ }
+ }
+
+ channel->mapped = memremap(channel->physaddr, channel_bytes,
+ MEMREMAP_WB);
+ if (!channel->mapped) {
+ release_mem_region(channel->physaddr, channel_bytes);
+ goto err_destroy_channel;
+ }
+
+ channel->nbytes = channel_bytes;
+ channel->guid = guid;
+ return channel;
+
+err_destroy_channel:
+ visorchannel_destroy(channel);
+ return NULL;
}
-EXPORT_SYMBOL_GPL(visorchannel_signalqueue_max_slots);
-static void
-sigqueue_debug(struct signal_queue_header *q, int which, struct seq_file *seq)
+struct visorchannel *
+visorchannel_create(u64 physaddr, unsigned long channel_bytes,
+ gfp_t gfp, uuid_le guid)
{
- seq_printf(seq, "Signal Queue #%d\n", which);
- seq_printf(seq, " VersionId = %lu\n", (ulong)q->version);
- seq_printf(seq, " Type = %lu\n", (ulong)q->chtype);
- seq_printf(seq, " oSignalBase = %llu\n",
- (long long)q->sig_base_offset);
- seq_printf(seq, " SignalSize = %lu\n", (ulong)q->signal_size);
- seq_printf(seq, " MaxSignalSlots = %lu\n",
- (ulong)q->max_slots);
- seq_printf(seq, " MaxSignals = %lu\n", (ulong)q->max_signals);
- seq_printf(seq, " FeatureFlags = %-16.16Lx\n",
- (long long)q->features);
- seq_printf(seq, " NumSignalsSent = %llu\n",
- (long long)q->num_sent);
- seq_printf(seq, " NumSignalsReceived = %llu\n",
- (long long)q->num_received);
- seq_printf(seq, " NumOverflows = %llu\n",
- (long long)q->num_overflows);
- seq_printf(seq, " Head = %lu\n", (ulong)q->head);
- seq_printf(seq, " Tail = %lu\n", (ulong)q->tail);
+ return visorchannel_create_guts(physaddr, channel_bytes, gfp, guid,
+ false);
}
-void
-visorchannel_debug(struct visorchannel *channel, int num_queues,
- struct seq_file *seq, u32 off)
+struct visorchannel *
+visorchannel_create_with_lock(u64 physaddr, unsigned long channel_bytes,
+ gfp_t gfp, uuid_le guid)
{
- u64 addr = 0;
- ulong nbytes = 0, nbytes_region = 0;
- struct channel_header hdr;
- struct channel_header *phdr = &hdr;
- int i = 0;
- int errcode = 0;
+ return visorchannel_create_guts(physaddr, channel_bytes, gfp, guid,
+ true);
+}
- if (!channel)
- return;
+/**
+ * visorchannel_signalinsert() - inserts a message into the designated
+ * channel/queue
+ * @channel: the channel the message will be added to
+ * @queue: the queue the message will be added to
+ * @msg: the message to insert
+ *
+ * Return: boolean indicating whether the insertion succeeded or failed
+ */
+bool
+visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg)
+{
+ bool rc;
+ unsigned long flags;
- addr = visorchannel_get_physaddr(channel);
- nbytes_region = visorchannel_get_nbytes(channel);
- errcode = visorchannel_read(channel, off,
- phdr, sizeof(struct channel_header));
- if (errcode < 0) {
- seq_printf(seq,
- "Read of channel header failed with errcode=%d)\n",
- errcode);
- if (off == 0) {
- phdr = &channel->chan_hdr;
- seq_puts(seq, "(following data may be stale)\n");
- } else {
- return;
- }
+ if (channel->needs_lock) {
+ spin_lock_irqsave(&channel->insert_lock, flags);
+ rc = signalinsert_inner(channel, queue, msg);
+ spin_unlock_irqrestore(&channel->insert_lock, flags);
+ } else {
+ rc = signalinsert_inner(channel, queue, msg);
}
- nbytes = (ulong)(phdr->size);
- seq_printf(seq, "--- Begin channel @0x%-16.16Lx for 0x%lx bytes (region=0x%lx bytes) ---\n",
- addr + off, nbytes, nbytes_region);
- seq_printf(seq, "Type = %pUL\n", &phdr->chtype);
- seq_printf(seq, "ZoneGuid = %pUL\n", &phdr->zone_uuid);
- seq_printf(seq, "Signature = 0x%-16.16Lx\n",
- (long long)phdr->signature);
- seq_printf(seq, "LegacyState = %lu\n", (ulong)phdr->legacy_state);
- seq_printf(seq, "SrvState = %lu\n", (ulong)phdr->srv_state);
- seq_printf(seq, "CliStateBoot = %lu\n", (ulong)phdr->cli_state_boot);
- seq_printf(seq, "CliStateOS = %lu\n", (ulong)phdr->cli_state_os);
- seq_printf(seq, "HeaderSize = %lu\n", (ulong)phdr->header_size);
- seq_printf(seq, "Size = %llu\n", (long long)phdr->size);
- seq_printf(seq, "Features = 0x%-16.16llx\n",
- (long long)phdr->features);
- seq_printf(seq, "PartitionHandle = 0x%-16.16llx\n",
- (long long)phdr->partition_handle);
- seq_printf(seq, "Handle = 0x%-16.16llx\n",
- (long long)phdr->handle);
- seq_printf(seq, "VersionId = %lu\n", (ulong)phdr->version_id);
- seq_printf(seq, "oChannelSpace = %llu\n",
- (long long)phdr->ch_space_offset);
- if ((phdr->ch_space_offset == 0) || (errcode < 0))
- ;
- else
- for (i = 0; i < num_queues; i++) {
- struct signal_queue_header q;
-
- errcode = visorchannel_read(channel,
- off +
- phdr->ch_space_offset +
- (i * sizeof(q)),
- &q, sizeof(q));
- if (errcode < 0) {
- seq_printf(seq,
- "failed to read signal queue #%d from channel @0x%-16.16Lx errcode=%d\n",
- i, addr, errcode);
- continue;
- }
- sigqueue_debug(&q, i, seq);
- }
- seq_printf(seq, "--- End channel @0x%-16.16Lx for 0x%lx bytes ---\n",
- addr + off, nbytes);
+
+ return rc;
}
-EXPORT_SYMBOL_GPL(visorchannel_debug);
+EXPORT_SYMBOL_GPL(visorchannel_signalinsert);