]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/staging/unisys/visorbus/visorchannel.c
Merge tag 'libnvdimm-for-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm...
[mirror_ubuntu-bionic-kernel.git] / drivers / staging / unisys / visorbus / visorchannel.c
index 20b63496e9f215a51e6385fd0d2e4b96b8758e75..2693c46afdc0bd7b284cb11254d8d31c5987c1b0 100644 (file)
@@ -1,12 +1,11 @@
 /* visorchannel_funcs.c
  *
- * Copyright (C) 2010 - 2013 UNISYS CORPORATION
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
  * All rights reserved.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -21,6 +20,7 @@
  */
 
 #include <linux/uuid.h>
+#include <linux/io.h>
 
 #include "version.h"
 #include "visorbus.h"
@@ -36,7 +36,7 @@ static const uuid_le spar_video_guid = SPAR_CONSOLEVIDEO_CHANNEL_PROTOCOL_GUID;
 struct visorchannel {
        u64 physaddr;
        ulong nbytes;
-       void __iomem *mapped;
+       void *mapped;
        bool requested;
        struct channel_header chan_hdr;
        uuid_le guid;
@@ -93,7 +93,7 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes,
                }
        }
 
-       channel->mapped = ioremap_cache(physaddr, size);
+       channel->mapped = memremap(physaddr, size, MEMREMAP_WB);
        if (!channel->mapped) {
                release_mem_region(physaddr, size);
                goto cleanup;
@@ -113,7 +113,7 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes,
        if (uuid_le_cmp(guid, NULL_UUID_LE) == 0)
                guid = channel->chan_hdr.chtype;
 
-       iounmap(channel->mapped);
+       memunmap(channel->mapped);
        if (channel->requested)
                release_mem_region(channel->physaddr, channel->nbytes);
        channel->mapped = NULL;
@@ -126,7 +126,8 @@ visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes,
                }
        }
 
-       channel->mapped = ioremap_cache(channel->physaddr, channel_bytes);
+       channel->mapped = memremap(channel->physaddr, channel_bytes,
+                       MEMREMAP_WB);
        if (!channel->mapped) {
                release_mem_region(channel->physaddr, channel_bytes);
                goto cleanup;
@@ -167,7 +168,7 @@ visorchannel_destroy(struct visorchannel *channel)
        if (!channel)
                return;
        if (channel->mapped) {
-               iounmap(channel->mapped);
+               memunmap(channel->mapped);
                if (channel->requested)
                        release_mem_region(channel->physaddr, channel->nbytes);
        }
@@ -241,7 +242,7 @@ visorchannel_read(struct visorchannel *channel, ulong offset,
        if (offset + nbytes > channel->nbytes)
                return -EIO;
 
-       memcpy_fromio(local, channel->mapped + offset, nbytes);
+       memcpy(local, channel->mapped + offset, nbytes);
 
        return 0;
 }
@@ -259,10 +260,11 @@ visorchannel_write(struct visorchannel *channel, ulong offset,
 
        if (offset < chdr_size) {
                copy_size = min(chdr_size - offset, nbytes);
-               memcpy(&channel->chan_hdr + offset, local, copy_size);
+               memcpy(((char *)(&channel->chan_hdr)) + offset,
+                      local, copy_size);
        }
 
-       memcpy_toio(channel->mapped + offset, local, nbytes);
+       memcpy(channel->mapped + offset, local, nbytes);
 
        return 0;
 }
@@ -416,11 +418,12 @@ bool
 visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg)
 {
        bool rc;
+       unsigned long flags;
 
        if (channel->needs_lock) {
-               spin_lock(&channel->remove_lock);
+               spin_lock_irqsave(&channel->remove_lock, flags);
                rc = signalremove_inner(channel, queue, msg);
-               spin_unlock(&channel->remove_lock);
+               spin_unlock_irqrestore(&channel->remove_lock, flags);
        } else {
                rc = signalremove_inner(channel, queue, msg);
        }
@@ -429,6 +432,27 @@ visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg)
 }
 EXPORT_SYMBOL_GPL(visorchannel_signalremove);
 
+bool
+visorchannel_signalempty(struct visorchannel *channel, u32 queue)
+{
+       unsigned long flags = 0;
+       struct signal_queue_header sig_hdr;
+       bool rc = false;
+
+       if (channel->needs_lock)
+               spin_lock_irqsave(&channel->remove_lock, flags);
+
+       if (!sig_read_header(channel, queue, &sig_hdr))
+               rc = true;
+       if (sig_hdr.head == sig_hdr.tail)
+               rc = true;
+       if (channel->needs_lock)
+               spin_unlock_irqrestore(&channel->remove_lock, flags);
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalempty);
+
 static bool
 signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg)
 {
@@ -470,11 +494,12 @@ bool
 visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg)
 {
        bool rc;
+       unsigned long flags;
 
        if (channel->needs_lock) {
-               spin_lock(&channel->insert_lock);
+               spin_lock_irqsave(&channel->insert_lock, flags);
                rc = signalinsert_inner(channel, queue, msg);
-               spin_unlock(&channel->insert_lock);
+               spin_unlock_irqrestore(&channel->insert_lock, flags);
        } else {
                rc = signalinsert_inner(channel, queue, msg);
        }