Staging: unisys: Remove RETBOOL macro
[firefly-linux-kernel-4.4.55.git] / drivers / staging / unisys / uislib / uisqueue.c
1 /* uisqueue.c
2  *
3  * Copyright © 2010 - 2013 UNISYS CORPORATION
4  * All rights reserved.
5  *
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.
10  *
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
15  * details.
16  */
17
18 /* @ALL_INSPECTED */
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21
22 #include "uisutils.h"
23
24 #include "chanstub.h"
25
26 /* this is shorter than using __FILE__ (full path name) in
27  * debug/info/error messages */
28 #define CURRENT_FILE_PC UISLIB_PC_uisqueue_c
29 #define __MYFILE__ "uisqueue.c"
30
31 #define RETVOID    do { goto Away; } while (0)
32 #define RETINT(x)  do { rc = (x); goto Away; } while (0)
33 #define RETPTR(x)  do { rc = (x); goto Away; } while (0)
34
35 #define CHECK_CACHE_ALIGN 0
36
37 /*****************************************************/
38 /* Exported functions                                */
39 /*****************************************************/
40 unsigned long long
41 uisqueue_InterlockedOr(unsigned long long __iomem *Target,
42                        unsigned long long Set)
43 {
44         unsigned long long i;
45         unsigned long long j;
46
47         j = readq(Target);
48         do {
49                 i = j;
50                 j = uislibcmpxchg64((__force unsigned long long *)Target,
51                                     i, i | Set, sizeof(*(Target)));
52
53         } while (i != j);
54
55         return j;
56 }
57 EXPORT_SYMBOL_GPL(uisqueue_InterlockedOr);
58
59 unsigned long long
60 uisqueue_InterlockedAnd(unsigned long long __iomem *Target,
61                         unsigned long long Set)
62 {
63         unsigned long long i;
64         unsigned long long j;
65
66         j = readq(Target);
67         do {
68                 i = j;
69                 j = uislibcmpxchg64((__force unsigned long long *)Target,
70                                     i, i & Set, sizeof(*(Target)));
71
72         } while (i != j);
73
74         return j;
75 }
76 EXPORT_SYMBOL_GPL(uisqueue_InterlockedAnd);
77
78 static U8
79 do_locked_client_insert(struct uisqueue_info *queueinfo,
80                         unsigned int whichqueue,
81                         void *pSignal,
82                         spinlock_t *lock,
83                         unsigned char issueInterruptIfEmpty,
84                         U64 interruptHandle, U8 *channelId)
85 {
86         unsigned long flags;
87         unsigned char queueWasEmpty;
88         unsigned int locked = 0;
89         unsigned int acquired = 0;
90         U8 rc = 0;
91
92         spin_lock_irqsave(lock, flags);
93         locked = 1;
94
95         if (!ULTRA_CHANNEL_CLIENT_ACQUIRE_OS(queueinfo->chan, channelId, NULL))
96                 RETINT(0);
97
98         acquired = 1;
99
100         queueWasEmpty = visor_signalqueue_empty(queueinfo->chan, whichqueue);
101         if (!visor_signal_insert(queueinfo->chan, whichqueue, pSignal))
102                 RETINT(0);
103         ULTRA_CHANNEL_CLIENT_RELEASE_OS(queueinfo->chan, channelId, NULL);
104         acquired = 0;
105         spin_unlock_irqrestore(lock, flags);
106         locked = 0;
107
108         queueinfo->packets_sent++;
109
110         RETINT(1);
111
112 Away:
113         if (acquired) {
114                 ULTRA_CHANNEL_CLIENT_RELEASE_OS(queueinfo->chan, channelId,
115                                                 NULL);
116                 acquired = 0;
117         }
118         if (locked) {
119                 spin_unlock_irqrestore((spinlock_t *) lock, flags);
120                 locked = 0;
121         }
122
123         return rc;
124 }
125
126 int
127 uisqueue_put_cmdrsp_with_lock_client(struct uisqueue_info *queueinfo,
128                                      struct uiscmdrsp *cmdrsp,
129                                      unsigned int whichqueue,
130                                      void *insertlock,
131                                      unsigned char issueInterruptIfEmpty,
132                                      U64 interruptHandle,
133                                      char oktowait, U8 *channelId)
134 {
135         while (!do_locked_client_insert(queueinfo, whichqueue, cmdrsp,
136                                         (spinlock_t *) insertlock,
137                                         issueInterruptIfEmpty,
138                                         interruptHandle, channelId)) {
139                 if (oktowait != OK_TO_WAIT) {
140                         LOGERR("****FAILED visor_signal_insert failed; cannot wait; insert aborted\n");
141                         return 0;       /* failed to queue */
142                 }
143                 /* try again */
144                 LOGERR("****FAILED visor_signal_insert failed; waiting to try again\n");
145                 set_current_state(TASK_INTERRUPTIBLE);
146                 schedule_timeout(msecs_to_jiffies(10));
147         }
148         return 1;
149 }
150 EXPORT_SYMBOL_GPL(uisqueue_put_cmdrsp_with_lock_client);
151
152 /* uisqueue_get_cmdrsp gets the cmdrsp entry at the head of the queue
153  * returns NULL if queue is empty */
154 int
155 uisqueue_get_cmdrsp(struct uisqueue_info *queueinfo,
156                     void *cmdrsp, unsigned int whichqueue)
157 {
158         if (!visor_signal_remove(queueinfo->chan, whichqueue, cmdrsp))
159                 return 0;
160
161         queueinfo->packets_received++;
162
163         return 1;               /* Success */
164 }
165 EXPORT_SYMBOL_GPL(uisqueue_get_cmdrsp);