cio.c 26 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
2
3
4
/*
 *  drivers/s390/cio/cio.c
 *   S/390 common I/O routines -- low level i/o calls
 *
5
 *    Copyright IBM Corp. 1999,2008
Linus Torvalds's avatar
Linus Torvalds committed
6
 *    Author(s): Ingo Adlung (adlung@de.ibm.com)
7
 *		 Cornelia Huck (cornelia.huck@de.ibm.com)
Linus Torvalds's avatar
Linus Torvalds committed
8
9
10
11
12
13
14
15
16
17
18
19
20
 *		 Arnd Bergmann (arndb@de.ibm.com)
 *		 Martin Schwidefsky (schwidefsky@de.ibm.com)
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/kernel_stat.h>
#include <linux/interrupt.h>
#include <asm/cio.h>
#include <asm/delay.h>
#include <asm/irq.h>
21
#include <asm/irq_regs.h>
22
#include <asm/setup.h>
23
#include <asm/reset.h>
Michael Holzheu's avatar
Michael Holzheu committed
24
#include <asm/ipl.h>
25
#include <asm/chpid.h>
26
#include <asm/airq.h>
27
#include <asm/isc.h>
28
#include <asm/cpu.h>
29
#include <asm/fcx.h>
Linus Torvalds's avatar
Linus Torvalds committed
30
31
32
33
#include "cio.h"
#include "css.h"
#include "chsc.h"
#include "ioasm.h"
34
#include "io_sch.h"
Linus Torvalds's avatar
Linus Torvalds committed
35
36
#include "blacklist.h"
#include "cio_debug.h"
37
#include "chp.h"
38
#include "../s390mach.h"
Linus Torvalds's avatar
Linus Torvalds committed
39
40
41
42
43
44
45

debug_info_t *cio_debug_msg_id;
debug_info_t *cio_debug_trace_id;
debug_info_t *cio_debug_crw_id;

/*
 * Function: cio_debug_init
46
47
 * Initializes three debug logs for common I/O:
 * - cio_msg logs generic cio messages
Linus Torvalds's avatar
Linus Torvalds committed
48
 * - cio_trace logs the calling of different functions
49
 * - cio_crw logs machine check related cio messages
Linus Torvalds's avatar
Linus Torvalds committed
50
 */
51
static int __init cio_debug_init(void)
Linus Torvalds's avatar
Linus Torvalds committed
52
{
53
	cio_debug_msg_id = debug_register("cio_msg", 16, 1, 16 * sizeof(long));
Linus Torvalds's avatar
Linus Torvalds committed
54
55
	if (!cio_debug_msg_id)
		goto out_unregister;
56
57
	debug_register_view(cio_debug_msg_id, &debug_sprintf_view);
	debug_set_level(cio_debug_msg_id, 2);
58
	cio_debug_trace_id = debug_register("cio_trace", 16, 1, 16);
Linus Torvalds's avatar
Linus Torvalds committed
59
60
	if (!cio_debug_trace_id)
		goto out_unregister;
61
62
	debug_register_view(cio_debug_trace_id, &debug_hex_ascii_view);
	debug_set_level(cio_debug_trace_id, 2);
63
	cio_debug_crw_id = debug_register("cio_crw", 16, 1, 16 * sizeof(long));
Linus Torvalds's avatar
Linus Torvalds committed
64
65
	if (!cio_debug_crw_id)
		goto out_unregister;
66
67
	debug_register_view(cio_debug_crw_id, &debug_sprintf_view);
	debug_set_level(cio_debug_crw_id, 4);
Linus Torvalds's avatar
Linus Torvalds committed
68
69
70
71
	return 0;

out_unregister:
	if (cio_debug_msg_id)
72
		debug_unregister(cio_debug_msg_id);
Linus Torvalds's avatar
Linus Torvalds committed
73
	if (cio_debug_trace_id)
74
		debug_unregister(cio_debug_trace_id);
Linus Torvalds's avatar
Linus Torvalds committed
75
	if (cio_debug_crw_id)
76
		debug_unregister(cio_debug_crw_id);
Linus Torvalds's avatar
Linus Torvalds committed
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
	return -1;
}

arch_initcall (cio_debug_init);

int
cio_set_options (struct subchannel *sch, int flags)
{
       sch->options.suspend = (flags & DOIO_ALLOW_SUSPEND) != 0;
       sch->options.prefetch = (flags & DOIO_DENY_PREFETCH) != 0;
       sch->options.inter = (flags & DOIO_SUPPRESS_INTER) != 0;
       return 0;
}

/* FIXME: who wants to use this? */
int
cio_get_options (struct subchannel *sch)
{
       int flags;

       flags = 0;
       if (sch->options.suspend)
		flags |= DOIO_ALLOW_SUSPEND;
       if (sch->options.prefetch)
		flags |= DOIO_DENY_PREFETCH;
       if (sch->options.inter)
		flags |= DOIO_SUPPRESS_INTER;
       return flags;
}

/*
 * Use tpi to get a pending interrupt, call the interrupt handler and
 * return a pointer to the subchannel structure.
 */
111
static int
Linus Torvalds's avatar
Linus Torvalds committed
112
113
114
115
116
117
118
119
120
121
122
cio_tpi(void)
{
	struct tpi_info *tpi_info;
	struct subchannel *sch;
	struct irb *irb;

	tpi_info = (struct tpi_info *) __LC_SUBCHANNEL_ID;
	if (tpi (NULL) != 1)
		return 0;
	irb = (struct irb *) __LC_IRB;
	/* Store interrupt response block to lowcore. */
123
	if (tsch (tpi_info->schid, irb) != 0)
Linus Torvalds's avatar
Linus Torvalds committed
124
125
126
127
128
129
130
		/* Not status pending or not operational. */
		return 1;
	sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
	if (!sch)
		return 1;
	local_bh_disable();
	irq_enter ();
131
	spin_lock(sch->lock);
132
	memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw));
