aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/unisys/uislib/uisqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/unisys/uislib/uisqueue.c')
-rw-r--r--drivers/staging/unisys/uislib/uisqueue.c215
1 files changed, 202 insertions, 13 deletions
diff --git a/drivers/staging/unisys/uislib/uisqueue.c b/drivers/staging/unisys/uislib/uisqueue.c
index f9f8442d58c5..71bb7b608e9a 100644
--- a/drivers/staging/unisys/uislib/uisqueue.c
+++ b/drivers/staging/unisys/uislib/uisqueue.c
@@ -21,8 +21,6 @@
#include "uisutils.h"
-#include "chanstub.h"
-
/* this is shorter than using __FILE__ (full path name) in
* debug/info/error messages */
#define CURRENT_FILE_PC UISLIB_PC_uisqueue_c
@@ -33,9 +31,202 @@
/*****************************************************/
/* Exported functions */
/*****************************************************/
+
+/*
+ * 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 spar_signal_insert(struct channel_header __iomem *ch, u32 queue,
+ void *sig)
+{
+ void __iomem *psignal;
+ unsigned int head, tail, nof;
+
+ struct signal_queue_header __iomem *pqhdr =
+ (struct signal_queue_header __iomem *)
+ ((char __iomem *)ch + readq(&ch->ch_space_offset))
+ + queue;
+
+ /* capture current head and tail */
+ head = readl(&pqhdr->head);
+ tail = readl(&pqhdr->tail);
+
+ /* queue is full if (head + 1) % n equals tail */
+ if (((head + 1) % readl(&pqhdr->max_slots)) == tail) {
+ nof = readq(&pqhdr->num_overflows) + 1;
+ writeq(nof, &pqhdr->num_overflows);
+ return 0;
+ }
+
+ /* increment the head index */
+ head = (head + 1) % readl(&pqhdr->max_slots);
+
+ /* copy signal to the head location from the area pointed to
+ * by pSignal
+ */
+ psignal = (char __iomem *)pqhdr + readq(&pqhdr->sig_base_offset) +
+ (head * readl(&pqhdr->signal_size));
+ memcpy_toio(psignal, sig, readl(&pqhdr->signal_size));
+
+ mb(); /* channel synch */
+ writel(head, &pqhdr->head);
+
+ writeq(readq(&pqhdr->num_sent) + 1, &pqhdr->num_sent);
+ return 1;
+}
+EXPORT_SYMBOL_GPL(spar_signal_insert);
+
+/*
+ * 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
+spar_signal_remove(struct channel_header __iomem *ch, u32 queue, void *sig)
+{
+ void __iomem *psource;
+ unsigned int head, tail;
+ struct signal_queue_header __iomem *pqhdr =
+ (struct signal_queue_header __iomem *)((char __iomem *)ch +
+ readq(&ch->ch_space_offset)) + queue;
+
+ /* capture current head and tail */
+ head = readl(&pqhdr->head);
+ tail = readl(&pqhdr->tail);
+
+ /* queue is empty if the head index equals the tail index */
+ if (head == tail) {
+ writeq(readq(&pqhdr->num_empty) + 1, &pqhdr->num_empty);
+ return 0;
+ }
+
+ /* advance past the 'empty' front slot */
+ tail = (tail + 1) % readl(&pqhdr->max_slots);
+
+ /* copy signal from tail location to the area pointed to by pSignal */
+ psource = (char __iomem *)pqhdr + readq(&pqhdr->sig_base_offset) +
+ (tail * readl(&pqhdr->signal_size));
+ memcpy_fromio(sig, psource, readl(&pqhdr->signal_size));
+
+ mb(); /* channel synch */
+ writel(tail, &pqhdr->tail);
+
+ writeq(readq(&pqhdr->num_received) + 1,
+ &pqhdr->num_received);
+ return 1;
+}
+EXPORT_SYMBOL_GPL(spar_signal_remove);
+
+/*
+ * 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 spar_signal_remove_all(struct channel_header *ch, u32 queue,
+ void *sig)
+{
+ void *psource;
+ unsigned int head, tail, count = 0;
+ struct signal_queue_header *pqhdr =
+ (struct signal_queue_header *)((char *)ch +
+ ch->ch_space_offset) + 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->max_slots;
+
+ /* copy signal from tail location to the area pointed
+ * to by pSignal
+ */
+ psource =
+ (char *)pqhdr + pqhdr->sig_base_offset +
+ (tail * pqhdr->signal_size);
+ memcpy((char *)sig + (pqhdr->signal_size * count),
+ psource, pqhdr->signal_size);
+
+ mb(); /* channel synch */
+ pqhdr->tail = tail;
+
+ count++;
+ pqhdr->num_received++;
+ }
+
+ return count;
+}
+
+/*
+ * 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 spar_signalqueue_empty(struct channel_header __iomem *ch,
+ u32 queue)
+{
+ struct signal_queue_header __iomem *pqhdr =
+ (struct signal_queue_header __iomem *)((char __iomem *)ch +
+ readq(&ch->ch_space_offset)) + queue;
+ return readl(&pqhdr->head) == readl(&pqhdr->tail);
+}
+EXPORT_SYMBOL_GPL(spar_signalqueue_empty);
+
unsigned long long
uisqueue_interlocked_or(unsigned long long __iomem *tgt,
- unsigned long long set)
+ unsigned long long set)
{
unsigned long long i;
unsigned long long j;
@@ -53,7 +244,7 @@ EXPORT_SYMBOL_GPL(uisqueue_interlocked_or);
unsigned long long
uisqueue_interlocked_and(unsigned long long __iomem *tgt,
- unsigned long long set)
+ unsigned long long set)
{
unsigned long long i;
unsigned long long j;
@@ -72,22 +263,21 @@ EXPORT_SYMBOL_GPL(uisqueue_interlocked_and);
static u8
do_locked_client_insert(struct uisqueue_info *queueinfo,
unsigned int whichqueue,
- void *pSignal,
+ void *signal,
spinlock_t *lock,
- unsigned char issueInterruptIfEmpty,
- u64 interruptHandle, u8 *channelId)
+ u8 *channel_id)
{
unsigned long flags;
u8 rc = 0;
spin_lock_irqsave(lock, flags);
- if (!spar_channel_client_acquire_os(queueinfo->chan, channelId))
+ if (!spar_channel_client_acquire_os(queueinfo->chan, channel_id))
goto unlock;
- if (spar_signal_insert(queueinfo->chan, whichqueue, pSignal)) {
+ if (spar_signal_insert(queueinfo->chan, whichqueue, signal)) {
queueinfo->packets_sent++;
rc = 1;
}
- spar_channel_client_release_os(queueinfo->chan, channelId);
+ spar_channel_client_release_os(queueinfo->chan, channel_id);
unlock:
spin_unlock_irqrestore((spinlock_t *)lock, flags);
return rc;
@@ -103,9 +293,8 @@ uisqueue_put_cmdrsp_with_lock_client(struct uisqueue_info *queueinfo,
char oktowait, u8 *channel_id)
{
while (!do_locked_client_insert(queueinfo, whichqueue, cmdrsp,
- (spinlock_t *) insertlock,
- issue_irq_if_empty,
- irq_handle, channel_id)) {
+ (spinlock_t *)insertlock,
+ channel_id)) {
if (oktowait != OK_TO_WAIT) {
LOGERR("****FAILED visor_signal_insert failed; cannot wait; insert aborted\n");
return 0; /* failed to queue */