[patch V2 4/8] staging: visorchannelstub driver to provide channel support routines

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The visorchannelstub module provides support routines for storing and
retrieving data from a channel.

Signed-off-by: Ken Cox <jkc@xxxxxxxxxx>
Cc: Ben Romer <sparmaintainer@xxxxxxxxxx>

Index: upstream-staging/drivers/staging/unisys/Kconfig
===================================================================
--- upstream-staging.orig/drivers/staging/unisys/Kconfig
+++ upstream-staging/drivers/staging/unisys/Kconfig
@@ -12,5 +12,6 @@ if UNISYSSPAR
 source "drivers/staging/unisys/visorutil/Kconfig"
 source "drivers/staging/unisys/visorchannel/Kconfig"
 source "drivers/staging/unisys/visorchipset/Kconfig"
+source "drivers/staging/unisys/channels/Kconfig"
 
 endif # UNISYSSPAR
Index: upstream-staging/drivers/staging/unisys/Makefile
===================================================================
--- upstream-staging.orig/drivers/staging/unisys/Makefile
+++ upstream-staging/drivers/staging/unisys/Makefile
@@ -4,4 +4,5 @@
 obj-$(CONFIG_UNISYS_VISORUTIL)		+= visorutil/
 obj-$(CONFIG_UNISYS_VISORCHANNEL)	+= visorchannel/
 obj-$(CONFIG_UNISYS_VISORCHIPSET)	+= visorchipset/
+obj-$(CONFIG_UNISYS_CHANNELSTUB)	+= channels/
 