Linus Torvalds's avatar
Linus Torvalds committed
133
	if (sch->driver && sch->driver->irq)
134
		sch->driver->irq(sch);
135
	spin_unlock(sch->lock);
Linus Torvalds's avatar
Linus Torvalds committed
136
	irq_exit ();
137
	_local_bh_enable();
Linus Torvalds's avatar
Linus Torvalds committed
138
139
140
	return 1;
}

141
static int
Linus Torvalds's avatar
Linus Torvalds committed
142
143
144
145
146
147
148
149
150
cio_start_handle_notoper(struct subchannel *sch, __u8 lpm)
{
	char dbf_text[15];

	if (lpm != 0)
		sch->lpm &= ~lpm;
	else
		sch->lpm = 0;

151
	stsch (sch->schid, &sch->schib);
Linus Torvalds's avatar
Linus Torvalds committed
152

153
	CIO_MSG_EVENT(2, "cio_start: 'not oper' status for "
154
155
		      "subchannel 0.%x.%04x!\n", sch->schid.ssid,
		      sch->schid.sch_no);
156
	sprintf(dbf_text, "no%s", dev_name(&sch->dev));
Linus Torvalds's avatar
Linus Torvalds committed
157
158
159
160
161
162
163
164
165
166
167
168
169
170
	CIO_TRACE_EVENT(0, dbf_text);
	CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib));

	return (sch->lpm ? -EACCES : -ENODEV);
}

int
cio_start_key (struct subchannel *sch,	/* subchannel structure */
	       struct ccw1 * cpa,	/* logical channel prog addr */
	       __u8 lpm,		/* logical path mask */
	       __u8 key)                /* storage key */
{
	char dbf_txt[15];
	int ccode;
171
	union orb *orb;
Linus Torvalds's avatar
Linus Torvalds committed
172

173
	CIO_TRACE_EVENT(4, "stIO");
174
	CIO_TRACE_EVENT(4, dev_name(&sch->dev));
Linus Torvalds's avatar
Linus Torvalds committed
175

176
	orb = &to_io_private(sch)->orb;
177
	memset(orb, 0, sizeof(union orb));
Linus Torvalds's avatar
Linus Torvalds committed
178
	/* sch is always under 2G. */
179
180
	orb->cmd.intparm = (u32)(addr_t)sch;
	orb->cmd.fmt = 1;
Linus Torvalds's avatar
Linus Torvalds committed
181

182
183
184
185
	orb->cmd.pfch = sch->options.prefetch == 0;
	orb->cmd.spnd = sch->options.suspend;
	orb->cmd.ssic = sch->options.suspend && sch->options.inter;
	orb->cmd.lpm = (lpm != 0) ? lpm : sch->lpm;
186
#ifdef CONFIG_64BIT
Linus Torvalds's avatar
Linus Torvalds committed
187
188
189
	/*
	 * for 64 bit we always support 64 bit IDAWs with 4k page size only
	 */
190
191
	orb->cmd.c64 = 1;
	orb->cmd.i2k = 0;
Linus Torvalds's avatar
Linus Torvalds committed
192
#endif
193
	orb->cmd.key = key >> 4;
Linus Torvalds's avatar
Linus Torvalds committed
194
	/* issue "Start Subchannel" */
195
	orb->cmd.cpa = (__u32) __pa(cpa);
196
	ccode = ssch(sch->schid, orb);
Linus Torvalds's avatar
Linus Torvalds committed
197
198

	/* process condition code */
199
200
	sprintf(dbf_txt, "ccode:%d", ccode);
	CIO_TRACE_EVENT(4, dbf_txt);
Linus Torvalds's avatar
Linus Torvalds committed
201
202
203
204
205
206

	switch (ccode) {
	case 0:
		/*
		 * initialize device status information
		 */
207
		sch->schib.scsw.cmd.actl |= SCSW_ACTL_START_PEND;
Linus Torvalds's avatar
Linus Torvalds committed
208
209
210
211
		return 0;
	case 1:		/* status pending */
	case 2:		/* busy */
		return -EBUSY;
212
	case 3:		/* device/path not operational */
Linus Torvalds's avatar
Linus Torvalds committed
213
		return cio_start_handle_notoper(sch, lpm);
214
215
	default:
		return ccode;
Linus Torvalds's avatar
Linus Torvalds committed
216
217
218
219
220
221
	}
}

int
cio_start (struct subchannel *sch, struct ccw1 *cpa, __u8 lpm)
{
222
	return cio_start_key(sch, cpa, lpm, PAGE_DEFAULT_KEY);
Linus Torvalds's avatar
Linus Torvalds committed
223
224
225
226
227
228
229
230
231
232
233
234
}

/*
 * resume suspended I/O operation
 */
int
cio_resume (struct subchannel *sch)
{
	char dbf_txt[15];
	int ccode;

	CIO_TRACE_EVENT (4, "resIO");
235
	CIO_TRACE_EVENT(4, dev_name(&sch->dev));
Linus Torvalds's avatar
Linus Torvalds committed
236

237
	ccode = rsch (sch->schid);
Linus Torvalds's avatar
Linus Torvalds committed
238
239
240
241
242
243

	sprintf (dbf_txt, "ccode:%d", ccode);
	CIO_TRACE_EVENT (4, dbf_txt);

	switch (ccode) {
	case 0:
244
		sch->schib.scsw.cmd.actl |= SCSW_ACTL_RESUME_PEND;
Linus Torvalds's avatar
Linus Torvalds committed
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
		return 0;
	case 1:
		return -EBUSY;
	case 2:
		return -EINVAL;
	default:
		/*
		 * useless to wait for request completion
		 *  as device is no longer operational !
		 */
		return -ENODEV;
	}
}

