Merge branch 'perf/urgent' into perf/core, to pick up fixes
[linux-2.6-microblaze.git] / drivers / s390 / cio / ioasm.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Channel subsystem I/O instructions.
4  */
5
6 #include <linux/export.h>
7
8 #include <asm/chpid.h>
9 #include <asm/schid.h>
10 #include <asm/crw.h>
11
12 #include "ioasm.h"
13 #include "orb.h"
14 #include "cio.h"
15 #include "cio_inject.h"
16
17 static inline int __stsch(struct subchannel_id schid, struct schib *addr)
18 {
19         unsigned long r1 = *(unsigned int *)&schid;
20         int ccode = -EIO;
21
22         asm volatile(
23                 "       lgr     1,%[r1]\n"
24                 "       stsch   %[addr]\n"
25                 "0:     ipm     %[cc]\n"
26                 "       srl     %[cc],28\n"
27                 "1:\n"
28                 EX_TABLE(0b, 1b)
29                 : [cc] "+&d" (ccode), [addr] "=Q" (*addr)
30                 : [r1] "d" (r1)
31                 : "cc", "1");
32         return ccode;
33 }
34
35 int stsch(struct subchannel_id schid, struct schib *addr)
36 {
37         int ccode;
38
39         ccode = __stsch(schid, addr);
40         trace_s390_cio_stsch(schid, addr, ccode);
41
42         return ccode;
43 }
44 EXPORT_SYMBOL(stsch);
45
46 static inline int __msch(struct subchannel_id schid, struct schib *addr)
47 {
48         unsigned long r1 = *(unsigned int *)&schid;
49         int ccode = -EIO;
50
51         asm volatile(
52                 "       lgr     1,%[r1]\n"
53                 "       msch    %[addr]\n"
54                 "0:     ipm     %[cc]\n"
55                 "       srl     %[cc],28\n"
56                 "1:\n"
57                 EX_TABLE(0b, 1b)
58                 : [cc] "+&d" (ccode)
59                 : [r1] "d" (r1), [addr] "Q" (*addr)
60                 : "cc", "1");
61         return ccode;
62 }
63
64 int msch(struct subchannel_id schid, struct schib *addr)
65 {
66         int ccode;
67
68         ccode = __msch(schid, addr);
69         trace_s390_cio_msch(schid, addr, ccode);
70
71         return ccode;
72 }
73
74 static inline int __tsch(struct subchannel_id schid, struct irb *addr)
75 {
76         unsigned long r1 = *(unsigned int *)&schid;
77         int ccode;
78
79         asm volatile(
80                 "       lgr     1,%[r1]\n"
81                 "       tsch    %[addr]\n"
82                 "       ipm     %[cc]\n"
83                 "       srl     %[cc],28"
84                 : [cc] "=&d" (ccode), [addr] "=Q" (*addr)
85                 : [r1] "d" (r1)
86                 : "cc", "1");
87         return ccode;
88 }
89
90 int tsch(struct subchannel_id schid, struct irb *addr)
91 {
92         int ccode;
93
94         ccode = __tsch(schid, addr);
95         trace_s390_cio_tsch(schid, addr, ccode);
96
97         return ccode;
98 }
99
100 static inline int __ssch(struct subchannel_id schid, union orb *addr)
101 {
102         unsigned long r1 = *(unsigned int *)&schid;
103         int ccode = -EIO;
104
105         asm volatile(
106                 "       lgr     1,%[r1]\n"
107                 "       ssch    %[addr]\n"
108                 "0:     ipm     %[cc]\n"
109                 "       srl     %[cc],28\n"
110                 "1:\n"
111                 EX_TABLE(0b, 1b)
112                 : [cc] "+&d" (ccode)
113                 : [r1] "d" (r1), [addr] "Q" (*addr)
114                 : "cc", "memory", "1");
115         return ccode;
116 }
117
118 int ssch(struct subchannel_id schid, union orb *addr)
119 {
120         int ccode;
121
122         ccode = __ssch(schid, addr);
123         trace_s390_cio_ssch(schid, addr, ccode);
124
125         return ccode;
126 }
127 EXPORT_SYMBOL(ssch);
128
129 static inline int __csch(struct subchannel_id schid)
130 {
131         unsigned long r1 = *(unsigned int *)&schid;
132         int ccode;
133
134         asm volatile(
135                 "       lgr     1,%[r1]\n"
136                 "       csch\n"
137                 "       ipm     %[cc]\n"
138                 "       srl     %[cc],28\n"
139                 : [cc] "=&d" (ccode)
140                 : [r1] "d" (r1)
141                 : "cc", "1");
142         return ccode;
143 }
144
145 int csch(struct subchannel_id schid)
146 {
147         int ccode;
148
149         ccode = __csch(schid);
150         trace_s390_cio_csch(schid, ccode);
151
152         return ccode;
153 }
154 EXPORT_SYMBOL(csch);
155
156 int tpi(struct tpi_info *addr)
157 {
158         int ccode;
159
160         asm volatile(
161                 "       tpi     %[addr]\n"
162                 "       ipm     %[cc]\n"
163                 "       srl     %[cc],28"
164                 : [cc] "=&d" (ccode), [addr] "=Q" (*addr)
165                 :
166                 : "cc");
167         trace_s390_cio_tpi(addr, ccode);
168
169         return ccode;
170 }
171
172 int chsc(void *chsc_area)
173 {
174         typedef struct { char _[4096]; } addr_type;
175         int cc = -EIO;
176
177         asm volatile(
178                 "       .insn   rre,0xb25f0000,%[chsc_area],0\n"
179                 "0:     ipm     %[cc]\n"
180                 "       srl     %[cc],28\n"
181                 "1:\n"
182                 EX_TABLE(0b, 1b)
183                 : [cc] "+&d" (cc), "+m" (*(addr_type *)chsc_area)
184                 : [chsc_area] "d" (chsc_area)
185                 : "cc");
186         trace_s390_cio_chsc(chsc_area, cc);
187
188         return cc;
189 }
190 EXPORT_SYMBOL(chsc);
191
192 static inline int __rsch(struct subchannel_id schid)
193 {
194         unsigned long r1 = *(unsigned int *)&schid;
195         int ccode;
196
197         asm volatile(
198                 "       lgr     1,%[r1]\n"
199                 "       rsch\n"
200                 "       ipm     %[cc]\n"
201                 "       srl     %[cc],28\n"
202                 : [cc] "=&d" (ccode)
203                 : [r1] "d" (r1)
204                 : "cc", "memory", "1");
205         return ccode;
206 }
207
208 int rsch(struct subchannel_id schid)
209 {
210         int ccode;
211
212         ccode = __rsch(schid);
213         trace_s390_cio_rsch(schid, ccode);
214
215         return ccode;
216 }
217
218 static inline int __hsch(struct subchannel_id schid)
219 {
220         unsigned long r1 = *(unsigned int *)&schid;
221         int ccode;
222
223         asm volatile(
224                 "       lgr     1,%[r1]\n"
225                 "       hsch\n"
226                 "       ipm     %[cc]\n"
227                 "       srl     %[cc],28\n"
228                 : [cc] "=&d" (ccode)
229                 : [r1] "d" (r1)
230                 : "cc", "1");
231         return ccode;
232 }
233
234 int hsch(struct subchannel_id schid)
235 {
236         int ccode;
237
238         ccode = __hsch(schid);
239         trace_s390_cio_hsch(schid, ccode);
240
241         return ccode;
242 }
243 EXPORT_SYMBOL(hsch);
244
245 static inline int __xsch(struct subchannel_id schid)
246 {
247         unsigned long r1 = *(unsigned int *)&schid;
248         int ccode;
249
250         asm volatile(
251                 "       lgr     1,%[r1]\n"
252                 "       xsch\n"
253                 "       ipm     %[cc]\n"
254                 "       srl     %[cc],28\n"
255                 : [cc] "=&d" (ccode)
256                 : [r1] "d" (r1)
257                 : "cc", "1");
258         return ccode;
259 }
260
261 int xsch(struct subchannel_id schid)
262 {
263         int ccode;
264
265         ccode = __xsch(schid);
266         trace_s390_cio_xsch(schid, ccode);
267
268         return ccode;
269 }
270
271 static inline int __stcrw(struct crw *crw)
272 {
273         int ccode;
274
275         asm volatile(
276                 "       stcrw   %[crw]\n"
277                 "       ipm     %[cc]\n"
278                 "       srl     %[cc],28\n"
279                 : [cc] "=&d" (ccode), [crw] "=Q" (*crw)
280                 :
281                 : "cc");
282         return ccode;
283 }
284
285 static inline int _stcrw(struct crw *crw)
286 {
287 #ifdef CONFIG_CIO_INJECT
288         if (static_branch_unlikely(&cio_inject_enabled)) {
289                 if (stcrw_get_injected(crw) == 0)
290                         return 0;
291         }
292 #endif
293
294         return __stcrw(crw);
295 }
296
297 int stcrw(struct crw *crw)
298 {
299         int ccode;
300
301         ccode = _stcrw(crw);
302         trace_s390_cio_stcrw(crw, ccode);
303
304         return ccode;
305 }