mirror of https://gitee.com/openkylin/linux.git
staging: visorchannelstub driver to provide channel support routines
The visorchannelstub module provides support routines for storing and retrieving data from a channel. Signed-off-by: Ken Cox <jkc@redhat.com> Cc: Ben Romer <sparmaintainer@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
12e364b9f0
commit
7b2a2d8383
|
@ -12,5 +12,6 @@ if UNISYSSPAR
|
||||||
source "drivers/staging/unisys/visorutil/Kconfig"
|
source "drivers/staging/unisys/visorutil/Kconfig"
|
||||||
source "drivers/staging/unisys/visorchannel/Kconfig"
|
source "drivers/staging/unisys/visorchannel/Kconfig"
|
||||||
source "drivers/staging/unisys/visorchipset/Kconfig"
|
source "drivers/staging/unisys/visorchipset/Kconfig"
|
||||||
|
source "drivers/staging/unisys/channels/Kconfig"
|
||||||
|
|
||||||
endif # UNISYSSPAR
|
endif # UNISYSSPAR
|
||||||
|
|
|
@ -4,4 +4,5 @@
|
||||||
obj-$(CONFIG_UNISYS_VISORUTIL) += visorutil/
|
obj-$(CONFIG_UNISYS_VISORUTIL) += visorutil/
|
||||||
obj-$(CONFIG_UNISYS_VISORCHANNEL) += visorchannel/
|
obj-$(CONFIG_UNISYS_VISORCHANNEL) += visorchannel/
|
||||||
obj-$(CONFIG_UNISYS_VISORCHIPSET) += visorchipset/
|
obj-$(CONFIG_UNISYS_VISORCHIPSET) += visorchipset/
|
||||||
|
obj-$(CONFIG_UNISYS_CHANNELSTUB) += channels/
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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 */
|
|
@ -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
|
Loading…
Reference in New Issue