1
2
3
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
17static 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
35int 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}
44EXPORT_SYMBOL(stsch);
45
46static 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
64int 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
74static 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
90int 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
100static 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
118int 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}
127EXPORT_SYMBOL(ssch);
128
129static 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
145int 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}
154EXPORT_SYMBOL(csch);
155
156int 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
172int 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}
190EXPORT_SYMBOL(chsc);
191
192static 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
208int 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
218static 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
234int 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}
243EXPORT_SYMBOL(hsch);
244
245static 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
261int 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
271static 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
285static 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
297int 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}
306