/*
 * halt I/O operation
 */
int
cio_halt(struct subchannel *sch)
{
	char dbf_txt[15];
	int ccode;

	if (!sch)
		return -ENODEV;

	CIO_TRACE_EVENT (2, "haltIO");
272
	CIO_TRACE_EVENT(2, dev_name(&sch->dev));
Linus Torvalds's avatar
Linus Torvalds committed
273
274
275
276

	/*
	 * Issue "Halt subchannel" and process condition code
	 */
277
	ccode = hsch (sch->schid);
Linus Torvalds's avatar
Linus Torvalds committed
278
279
280
281
282
283

	sprintf (dbf_txt, "ccode:%d", ccode);
	CIO_TRACE_EVENT (2, dbf_txt);

	switch (ccode) {
	case 0:
284
		sch->schib.scsw.cmd.actl |= SCSW_ACTL_HALT_PEND;
Linus Torvalds's avatar
Linus Torvalds committed
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
		return 0;
	case 1:		/* status pending */
	case 2:		/* busy */
		return -EBUSY;
	default:		/* device not operational */
		return -ENODEV;
	}
}

/*
 * Clear I/O operation
 */
int
cio_clear(struct subchannel *sch)
{
	char dbf_txt[15];
	int ccode;

	if (!sch)
		return -ENODEV;

	CIO_TRACE_EVENT (2, "clearIO");
307
	CIO_TRACE_EVENT(2, dev_name(&sch->dev));
Linus Torvalds's avatar
Linus Torvalds committed
308
309
310
311

	/*
	 * Issue "Clear subchannel" and process condition code
	 */
312
	ccode = csch (sch->schid);
Linus Torvalds's avatar
Linus Torvalds committed
313
314
315
316
317
318

	sprintf (dbf_txt, "ccode:%d", ccode);
	CIO_TRACE_EVENT (2, dbf_txt);

	switch (ccode) {
	case 0:
319
		sch->schib.scsw.cmd.actl |= SCSW_ACTL_CLEAR_PEND;
Linus Torvalds's avatar
Linus Torvalds committed
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
		return 0;
	default:		/* device not operational */
		return -ENODEV;
	}
}

/*
 * Function: cio_cancel
 * Issues a "Cancel Subchannel" on the specified subchannel
 * Note: We don't need any fancy intparms and flags here
 *	 since xsch is executed synchronously.
 * Only for common I/O internal use as for now.
 */
int
cio_cancel (struct subchannel *sch)
{
	char dbf_txt[15];
	int ccode;

	if (!sch)
		return -ENODEV;

	CIO_TRACE_EVENT (2, "cancelIO");
343
	CIO_TRACE_EVENT(2, dev_name(&sch->dev));
Linus Torvalds's avatar
Linus Torvalds committed
344

345
	ccode = xsch (sch->schid);
Linus Torvalds's avatar
Linus Torvalds committed
346
347
348
349
350
351
352

	sprintf (dbf_txt, "ccode:%d", ccode);
	CIO_TRACE_EVENT (2, dbf_txt);

	switch (ccode) {
	case 0:		/* success */
		/* Update information in scsw. */
353
		stsch (sch->schid, &sch->schib);
Linus Torvalds's avatar
Linus Torvalds committed
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
		return 0;
	case 1:		/* status pending */
		return -EBUSY;
	case 2:		/* not applicable */
		return -EINVAL;
	default:	/* not oper */
		return -ENODEV;
	}
}

/*
 * Function: cio_modify
 * Issues a "Modify Subchannel" on the specified subchannel
 */
int
cio_modify (struct subchannel *sch)
{
	int ccode, retry, ret;

	ret = 0;
	for (retry = 0; retry < 5; retry++) {
375
		ccode = msch_err (sch->schid, &sch->schib);
Linus Torvalds's avatar
Linus Torvalds committed
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
		if (ccode < 0)	/* -EIO if msch gets a program check. */
			return ccode;
		switch (ccode) {
		case 0: /* successfull */
			return 0;
		case 1:	/* status pending */
			return -EBUSY;
		case 2:	/* busy */
			udelay (100);	/* allow for recovery */
			ret = -EBUSY;
			break;
		case 3:	/* not operational */
			return -ENODEV;
		}
	}
	return ret;
}

394
395
396
397
/**
 * cio_enable_subchannel - enable a subchannel.
 * @sch: subchannel to be enabled
 * @intparm: interruption parameter to set
Linus Torvalds's avatar
Linus Torvalds committed
398
 */
399
int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
Linus Torvalds's avatar
Linus Torvalds committed
400
401
402
403
404
405
406
{
	char dbf_txt[15];
	int ccode;
	int retry;
	int ret;

	CIO_TRACE_EVENT (2, "ensch");
407
	CIO_TRACE_EVENT(2, dev_name(&sch->dev));
Linus Torvalds's avatar
Linus Torvalds committed
408

409
410
	if (sch_is_pseudo_sch(sch))
		return -EINVAL;
411
	ccode = stsch (sch->schid, &sch->schib);
Linus Torvalds's avatar
Linus Torvalds committed
412
413
414
415
416
	if (ccode)
		return -ENODEV;

	for (retry = 5, ret = 0; retry > 0; retry--) {
		sch->schib.pmcw.ena = 1;
417
		sch->schib.pmcw.isc = sch->isc;
418
		sch->schib.pmcw.intparm = intparm;
Linus Torvalds's avatar
Linus Torvalds committed
419
420
421
422
423
424
425
426
427
428
		ret = cio_modify(sch);
		if (ret == -ENODEV)
			break;
		if (ret == -EIO)
			/*
			 * Got a program check in cio_modify. Try without
			 * the concurrent sense bit the next time.
			 */
			sch->schib.pmcw.csense = 0;
		if (ret == 0) {
429
			stsch (sch->schid, &sch->schib);
Linus Torvalds's avatar
Linus Torvalds committed
430
431
432
433
434
			if (sch->schib.pmcw.ena)
				break;
		}
		if (ret == -EBUSY) {
			struct irb irb;
435
			if (tsch(sch->schid, &irb) != 0)
Linus Torvalds's avatar
Linus Torvalds committed
436
437
438
439
440
441
442
				break;
		}
	}
	sprintf (dbf_txt, "ret:%d", ret);
	CIO_TRACE_EVENT (2, dbf_txt);
	return ret;
}
443
EXPORT_SYMBOL_GPL(cio_enable_subchannel);
Linus Torvalds's avatar
Linus Torvalds committed
444

