Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

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