1 /* Copyright (C) 2010 - 2013 UNISYS CORPORATION
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or (at
7 * your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
12 * NON INFRINGEMENT. See the GNU General Public License for more
16 #include <linux/kernel.h>
17 #ifdef CONFIG_MODVERSIONS
18 #include <config/modversions.h>
20 #include <linux/module.h>
21 #include <linux/init.h> /* for module_init and module_exit */
22 #include <linux/slab.h> /* for memcpy */
23 #include <linux/types.h>
25 /* Implementation of exported functions for Supervisor channels */
29 * Routine Description:
30 * Tries to insert the prebuilt signal pointed to by pSignal into the nth
31 * Queue of the Channel pointed to by pChannel
34 * pChannel: (IN) points to the IO Channel
35 * Queue: (IN) nth Queue of the IO Channel
36 * pSignal: (IN) pointer to the signal
39 * - pChannel, Queue and pSignal are valid.
40 * - If insertion fails due to a full queue, the caller will determine the
41 * retry policy (e.g. wait & try again, report an error, etc.).
44 * 1 if the insertion succeeds, 0 if the queue was full.
47 visor_signal_insert(CHANNEL_HEADER __iomem *pChannel, U32 Queue, void *pSignal)
49 void __iomem *psignal;
50 unsigned int head, tail, nof;
52 SIGNAL_QUEUE_HEADER __iomem *pqhdr =
53 (SIGNAL_QUEUE_HEADER __iomem *)
54 ((char __iomem *) pChannel + readq(&pChannel->oChannelSpace))
57 /* capture current head and tail */
58 head = readl(&pqhdr->Head);
59 tail = readl(&pqhdr->Tail);
61 /* queue is full if (head + 1) % n equals tail */
62 if (((head + 1) % readl(&pqhdr->MaxSignalSlots)) == tail) {
63 nof = readq(&pqhdr->NumOverflows) + 1;
64 writeq(nof, &pqhdr->NumOverflows);
68 /* increment the head index */
69 head = (head + 1) % readl(&pqhdr->MaxSignalSlots);
71 /* copy signal to the head location from the area pointed to
74 psignal = (char __iomem *)pqhdr + readq(&pqhdr->oSignalBase) +
75 (head * readl(&pqhdr->SignalSize));
76 MEMCPY_TOIO(psignal, pSignal, readl(&pqhdr->SignalSize));
79 writel(head, &pqhdr->Head);
81 writeq(readq(&pqhdr->NumSignalsSent) + 1, &pqhdr->NumSignalsSent);
84 EXPORT_SYMBOL_GPL(visor_signal_insert);
87 * Routine Description:
88 * Removes one signal from Channel pChannel's nth Queue at the
89 * time of the call and copies it into the memory pointed to by
93 * pChannel: (IN) points to the IO Channel
94 * Queue: (IN) nth Queue of the IO Channel
95 * pSignal: (IN) pointer to where the signals are to be copied
98 * - pChannel and Queue are valid.
99 * - pSignal points to a memory area large enough to hold queue's SignalSize
102 * 1 if the removal succeeds, 0 if the queue was empty.
105 visor_signal_remove(CHANNEL_HEADER __iomem *pChannel, U32 Queue, void *pSignal)
107 void __iomem *psource;
108 unsigned int head, tail;
109 SIGNAL_QUEUE_HEADER __iomem *pqhdr =
110 (SIGNAL_QUEUE_HEADER __iomem *) ((char __iomem *) pChannel +
111 readq(&pChannel->oChannelSpace)) + Queue;
113 /* capture current head and tail */
114 head = readl(&pqhdr->Head);
115 tail = readl(&pqhdr->Tail);
117 /* queue is empty if the head index equals the tail index */
119 writeq(readq(&pqhdr->NumEmptyCnt) + 1, &pqhdr->NumEmptyCnt);
123 /* advance past the 'empty' front slot */
124 tail = (tail + 1) % readl(&pqhdr->MaxSignalSlots);
126 /* copy signal from tail location to the area pointed to by pSignal */
127 psource = (char __iomem *) pqhdr + readq(&pqhdr->oSignalBase) +
128 (tail * readl(&pqhdr->SignalSize));
129 MEMCPY_FROMIO(pSignal, psource, readl(&pqhdr->SignalSize));
132 writel(tail, &pqhdr->Tail);
134 writeq(readq(&pqhdr->NumSignalsReceived) + 1,
135 &pqhdr->NumSignalsReceived);
138 EXPORT_SYMBOL_GPL(visor_signal_remove);
141 * Routine Description:
142 * Removes all signals present in Channel pChannel's nth Queue at the
143 * time of the call and copies them into the memory pointed to by
144 * pSignal. Returns the # of signals copied as the value of the routine.
147 * pChannel: (IN) points to the IO Channel
148 * Queue: (IN) nth Queue of the IO Channel
149 * pSignal: (IN) pointer to where the signals are to be copied
152 * - pChannel and Queue are valid.
153 * - pSignal points to a memory area large enough to hold Queue's MaxSignals
154 * # of signals, each of which is Queue's SignalSize.
157 * # of signals copied.
160 SignalRemoveAll(pCHANNEL_HEADER pChannel, U32 Queue, void *pSignal)
163 unsigned int head, tail, signalCount = 0;
164 pSIGNAL_QUEUE_HEADER pqhdr =
165 (pSIGNAL_QUEUE_HEADER) ((char *) pChannel +
166 pChannel->oChannelSpace) + Queue;
168 /* capture current head and tail */
172 /* queue is empty if the head index equals the tail index */
176 while (head != tail) {
177 /* advance past the 'empty' front slot */
178 tail = (tail + 1) % pqhdr->MaxSignalSlots;
180 /* copy signal from tail location to the area pointed
184 (char *) pqhdr + pqhdr->oSignalBase +
185 (tail * pqhdr->SignalSize);
186 MEMCPY((char *) pSignal + (pqhdr->SignalSize * signalCount),
187 psource, pqhdr->SignalSize);
193 pqhdr->NumSignalsReceived++;
200 * Routine Description:
201 * Determine whether a signal queue is empty.
204 * pChannel: (IN) points to the IO Channel
205 * Queue: (IN) nth Queue of the IO Channel
208 * 1 if the signal queue is empty, 0 otherwise.
211 visor_signalqueue_empty(CHANNEL_HEADER __iomem *pChannel, U32 Queue)
213 SIGNAL_QUEUE_HEADER __iomem *pqhdr =
214 (SIGNAL_QUEUE_HEADER __iomem *) ((char __iomem *) pChannel +
215 readq(&pChannel->oChannelSpace)) + Queue;
216 return readl(&pqhdr->Head) == readl(&pqhdr->Tail);
218 EXPORT_SYMBOL_GPL(visor_signalqueue_empty);