445
446
447
/**
 * cio_disable_subchannel - disable a subchannel.
 * @sch: subchannel to disable
Linus Torvalds's avatar
Linus Torvalds committed
448
 */
449
int cio_disable_subchannel(struct subchannel *sch)
Linus Torvalds's avatar
Linus Torvalds committed
450
451
452
453
454
455
456
{
	char dbf_txt[15];
	int ccode;
	int retry;
	int ret;

	CIO_TRACE_EVENT (2, "dissch");
457
	CIO_TRACE_EVENT(2, dev_name(&sch->dev));
Linus Torvalds's avatar
Linus Torvalds committed
458

459
460
	if (sch_is_pseudo_sch(sch))
		return 0;
461
	ccode = stsch (sch->schid, &sch->schib);
Linus Torvalds's avatar
Linus Torvalds committed
462
463
464
	if (ccode == 3)		/* Not operational. */
		return -ENODEV;

465
	if (scsw_actl(&sch->schib.scsw) != 0)
Linus Torvalds's avatar
Linus Torvalds committed
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
		/*
		 * the disable function must not be called while there are
		 *  requests pending for completion !
		 */
		return -EBUSY;

	for (retry = 5, ret = 0; retry > 0; retry--) {
		sch->schib.pmcw.ena = 0;
		ret = cio_modify(sch);
		if (ret == -ENODEV)
			break;
		if (ret == -EBUSY)
			/*
			 * The subchannel is busy or status pending.
			 * We'll disable when the next interrupt was delivered
			 * via the state machine.
			 */
			break;
		if (ret == 0) {
485
			stsch (sch->schid, &sch->schib);
Linus Torvalds's avatar
Linus Torvalds committed
486
487
488
489
490
491
492
493
			if (!sch->schib.pmcw.ena)
				break;
		}
	}
	sprintf (dbf_txt, "ret:%d", ret);
	CIO_TRACE_EVENT (2, dbf_txt);
	return ret;
}
494
EXPORT_SYMBOL_GPL(cio_disable_subchannel);
Linus Torvalds's avatar
Linus Torvalds committed
495

496
int cio_create_sch_lock(struct subchannel *sch)
497
498
499
500
501
502
503
504
{
	sch->lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
	if (!sch->lock)
		return -ENOMEM;
	spin_lock_init(sch->lock);
	return 0;
}

505
static int cio_check_devno_blacklisted(struct subchannel *sch)
506
507
508
509
510
511
512
513
514
515
516
517
518
519
{
	if (is_blacklisted(sch->schid.ssid, sch->schib.pmcw.dev)) {
		/*
		 * This device must not be known to Linux. So we simply
		 * say that there is no device and return ENODEV.
		 */
		CIO_MSG_EVENT(6, "Blacklisted device detected "
			      "at devno %04X, subchannel set %x\n",
			      sch->schib.pmcw.dev, sch->schid.ssid);
		return -ENODEV;
	}
	return 0;
}

520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
static int cio_validate_io_subchannel(struct subchannel *sch)
{
	/* Initialization for io subchannels. */
	if (!css_sch_is_valid(&sch->schib))
		return -ENODEV;

	/* Devno is valid. */
	return cio_check_devno_blacklisted(sch);
}

static int cio_validate_msg_subchannel(struct subchannel *sch)
{
	/* Initialization for message subchannels. */
	if (!css_sch_is_valid(&sch->schib))
		return -ENODEV;

	/* Devno is valid. */
	return cio_check_devno_blacklisted(sch);
}

540
541
542
543
/**
 * cio_validate_subchannel - basic validation of subchannel
 * @sch: subchannel structure to be filled out
 * @schid: subchannel id
Linus Torvalds's avatar
Linus Torvalds committed
544
545
546
 *
 * Find out subchannel type and initialize struct subchannel.
 * Return codes:
547
 *   0 on success
Linus Torvalds's avatar
Linus Torvalds committed
548
 *   -ENXIO for non-defined subchannels
549
550
 *   -ENODEV for invalid subchannels or blacklisted devices
 *   -EIO for subchannels in an invalid subchannel set
Linus Torvalds's avatar
Linus Torvalds committed
551
 */
