diff options
Diffstat (limited to 'drivers/staging/unisys/visorbus/visorchannel.c')
-rw-r--r-- | drivers/staging/unisys/visorbus/visorchannel.c | 59 |
1 files changed, 42 insertions, 17 deletions
diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index 20b63496e..2693c46af 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -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); } |