3 * Copyright (C) 2010 - 2013 UNISYS CORPORATION
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
14 * NON INFRINGEMENT. See the GNU General Public License for more
19 #include <linux/kernel.h>
20 #include <linux/module.h>
24 /* this is shorter than using __FILE__ (full path name) in
25 * debug/info/error messages */
26 #define CURRENT_FILE_PC UISLIB_PC_uisqueue_c
27 #define __MYFILE__ "uisqueue.c"
29 #define CHECK_CACHE_ALIGN 0
31 /*****************************************************/
32 /* Exported functions */
33 /*****************************************************/
36 * Routine Description:
37 * Tries to insert the prebuilt signal pointed to by pSignal into the nth
38 * Queue of the Channel pointed to by pChannel
41 * pChannel: (IN) points to the IO Channel
42 * Queue: (IN) nth Queue of the IO Channel
43 * pSignal: (IN) pointer to the signal
46 * - pChannel, Queue and pSignal are valid.
47 * - If insertion fails due to a full queue, the caller will determine the
48 * retry policy (e.g. wait & try again, report an error, etc.).
51 * 1 if the insertion succeeds, 0 if the queue was full.
53 unsigned char spar_signal_insert(struct channel_header __iomem
*ch
, u32 queue
,
56 void __iomem
*psignal
;
57 unsigned int head
, tail
, nof
;
59 struct signal_queue_header __iomem
*pqhdr
=
60 (struct signal_queue_header __iomem
*)
61 ((char __iomem
*)ch
+ readq(&ch
->ch_space_offset
))
64 /* capture current head and tail */
65 head
= readl(&pqhdr
->head
);
66 tail
= readl(&pqhdr
->tail
);
68 /* queue is full if (head + 1) % n equals tail */
69 if (((head
+ 1) % readl(&pqhdr
->max_slots
)) == tail
) {
70 nof
= readq(&pqhdr
->num_overflows
) + 1;
71 writeq(nof
, &pqhdr
->num_overflows
);
75 /* increment the head index */
76 head
= (head
+ 1) % readl(&pqhdr
->max_slots
);
78 /* copy signal to the head location from the area pointed to
81 psignal
= (char __iomem
*)pqhdr
+ readq(&pqhdr
->sig_base_offset
) +
82 (head
* readl(&pqhdr
->signal_size
));
83 memcpy_toio(psignal
, sig
, readl(&pqhdr
->signal_size
));
85 mb(); /* channel synch */
86 writel(head
, &pqhdr
->head
);
88 writeq(readq(&pqhdr
->num_sent
) + 1, &pqhdr
->num_sent
);
91 EXPORT_SYMBOL_GPL(spar_signal_insert
);
94 * Routine Description:
95 * Removes one signal from Channel pChannel's nth Queue at the
96 * time of the call and copies it into the memory pointed to by
100 * pChannel: (IN) points to the IO Channel
101 * Queue: (IN) nth Queue of the IO Channel
102 * pSignal: (IN) pointer to where the signals are to be copied
105 * - pChannel and Queue are valid.
106 * - pSignal points to a memory area large enough to hold queue's SignalSize
109 * 1 if the removal succeeds, 0 if the queue was empty.
112 spar_signal_remove(struct channel_header __iomem
*ch
, u32 queue
, void *sig
)
114 void __iomem
*psource
;
115 unsigned int head
, tail
;
116 struct signal_queue_header __iomem
*pqhdr
=
117 (struct signal_queue_header __iomem
*)((char __iomem
*)ch
+
118 readq(&ch
->ch_space_offset
)) + queue
;
120 /* capture current head and tail */
121 head
= readl(&pqhdr
->head
);
122 tail
= readl(&pqhdr
->tail
);
124 /* queue is empty if the head index equals the tail index */
126 writeq(readq(&pqhdr
->num_empty
) + 1, &pqhdr
->num_empty
);
130 /* advance past the 'empty' front slot */
131 tail
= (tail
+ 1) % readl(&pqhdr
->max_slots
);
133 /* copy signal from tail location to the area pointed to by pSignal */
134 psource
= (char __iomem
*)pqhdr
+ readq(&pqhdr
->sig_base_offset
) +
135 (tail
* readl(&pqhdr
->signal_size
));
136 memcpy_fromio(sig
, psource
, readl(&pqhdr
->signal_size
));
138 mb(); /* channel synch */
139 writel(tail
, &pqhdr
->tail
);
141 writeq(readq(&pqhdr
->num_received
) + 1,
142 &pqhdr
->num_received
);
145 EXPORT_SYMBOL_GPL(spar_signal_remove
);
148 * Routine Description:
149 * Removes all signals present in Channel pChannel's nth Queue at the
150 * time of the call and copies them into the memory pointed to by
151 * pSignal. Returns the # of signals copied as the value of the routine.
154 * pChannel: (IN) points to the IO Channel
155 * Queue: (IN) nth Queue of the IO Channel
156 * pSignal: (IN) pointer to where the signals are to be copied
159 * - pChannel and Queue are valid.
160 * - pSignal points to a memory area large enough to hold Queue's MaxSignals
161 * # of signals, each of which is Queue's SignalSize.
164 * # of signals copied.
166 unsigned int spar_signal_remove_all(struct channel_header
*ch
, u32 queue
,
170 unsigned int head
, tail
, count
= 0;
171 struct signal_queue_header
*pqhdr
=
172 (struct signal_queue_header
*)((char *)ch
+
173 ch
->ch_space_offset
) + queue
;
175 /* capture current head and tail */
179 /* queue is empty if the head index equals the tail index */
183 while (head
!= tail
) {
184 /* advance past the 'empty' front slot */
185 tail
= (tail
+ 1) % pqhdr
->max_slots
;
187 /* copy signal from tail location to the area pointed
191 (char *)pqhdr
+ pqhdr
->sig_base_offset
+
192 (tail
* pqhdr
->signal_size
);
193 memcpy((char *)sig
+ (pqhdr
->signal_size
* count
),
194 psource
, pqhdr
->signal_size
);
196 mb(); /* channel synch */
200 pqhdr
->num_received
++;
207 * Routine Description:
208 * Determine whether a signal queue is empty.
211 * pChannel: (IN) points to the IO Channel
212 * Queue: (IN) nth Queue of the IO Channel
215 * 1 if the signal queue is empty, 0 otherwise.
217 unsigned char spar_signalqueue_empty(struct channel_header __iomem
*ch
,
220 struct signal_queue_header __iomem
*pqhdr
=
221 (struct signal_queue_header __iomem
*)((char __iomem
*)ch
+
222 readq(&ch
->ch_space_offset
)) + queue
;
223 return readl(&pqhdr
->head
) == readl(&pqhdr
->tail
);
225 EXPORT_SYMBOL_GPL(spar_signalqueue_empty
);
228 uisqueue_interlocked_or(unsigned long long __iomem
*tgt
,
229 unsigned long long set
)
231 unsigned long long i
;
232 unsigned long long j
;
237 j
= cmpxchg((__force
unsigned long long *)tgt
, i
, i
| set
);
243 EXPORT_SYMBOL_GPL(uisqueue_interlocked_or
);
246 uisqueue_interlocked_and(unsigned long long __iomem
*tgt
,
247 unsigned long long set
)
249 unsigned long long i
;
250 unsigned long long j
;
255 j
= cmpxchg((__force
unsigned long long *)tgt
, i
, i
& set
);
261 EXPORT_SYMBOL_GPL(uisqueue_interlocked_and
);
264 do_locked_client_insert(struct uisqueue_info
*queueinfo
,
265 unsigned int whichqueue
,
273 spin_lock_irqsave(lock
, flags
);
274 if (!spar_channel_client_acquire_os(queueinfo
->chan
, channel_id
))
276 if (spar_signal_insert(queueinfo
->chan
, whichqueue
, signal
)) {
277 queueinfo
->packets_sent
++;
280 spar_channel_client_release_os(queueinfo
->chan
, channel_id
);
282 spin_unlock_irqrestore((spinlock_t
*)lock
, flags
);
287 uisqueue_put_cmdrsp_with_lock_client(struct uisqueue_info
*queueinfo
,
288 struct uiscmdrsp
*cmdrsp
,
289 unsigned int whichqueue
,
291 unsigned char issue_irq_if_empty
,
293 char oktowait
, u8
*channel_id
)
295 while (!do_locked_client_insert(queueinfo
, whichqueue
, cmdrsp
,
296 (spinlock_t
*)insertlock
,
298 if (oktowait
!= OK_TO_WAIT
)
299 return 0; /* failed to queue */
302 set_current_state(TASK_INTERRUPTIBLE
);
303 schedule_timeout(msecs_to_jiffies(10));
307 EXPORT_SYMBOL_GPL(uisqueue_put_cmdrsp_with_lock_client
);
309 /* uisqueue_get_cmdrsp gets the cmdrsp entry at the head of the queue
310 * returns NULL if queue is empty */
312 uisqueue_get_cmdrsp(struct uisqueue_info
*queueinfo
,
313 void *cmdrsp
, unsigned int whichqueue
)
315 if (!spar_signal_remove(queueinfo
->chan
, whichqueue
, cmdrsp
))
318 queueinfo
->packets_received
++;
320 return 1; /* Success */
322 EXPORT_SYMBOL_GPL(uisqueue_get_cmdrsp
);