Merge remote-tracking branch 'staging/staging-next'
[deliverable/linux.git] / drivers / staging / unisys / visorbus / visorchannel.c
index 43373582cf1d52b1437236df8c263cc96437f034..b84c8d800c8e26e50137beb85daebd4b7799c2e1 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 /*
- *  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.
  */
 
@@ -55,110 +55,6 @@ struct visorchannel {
        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)
 {
@@ -171,21 +67,18 @@ 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)
@@ -193,28 +86,24 @@ 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,
@@ -223,8 +112,13 @@ 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)
 {
@@ -243,7 +137,6 @@ visorchannel_read(struct visorchannel *channel, ulong offset,
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(visorchannel_read);
 
 int
 visorchannel_write(struct visorchannel *channel, ulong offset,
@@ -265,67 +158,32 @@ 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,                                     \
@@ -400,7 +258,8 @@ signalremove_inner(struct visorchannel *channel, u32 queue, void *msg)
                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 */
@@ -411,6 +270,15 @@ signalremove_inner(struct visorchannel *channel, u32 queue, void *msg)
        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)
 {
@@ -429,6 +297,15 @@ 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)
 {
@@ -475,7 +352,8 @@ signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg)
 
        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 */
@@ -487,149 +365,151 @@ signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg)
        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);
This page took 0.031913 seconds and 5 git commands to generate.