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
);