Index: upstream-staging/drivers/staging/unisys/channels/Kconfig
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/channels/Kconfig
@@ -0,0 +1,10 @@
+#
+# Unisys channels configuration
+#
+
+config UNISYS_CHANNELSTUB
+	tristate "Unisys channelstub driver"
+	depends on UNISYSSPAR
+	---help---
+	If you say Y here, you will enable the Unisys channels driver.
+
Index: upstream-staging/drivers/staging/unisys/channels/Makefile
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/channels/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for Unisys channelstub
+#
+
+obj-$(CONFIG_UNISYS_CHANNELSTUB)	+= visorchannelstub.o
+
+visorchannelstub-y := channel.o chanstub.o
+
+ccflags-y += -Idrivers/staging/unisys/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include
+ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels
+ccflags-y += -DCONFIG_SPAR_GUEST -DGUESTDRIVERBUILD -DNOAUTOVERSION
+
Index: upstream-staging/drivers/staging/unisys/channels/channel.c
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/channels/channel.c
@@ -0,0 +1,307 @@
+/* Copyright © 2010 - 2013 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 distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include <linux/kernel.h>
+#ifdef CONFIG_MODVERSIONS
+#include <config/modversions.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>		/* for module_init and module_exit */
+#include <linux/slab.h>		/* for memcpy */
+#include <linux/types.h>
+
+/* Implementation of exported functions for Supervisor channels */
+#include "channel.h"
+
+/*
+ * Routine Description:
+ * Tries to insert the prebuilt signal pointed to by pSignal into the nth
+ * Queue of the Channel pointed to by pChannel
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ * pSignal: (IN) pointer to the signal
+ *
+ * Assumptions:
+ * - pChannel, Queue and pSignal are valid.
+ * - If insertion fails due to a full queue, the caller will determine the
+ * retry policy (e.g. wait & try again, report an error, etc.).
+ *
+ * Return value:
+ * 1 if the insertion succeeds, 0 if the queue was full.
+ */
+unsigned char
+SignalInsert(pCHANNEL_HEADER pChannel, U32 Queue, void *pSignal)
+{
+	void *psignal;
+	unsigned int head, tail;
+	pSIGNAL_QUEUE_HEADER pqhdr =
+	    (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+				    pChannel->oChannelSpace) + Queue;
+
+	/* capture current head and tail */
+	head = pqhdr->Head;
+	tail = pqhdr->Tail;
+
+	/* queue is full if (head + 1) % n equals tail */
+	if (((head + 1) % pqhdr->MaxSignalSlots) == tail) {
+		pqhdr->NumOverflows++;
+		return 0;
+	}
+
+	/* increment the head index */
+	head = (head + 1) % pqhdr->MaxSignalSlots;
+
+	/* copy signal to the head location from the area pointed to
+	 * by pSignal
+	 */
+	psignal =
+	    (char *) pqhdr + pqhdr->oSignalBase + (head * pqhdr->SignalSize);
+	MEMCPY(psignal, pSignal, pqhdr->SignalSize);
+
+	VolatileBarrier();
+	pqhdr->Head = head;
+
+	pqhdr->NumSignalsSent++;
+	return 1;
+}
+EXPORT_SYMBOL_GPL(SignalInsert);
+
+/*
+ * Routine Description:
+ * Removes one signal from Channel pChannel's nth Queue at the
+ * time of the call and copies it into the memory pointed to by
+ * pSignal.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ * pSignal: (IN) pointer to where the signals are to be copied
+ *
+ * Assumptions:
+ * - pChannel and Queue are valid.
+ * - pSignal points to a memory area large enough to hold queue's SignalSize
+ *
+ * Return value:
+ * 1 if the removal succeeds, 0 if the queue was empty.
+ */
+unsigned char
+SignalRemove(pCHANNEL_HEADER pChannel, U32 Queue, void *pSignal)
+{
+	void *psource;
+	unsigned int head, tail;
+	pSIGNAL_QUEUE_HEADER pqhdr =
+	    (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+				    pChannel->oChannelSpace) + Queue;
+
+	/* capture current head and tail */
+	head = pqhdr->Head;
+	tail = pqhdr->Tail;
+
+	/* queue is empty if the head index equals the tail index */
+	if (head == tail) {
+		pqhdr->NumEmptyCnt++;
+		return 0;
+	}
+
+	/* advance past the 'empty' front slot */
+	tail = (tail + 1) % pqhdr->MaxSignalSlots;
+
+	/* copy signal from tail location to the area pointed to by pSignal */
+	psource =
+	    (char *) pqhdr + pqhdr->oSignalBase + (tail * pqhdr->SignalSize);
+	MEMCPY(pSignal, psource, pqhdr->SignalSize);
+
+	VolatileBarrier();
+	pqhdr->Tail = tail;
+
+	pqhdr->NumSignalsReceived++;
+	return 1;
+}
+EXPORT_SYMBOL_GPL(SignalRemove);
+
+/*
+ * Routine Description:
+ * Removes all signals present in Channel pChannel's nth Queue at the
+ * time of the call and copies them into the memory pointed to by
+ * pSignal.  Returns the # of signals copied as the value of the routine.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ * pSignal: (IN) pointer to where the signals are to be copied
+ *
+ * Assumptions:
+ * - pChannel and Queue are valid.
+ * - pSignal points to a memory area large enough to hold Queue's MaxSignals
+ * # of signals, each of which is Queue's SignalSize.
+ *
+ * Return value:
+ * # of signals copied.
+ */
+unsigned int
+SignalRemoveAll(pCHANNEL_HEADER pChannel, U32 Queue, void *pSignal)
+{
+	void *psource;
+	unsigned int head, tail, signalCount = 0;
+	pSIGNAL_QUEUE_HEADER pqhdr =
+	    (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+				    pChannel->oChannelSpace) + Queue;
+
+	/* capture current head and tail */
+	head = pqhdr->Head;
+	tail = pqhdr->Tail;
+
+	/* queue is empty if the head index equals the tail index */
+	if (head == tail)
+		return 0;
+
+	while (head != tail) {
+		/* advance past the 'empty' front slot */
+		tail = (tail + 1) % pqhdr->MaxSignalSlots;
+
+		/* copy signal from tail location to the area pointed
+		 * to by pSignal
+		 */
+		psource =
+		    (char *) pqhdr + pqhdr->oSignalBase +
+		    (tail * pqhdr->SignalSize);
+		MEMCPY((char *) pSignal + (pqhdr->SignalSize * signalCount),
+		       psource, pqhdr->SignalSize);
+
+		VolatileBarrier();
+		pqhdr->Tail = tail;
+
+		signalCount++;
+		pqhdr->NumSignalsReceived++;
+	}
+
+	return signalCount;
+}
+
+/*
+ * Routine Description:
+ * Copies one signal from channel pChannel's nth Queue at the given position
+ * at the time of the call into the memory pointed to by pSignal.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ * Position: (IN) nth entry in Queue of the IO Channel
+ * pSignal: (IN) pointer to where the signals are to be copied
+ *
+ * Assumptions:
+ * - pChannel and Queue are valid.
+ * - pSignal points to a memory area large enough to hold queue's SignalSize
+ *
+ * Return value:
+ * 1 if the copy succeeds, 0 if the queue was empty or Position was invalid.
+ */
+unsigned char
+SignalPeek(pCHANNEL_HEADER pChannel, U32 Queue, U32 Position, void *pSignal)
+{
+	void *psignal;
+	unsigned int head, tail;
+	pSIGNAL_QUEUE_HEADER pqhdr =
+	    (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+				    pChannel->oChannelSpace) + Queue;
+
+	head = pqhdr->Head;
+	tail = pqhdr->Tail;
+
+	/* check if Position is out of range or queue is empty */
+	if (Position >= pqhdr->MaxSignalSlots || Position == tail
+	    || head == tail)
+		return 0;
+
+	/* check if Position is between tail and head */
+	if (head > tail) {
+		if (Position > head || Position < tail)
+			return 0;
+	} else if ((Position > head) && (Position < tail))
+		return 0;
+
+	/* copy signal from Position location to the area pointed to
+	 * by pSignal
+	 */
+	psignal =
+	    (char *) pqhdr + pqhdr->oSignalBase +
+	    (Position * pqhdr->SignalSize);
+	MEMCPY(pSignal, psignal, pqhdr->SignalSize);
+
+	return 1;
+}
+
+/*
+ * Routine Description:
+ * Determine whether a signal queue is empty.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ *
+ * Return value:
+ * 1 if the signal queue is empty, 0 otherwise.
+ */
+unsigned char
+SignalQueueIsEmpty(pCHANNEL_HEADER pChannel, U32 Queue)
+{
+	pSIGNAL_QUEUE_HEADER pqhdr =
+	    (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+				    pChannel->oChannelSpace) + Queue;
+	return pqhdr->Head == pqhdr->Tail;
+}
+EXPORT_SYMBOL_GPL(SignalQueueIsEmpty);
+
+/*
+ * Routine Description:
+ * Determine whether a signal queue is empty.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ *
+ * Return value:
+ * 1 if the signal queue has 1 element, 0 otherwise.
+ */
+unsigned char
+SignalQueueHasOneElement(pCHANNEL_HEADER pChannel, U32 Queue)
+{
+	pSIGNAL_QUEUE_HEADER pqhdr =
+	    (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+				    pChannel->oChannelSpace) + Queue;
+	return ((pqhdr->Tail + 1) % pqhdr->MaxSignalSlots) == pqhdr->Head;
+}
+
+/*
+ * Routine Description:
+ * Determine whether a signal queue is full.
+ *
+ * Parameters:
+ * pChannel: (IN) points to the IO Channel
+ * Queue: (IN) nth Queue of the IO Channel
+ *
+ * Return value:
+ * 1 if the signal queue is full, 0 otherwise.
+ */
+unsigned char
+SignalQueueIsFull(pCHANNEL_HEADER pChannel, U32 Queue)
+{
+	pSIGNAL_QUEUE_HEADER pqhdr =
+	    (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
+				    pChannel->oChannelSpace) + Queue;
+	return ((pqhdr->Head + 1) % pqhdr->MaxSignalSlots) == pqhdr->Tail;
+}
Index: upstream-staging/drivers/staging/unisys/channels/chanstub.c
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/channels/chanstub.c
@@ -0,0 +1,70 @@
+/* Copyright © 2010 - 2013 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 distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#define EXPORT_SYMTAB
+#include <linux/kernel.h>
+#ifdef CONFIG_MODVERSIONS
+#include <config/modversions.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>		/* for module_init and module_exit */
+#include <linux/slab.h>		/* for memcpy */
+#include <linux/types.h>
+
+#include "channel.h"
+#include "chanstub.h"
+#include "version.h"
+
+__init int
+channel_mod_init(void)
+{
+	return 0;
+}
+
+__exit void
+channel_mod_exit(void)
+{
+}
+
+unsigned char
+SignalInsert_withLock(pCHANNEL_HEADER pChannel, U32 Queue,
+		      void *pSignal, spinlock_t *lock)
+{
+	unsigned char result;
+	unsigned long flags;
+	spin_lock_irqsave(lock, flags);
+	result = SignalInsert(pChannel, Queue, pSignal);
+	spin_unlock_irqrestore(lock, flags);
+	return result;
+}
+
+unsigned char
+SignalRemove_withLock(pCHANNEL_HEADER pChannel, U32 Queue,
+		      void *pSignal, spinlock_t *lock)
+{
+	unsigned char result;
+	spin_lock(lock);
+	result = SignalRemove(pChannel, Queue, pSignal);
+	spin_unlock(lock);
+	return result;
+}
+
+module_init(channel_mod_init);
+module_exit(channel_mod_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bryan Glaudel");
+MODULE_ALIAS("uischan");
+	/* this is extracted during depmod and kept in modules.dep */
Index: upstream-staging/drivers/staging/unisys/channels/chanstub.h
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/channels/chanstub.h
@@ -0,0 +1,23 @@
+/* Copyright © 2010 - 2013 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 distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __CHANSTUB_H__
+#define __CHANSTUB_H__
+unsigned char SignalInsert_withLock(pCHANNEL_HEADER pChannel, U32 Queue,
+				     void *pSignal, spinlock_t *lock);
+unsigned char SignalRemove_withLock(pCHANNEL_HEADER pChannel, U32 Queue,
+				     void *pSignal, spinlock_t *lock);
+
+#endif

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux