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