552
int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid)
Linus Torvalds's avatar
Linus Torvalds committed
553
554
555
{
	char dbf_txt[15];
	int ccode;
556
	int err;
Linus Torvalds's avatar
Linus Torvalds committed
557

558
559
	sprintf(dbf_txt, "valsch%x", schid.sch_no);
	CIO_TRACE_EVENT(4, dbf_txt);
Linus Torvalds's avatar
Linus Torvalds committed
560
561
562
563

	/* Nuke all fields. */
	memset(sch, 0, sizeof(struct subchannel));

564
565
566
567
568
569
570
571
	sch->schid = schid;
	if (cio_is_console(schid)) {
		sch->lock = cio_get_console_lock();
	} else {
		err = cio_create_sch_lock(sch);
		if (err)
			goto out;
	}
572
	mutex_init(&sch->reg_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
573
	/* Set a name for the subchannel */
574
575
576
577
	if (cio_is_console(schid))
		sch->dev.init_name = cio_get_console_sch_name(schid);
	else
		dev_set_name(&sch->dev, "0.%x.%04x", schid.ssid, schid.sch_no);
Linus Torvalds's avatar
Linus Torvalds committed
578
579
580
581

	/*
	 * The first subchannel that is not-operational (ccode==3)
	 *  indicates that there aren't any more devices available.
582
583
	 * If stsch gets an exception, it means the current subchannel set
	 *  is not valid.
Linus Torvalds's avatar
Linus Torvalds committed
584
	 */
585
	ccode = stsch_err (schid, &sch->schib);
586
587
588
589
	if (ccode) {
		err = (ccode == 3) ? -ENXIO : ccode;
		goto out;
	}
Linus Torvalds's avatar
Linus Torvalds committed
590
591
	/* Copy subchannel type from path management control word. */
	sch->st = sch->schib.pmcw.st;
Cornelia Huck's avatar
Cornelia Huck committed
592

593
594
595
596
	switch (sch->st) {
	case SUBCHANNEL_TYPE_IO:
		err = cio_validate_io_subchannel(sch);
		break;
597
598
599
	case SUBCHANNEL_TYPE_MSG:
		err = cio_validate_msg_subchannel(sch);
		break;
600
601
	default:
		err = 0;
Linus Torvalds's avatar
Linus Torvalds committed
602
	}
603
	if (err)
604
605
		goto out;

606
607
	CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports subchannel type %04X\n",
		      sch->schid.ssid, sch->schid.sch_no, sch->st);
Linus Torvalds's avatar
Linus Torvalds committed
608
	return 0;
609
610
611
612
613
out:
	if (!cio_is_console(schid))
		kfree(sch->lock);
	sch->lock = NULL;
	return err;
Linus Torvalds's avatar
Linus Torvalds committed
614
615
616
617
618
619
620
621
622
623
624
625
626
627
}

/*
 * do_IRQ() handles all normal I/O device IRQ's (the special
 *	    SMP cross-CPU interrupts have their own specific
 *	    handlers).
 *
 */
void
do_IRQ (struct pt_regs *regs)
{
	struct tpi_info *tpi_info;
	struct subchannel *sch;
	struct irb *irb;
628
	struct pt_regs *old_regs;
Linus Torvalds's avatar
Linus Torvalds committed
629

630
	old_regs = set_irq_regs(regs);
631
	irq_enter();
632
	s390_idle_check();
633
634
635
	if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
		/* Serve timer interrupts first. */
		clock_comparator_work();
Linus Torvalds's avatar
Linus Torvalds committed
636
637
638
639
640
641
642
643
644
645
646
647
	/*
	 * Get interrupt information from lowcore
	 */
	tpi_info = (struct tpi_info *) __LC_SUBCHANNEL_ID;
	irb = (struct irb *) __LC_IRB;
	do {
		kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++;
		/*
		 * Non I/O-subchannel thin interrupts are processed differently
		 */
		if (tpi_info->adapter_IO == 1 &&
		    tpi_info->int_type == IO_INTERRUPT_TYPE) {
648
			do_adapter_IO(tpi_info->isc);
Linus Torvalds's avatar
Linus Torvalds committed
649
650
651
			continue;
		}
		sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
652
653
654
655
656
657
		if (!sch) {
			/* Clear pending interrupt condition. */
			tsch(tpi_info->schid, irb);
			continue;
		}
		spin_lock(sch->lock);
Linus Torvalds's avatar
Linus Torvalds committed
658
		/* Store interrupt response block to lowcore. */
659
		if (tsch(tpi_info->schid, irb) == 0) {
Linus Torvalds's avatar
Linus Torvalds committed
660
661
662
663
664
			/* Keep subchannel information word up to date. */
			memcpy (&sch->schib.scsw, &irb->scsw,
				sizeof (irb->scsw));
			/* Call interrupt handler if there is one. */
			if (sch->driver && sch->driver->irq)
665
				sch->driver->irq(sch);
Linus Torvalds's avatar
Linus Torvalds committed
666
		}
667
		spin_unlock(sch->lock);
Linus Torvalds's avatar
Linus Torvalds committed
668
669
670
671
672
673
674
675
		/*
		 * Are more interrupts pending?
		 * If so, the tpi instruction will update the lowcore
		 * to hold the info for the next interrupt.
		 * We don't do this for VM because a tpi drops the cpu
		 * out of the sie which costs more cycles than it saves.
		 */
	} while (!MACHINE_IS_VM && tpi (NULL) != 0);
676
	irq_exit();
677
	set_irq_regs(old_regs);
Linus Torvalds's avatar
Linus Torvalds committed
678
679
680
681
}

#ifdef CONFIG_CCW_CONSOLE
static struct subchannel console_subchannel;
682
static char console_sch_name[10] = "0.x.xxxx";
683
static struct io_subchannel_private console_priv;
Linus Torvalds's avatar
Linus Torvalds committed
684
685
static int console_subchannel_in_use;

686
687
688
689
690
void *cio_get_console_priv(void)
{
	return &console_priv;
}

Linus Torvalds's avatar
Linus Torvalds committed
691
692
693
/*
 * busy wait for the next interrupt on the console
 */
694
695
696
void wait_cons_dev(void)
	__releases(console_subchannel.lock)
	__acquires(console_subchannel.lock)
