summaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/s390mach.c
blob: 750e50c30c67b6e27737cfeedec53a1be766fe14 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
 *  arch/s390/kernel/s390mach.c
 *   S/390 machine check handler,
 *            currently only channel-reports are supported
 *
 *  S390 version
 *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
 *    Author(s): Ingo Adlung (adlung@de.ibm.com)
 */

#include <linux/init.h>

#include <asm/irq.h>
#include <asm/lowcore.h>
#include <asm/semaphore.h>
#include <asm/s390io.h>
#include <asm/s390dyn.h>
#include <asm/s390mach.h>

#define S390_MACHCHK_DEBUG

static mchchk_queue_element_t *mchchk_queue_head = NULL;
static mchchk_queue_element_t *mchchk_queue_tail = NULL;
static mchchk_queue_element_t *mchchk_queue_free = NULL;
static spinlock_t              mchchk_queue_lock;
static struct semaphore        s_sem[2];

//
// initialize machine check handling
//
void s390_init_machine_check( void )
{
	init_MUTEX_LOCKED( &s_sem[0] );
	init_MUTEX_LOCKED( &s_sem[1] );

#if 0
	//
	// fix me ! initialize a machine check queue with 100 elements
	//
#ifdef S390_MACHCHK_DEBUG
	printk( "init_mach : starting kernel thread\n");
#endif	

	kernel_thread( s390_machine_check_handler, s_sem, 0);

	//
	// wait for the machine check handler to be ready
	//
#ifdef S390_MACHCHK_DEBUG
	printk( "init_mach : waiting for kernel thread\n");
#endif	

	down( &sem[0]);

#ifdef S390_MACHCHK_DEBUG
	printk( "init_mach : kernel thread ready\n");
#endif	

	//
	// fix me ! we have to initialize CR14 to allow for CRW pending
	//           conditions

	//
	// fix me ! enable machine checks in the PSW
	//
#endif
	return;
}

//
// machine check pre-processor
//
void __init s390_do_machine_check( void )
{
   // fix me ! we have to check for machine check and
   //          post the handler eventually

	return;
}

//
// machine check handler
//
static void __init s390_machine_check_handler( struct semaphore *sem )
{
#ifdef S390_MACHCHK_DEBUG
	printk( "mach_handler : kernel thread up\n");
#endif	

	up( &sem[0] );

#ifdef S390_MACHCHK_DEBUG
	printk( "mach_handler : kernel thread ready\n");
#endif	

	do {

#ifdef S390_MACHCHK_DEBUG
	printk( "mach_handler : waiting for wakeup\n");
#endif	

		down_interruptible( &sem[1] );
#ifdef S390_MACHCHK_DEBUG
	printk( "mach_handler : wakeup\n");
#endif	

		break;	// fix me ! unconditional surrender ...
  	
		// fix me ! check for machine checks and
		//          call do_crw_pending() eventually
	
	} while (1);

	return;
}

mchchk_queue_element_t *s390_get_mchchk( void )
{
	unsigned long           flags;
	mchchk_queue_element_t *qe;

	spin_lock_irqsave( &mchchk_queue_lock, flags );

	// fix me ! dequeue first element if available
	qe = NULL;

	spin_unlock_irqrestore( &mchchk_queue_lock, flags );

	return qe;
}

void s390_free_mchchk( mchchk_queue_element_t *mchchk )
{
	unsigned long flags;

	if ( mchchk != NULL)
	{
		spin_lock_irqsave( &mchchk_queue_lock, flags );
		
		mchchk->next      = mchchk_queue_free;

		if ( mchchk_queue_free != NULL )
		{
			mchchk_queue_free->prev = mchchk;

		} /* endif */

		mchchk->prev      = NULL;
		mchchk_queue_free = mchchk;

		spin_unlock_irqrestore( &mchchk_queue_lock, flags );

	} /* endif */

	return;
}