Linus Torvalds's avatar
Linus Torvalds committed
697
698
699
700
701
702
703
704
705
706
707
{
	unsigned long cr6      __attribute__ ((aligned (8)));
	unsigned long save_cr6 __attribute__ ((aligned (8)));

	/* 
	 * before entering the spinlock we may already have
	 * processed the interrupt on a different CPU...
	 */
	if (!console_subchannel_in_use)
		return;

708
	/* disable all but the console isc */
Linus Torvalds's avatar
Linus Torvalds committed
709
	__ctl_store (save_cr6, 6, 6);
710
	cr6 = 1UL << (31 - CONSOLE_ISC);
Linus Torvalds's avatar
Linus Torvalds committed
711
712
713
	__ctl_load (cr6, 6, 6);

	do {
714
		spin_unlock(console_subchannel.lock);
Linus Torvalds's avatar
Linus Torvalds committed
715
716
		if (!cio_tpi())
			cpu_relax();
717
		spin_lock(console_subchannel.lock);
718
	} while (console_subchannel.schib.scsw.cmd.actl != 0);
Linus Torvalds's avatar
Linus Torvalds committed
719
720
721
722
723
724
725
	/*
	 * restore previous isc value
	 */
	__ctl_load (save_cr6, 6, 6);
}

static int
726
727
cio_test_for_console(struct subchannel_id schid, void *data)
{
728
	if (stsch_err(schid, &console_subchannel.schib) != 0)
729
		return -ENXIO;
730
731
732
	if ((console_subchannel.schib.pmcw.st == SUBCHANNEL_TYPE_IO) &&
	    console_subchannel.schib.pmcw.dnv &&
	    (console_subchannel.schib.pmcw.dev == console_devno)) {
733
734
735
736
737
738
739
740
741
		console_irq = schid.sch_no;
		return 1; /* found */
	}
	return 0;
}


static int
cio_get_console_sch_no(void)
Linus Torvalds's avatar
Linus Torvalds committed
742
{
743
	struct subchannel_id schid;
Linus Torvalds's avatar
Linus Torvalds committed
744
	
745
	init_subchannel_id(&schid);
Linus Torvalds's avatar
Linus Torvalds committed
746
747
	if (console_irq != -1) {
		/* VM provided us with the irq number of the console. */
748
749
		schid.sch_no = console_irq;
		if (stsch(schid, &console_subchannel.schib) != 0 ||
750
		    (console_subchannel.schib.pmcw.st != SUBCHANNEL_TYPE_IO) ||
Linus Torvalds's avatar
Linus Torvalds committed
751
752
753
754
755
		    !console_subchannel.schib.pmcw.dnv)
			return -1;
		console_devno = console_subchannel.schib.pmcw.dev;
	} else if (console_devno != -1) {
		/* At least the console device number is known. */
756
		for_each_subchannel(cio_test_for_console, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
757
758
759
760
761
762
763
764
765
766
767
768
769
770
		if (console_irq == -1)
			return -1;
	} else {
		/* unlike in 2.4, we cannot autoprobe here, since
		 * the channel subsystem is not fully initialized.
		 * With some luck, the HWC console can take over */
		return -1;
	}
	return console_irq;
}

struct subchannel *
cio_probe_console(void)
{
771
	int sch_no, ret;
772
	struct subchannel_id schid;
Linus Torvalds's avatar
Linus Torvalds committed
773
774
775

	if (xchg(&console_subchannel_in_use, 1) != 0)
		return ERR_PTR(-EBUSY);
776
777
	sch_no = cio_get_console_sch_no();
	if (sch_no == -1) {
Linus Torvalds's avatar
Linus Torvalds committed
778
		console_subchannel_in_use = 0;
779
		printk(KERN_WARNING "cio: No ccw console found!\n");
Linus Torvalds's avatar
Linus Torvalds committed
780
781
782
		return ERR_PTR(-ENODEV);
	}
	memset(&console_subchannel, 0, sizeof(struct subchannel));
783
	init_subchannel_id(&schid);
784
	schid.sch_no = sch_no;
785
	ret = cio_validate_subchannel(&console_subchannel, schid);
Linus Torvalds's avatar
Linus Torvalds committed
786
787
788
789
790
791
	if (ret) {
		console_subchannel_in_use = 0;
		return ERR_PTR(-ENODEV);
	}

	/*
792
	 * enable console I/O-interrupt subclass
Linus Torvalds's avatar
Linus Torvalds committed
793
	 */
794
	isc_register(CONSOLE_ISC);
795
	console_subchannel.schib.pmcw.isc = CONSOLE_ISC;
Linus Torvalds's avatar
Linus Torvalds committed
796
	console_subchannel.schib.pmcw.intparm =
797
		(u32)(addr_t)&console_subchannel;
Linus Torvalds's avatar
Linus Torvalds committed
798
799
	ret = cio_modify(&console_subchannel);
	if (ret) {
800
		isc_unregister(CONSOLE_ISC);
Linus Torvalds's avatar
Linus Torvalds committed
801
802
803
804
805
806
807
808
809
810
811
		console_subchannel_in_use = 0;
		return ERR_PTR(ret);
	}
	return &console_subchannel;
}

void
cio_release_console(void)
{
	console_subchannel.schib.pmcw.intparm = 0;
	cio_modify(&console_subchannel);
812
	isc_unregister(CONSOLE_ISC);
Linus Torvalds's avatar
Linus Torvalds committed
813
814
815
816
817
	console_subchannel_in_use = 0;
}

/* Bah... hack to catch console special sausages. */
int
818
cio_is_console(struct subchannel_id schid)
Linus Torvalds's avatar
Linus Torvalds committed
819
820
821
{
	if (!console_subchannel_in_use)
		return 0;
822
	return schid_equal(&schid, &console_subchannel.schid);
Linus Torvalds's avatar
Linus Torvalds committed
823
824
825
826
827
828
}

struct subchannel *
cio_get_console_subchannel(void)
{
	if (!console_subchannel_in_use)
Heiko Carstens's avatar
Heiko Carstens committed
829
		return NULL;
Linus Torvalds's avatar
Linus Torvalds committed
830
831
832
	return &console_subchannel;
}

833
834
835
836
837
838
const char *cio_get_console_sch_name(struct subchannel_id schid)
{
	snprintf(console_sch_name, 10, "0.%x.%04x", schid.ssid, schid.sch_no);
	return (const char *)console_sch_name;
}

Linus Torvalds's avatar
Linus Torvalds committed
839
#endif
840
static int
841
__disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
Linus Torvalds's avatar
Linus Torvalds committed
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
{
	int retry, cc;

	cc = 0;
	for (retry=0;retry<3;retry++) {
		schib->pmcw.ena = 0;
		cc = msch(schid, schib);
		if (cc)
			return (cc==3?-ENODEV:-EBUSY);
		stsch(schid, schib);
		if (!schib->pmcw.ena)
			return 0;
	}
	return -EBUSY; /* uhm... */
}

Martin Schwidefsky's avatar
Martin Schwidefsky committed
858
859
860
861
862
863
864
865
866
867
868
869
870
/* we can't use the normal udelay here, since it enables external interrupts */

static void udelay_reset(unsigned long usecs)
{
	uint64_t start_cc, end_cc;

	asm volatile ("STCK %0" : "=m" (start_cc));
	do {
		cpu_relax();
		asm volatile ("STCK %0" : "=m" (end_cc));
	} while (((end_cc - start_cc)/4096) < usecs);
}

871
static int
872
__clear_io_subchannel_easy(struct subchannel_id schid)
Linus Torvalds's avatar
Linus Torvalds committed
873
874
875
876
877
878
879
880
881
{
	int retry;

	if (csch(schid))
		return -ENODEV;
	for (retry=0;retry<20;retry++) {
		struct tpi_info ti;

		if (tpi(&ti)) {
882
883
			tsch(ti.schid, (struct irb *)__LC_IRB);
			if (schid_equal(&ti.schid, &schid))
884
				return 0;
Linus Torvalds's avatar
Linus Torvalds committed
885
		}
Martin Schwidefsky's avatar
Martin Schwidefsky committed
886
		udelay_reset(100);
Linus Torvalds's avatar
Linus Torvalds committed
887
888
889
890
	}
	return -EBUSY;
}

891
892
893
894
895
896
static void __clear_chsc_subchannel_easy(void)
{
	/* It seems we can only wait for a bit here :/ */
	udelay_reset(100);
}

897
898
899
900
901
902
903
904
905
906
907
908
static int pgm_check_occured;

static void cio_reset_pgm_check_handler(void)
{
	pgm_check_occured = 1;
}

static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr)
{
	int rc;

	pgm_check_occured = 0;
909
	s390_base_pgm_handler_fn = cio_reset_pgm_check_handler;
910
	rc = stsch(schid, addr);
911
	s390_base_pgm_handler_fn = NULL;
Michael Holzheu's avatar
Michael Holzheu committed
912

913
	/* The program check handler could have changed pgm_check_occured. */
914
	barrier();
Michael Holzheu's avatar
Michael Holzheu committed
915

916
917
918
919
920
921
	if (pgm_check_occured)
		return -EIO;
	else
		return rc;
}

922
static int __shutdown_subchannel_easy(struct subchannel_id schid, void *data)
923
924
925
{
	struct schib schib;

926
	if (stsch_reset(schid, &schib))
927
928
929
930
931
932
933
934
		return -ENXIO;
	if (!schib.pmcw.ena)
		return 0;
	switch(__disable_subchannel_easy(schid, &schib)) {
	case 0:
	case -ENODEV:
		break;
	default: /* -EBUSY */
935
936
937
938
939
		switch (schib.pmcw.st) {
		case SUBCHANNEL_TYPE_IO:
			if (__clear_io_subchannel_easy(schid))
				goto out; /* give up... */
			break;
940
941
942
		case SUBCHANNEL_TYPE_CHSC:
			__clear_chsc_subchannel_easy();
			break;
943
944
945
946
		default:
			/* No default clear strategy */
			break;
		}
947
948
949
		stsch(schid, &schib);
		__disable_subchannel_easy(schid, &schib);
	}
950
out:
951
952
	return 0;
}
Linus Torvalds's avatar
Linus Torvalds committed
953

954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
static atomic_t chpid_reset_count;

static void s390_reset_chpids_mcck_handler(void)
{
	struct crw crw;
	struct mci *mci;

	/* Check for pending channel report word. */
	mci = (struct mci *)&S390_lowcore.mcck_interruption_code;
	if (!mci->cp)
		return;
	/* Process channel report words. */
	while (stcrw(&crw) == 0) {
		/* Check for responses to RCHP. */
		if (crw.slct && crw.rsc == CRW_RSC_CPATH)
			atomic_dec(&chpid_reset_count);
	}
}

#define RCHP_TIMEOUT (30 * USEC_PER_SEC)
static void css_reset(void)
{
	int i, ret;
	unsigned long long timeout;
978
	struct chp_id chpid;
979
980
981
982

	/* Reset subchannels. */
	for_each_subchannel(__shutdown_subchannel_easy,  NULL);
	/* Reset channel paths. */
983
	s390_base_mcck_handler_fn = s390_reset_chpids_mcck_handler;
984
985
986
987
	/* Enable channel report machine checks. */
	__ctl_set_bit(14, 28);
	/* Temporarily reenable machine checks. */
	local_mcck_enable();
988
	chp_id_init(&chpid);
989
	for (i = 0; i <= __MAX_CHPID; i++) {
990
991
		chpid.id = i;
		ret = rchp(chpid);
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
		if ((ret == 0) || (ret == 2))
			/*
			 * rchp either succeeded, or another rchp is already
			 * in progress. In either case, we'll get a crw.
			 */
			atomic_inc(&chpid_reset_count);
	}
	/* Wait for machine check for all channel paths. */
	timeout = get_clock() + (RCHP_TIMEOUT << 12);
	while (atomic_read(&chpid_reset_count) != 0) {
		if (get_clock() > timeout)
			break;
		cpu_relax();
	}
	/* Disable machine checks again. */
	local_mcck_disable();
	/* Disable channel report machine checks. */
	__ctl_clear_bit(14, 28);
1010
	s390_base_mcck_handler_fn = NULL;
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
}

static struct reset_call css_reset_call = {
	.fn = css_reset,
};

static int __init init_css_reset_call(void)
{
	atomic_set(&chpid_reset_count, 0);
	register_reset_call(&css_reset_call);
	return 0;
}

arch_initcall(init_css_reset_call);

struct sch_match_id {
	struct subchannel_id schid;
	struct ccw_dev_id devid;
	int rc;
};

static int __reipl_subchannel_match(struct subchannel_id schid, void *data)
{
	struct schib schib;
	struct sch_match_id *match_id = data;

1037
	if (stsch_reset(schid, &schib))
1038
		return -ENXIO;
1039
	if ((schib.pmcw.st == SUBCHANNEL_TYPE_IO) && schib.pmcw.dnv &&
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
	    (schib.pmcw.dev == match_id->devid.devno) &&
	    (schid.ssid == match_id->devid.ssid)) {
		match_id->schid = schid;
		match_id->rc = 0;
		return 1;
	}
	return 0;
}

static int reipl_find_schid(struct ccw_dev_id *devid,
			    struct subchannel_id *schid)
Linus Torvalds's avatar
Linus Torvalds committed
1051
{
Michael Holzheu's avatar
Michael Holzheu committed
1052
1053
1054
1055
	struct sch_match_id match_id;

	match_id.devid = *devid;
	match_id.rc = -ENODEV;
1056
	for_each_subchannel(__reipl_subchannel_match, &match_id);
Michael Holzheu's avatar
Michael Holzheu committed
1057
1058
1059
	if (match_id.rc == 0)
		*schid = match_id.schid;
	return match_id.rc;
Linus Torvalds's avatar
Linus Torvalds committed
1060
1061
}

Michael Holzheu's avatar
Michael Holzheu committed
1062
1063
extern void do_reipl_asm(__u32 schid);

Linus Torvalds's avatar
Linus Torvalds committed
1064
/* Make sure all subchannels are quiet before we re-ipl an lpar. */
Michael Holzheu's avatar
Michael Holzheu committed
1065
void reipl_ccw_dev(struct ccw_dev_id *devid)
Linus Torvalds's avatar
Linus Torvalds committed
1066
{
Michael Holzheu's avatar
Michael Holzheu committed
1067
1068
	struct subchannel_id schid;

1069
1070
	s390_reset_system();
	if (reipl_find_schid(devid, &schid) != 0)
Michael Holzheu's avatar
Michael Holzheu committed
1071
1072
		panic("IPL Device not found\n");
	do_reipl_asm(*((__u32*)&schid));
Linus Torvalds's avatar
Linus Torvalds committed
1073
}
1074

1075
int __init cio_get_iplinfo(struct cio_iplinfo *iplinfo)
1076
1077
{
	struct subchannel_id schid;
1078
	struct schib schib;
1079
1080
1081

	schid = *(struct subchannel_id *)__LC_SUBCHANNEL_ID;
	if (!schid.one)
1082
1083
1084
		return -ENODEV;
	if (stsch(schid, &schib))
		return -ENODEV;
1085
1086
	if (schib.pmcw.st != SUBCHANNEL_TYPE_IO)
		return -ENODEV;
1087
1088
1089
1090
1091
	if (!schib.pmcw.dnv)
		return -ENODEV;
	iplinfo->devno = schib.pmcw.dev;
	iplinfo->is_qdio = schib.pmcw.qf;
	return 0;
1092
}
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150

/**
 * cio_tm_start_key - perform start function
 * @sch: subchannel on which to perform the start function
 * @tcw: transport-command word to be started
 * @lpm: mask of paths to use
 * @key: storage key to use for storage access
 *
 * Start the tcw on the given subchannel. Return zero on success, non-zero
 * otherwise.
 */
int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key)
{
	int cc;
	union orb *orb = &to_io_private(sch)->orb;

	memset(orb, 0, sizeof(union orb));
	orb->tm.intparm = (u32) (addr_t) sch;
	orb->tm.key = key >> 4;
	orb->tm.b = 1;
	orb->tm.lpm = lpm ? lpm : sch->lpm;
	orb->tm.tcw = (u32) (addr_t) tcw;
	cc = ssch(sch->schid, orb);
	switch (cc) {
	case 0:
		return 0;
	case 1:
	case 2:
		return -EBUSY;
	default:
		return cio_start_handle_notoper(sch, lpm);
	}
}

/**
 * cio_tm_intrg - perform interrogate function
 * @sch - subchannel on which to perform the interrogate function
 *
 * If the specified subchannel is running in transport-mode, perform the
 * interrogate function. Return zero on success, non-zero otherwie.
 */
int cio_tm_intrg(struct subchannel *sch)
{
	int cc;

	if (!to_io_private(sch)->orb.tm.b)
		return -EINVAL;
	cc = xsch(sch->schid);
	switch (cc) {
	case 0:
	case 2:
		return 0;
	case 1:
		return -EBUSY;
	default:
		return -ENODEV;
	}
}