Blame view

drivers/s390/char/sclp_sdias.c 6.5 KB
411ed3225   Michael Holzheu   [S390] zfcpdump s...
1
  /*
f8049e3e8   Michael Holzheu   s390/sclp: Move d...
2
   * SCLP "store data in absolute storage"
411ed3225   Michael Holzheu   [S390] zfcpdump s...
3
   *
f8049e3e8   Michael Holzheu   s390/sclp: Move d...
4
   * Copyright IBM Corp. 2003, 2013
411ed3225   Michael Holzheu   [S390] zfcpdump s...
5
6
   * Author(s): Michael Holzheu
   */
b3ff088b3   Martin Schwidefsky   [S390] convert sc...
7
8
  #define KMSG_COMPONENT "sclp_sdias"
  #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
e3c652b53   Michael Holzheu   [S390] zfcpdump: ...
9
  #include <linux/completion.h>
411ed3225   Michael Holzheu   [S390] zfcpdump s...
10
11
12
13
  #include <linux/sched.h>
  #include <asm/sclp.h>
  #include <asm/debug.h>
  #include <asm/ipl.h>
b3ff088b3   Martin Schwidefsky   [S390] convert sc...
14

f8049e3e8   Michael Holzheu   s390/sclp: Move d...
15
  #include "sclp_sdias.h"
411ed3225   Michael Holzheu   [S390] zfcpdump s...
16
17
18
19
  #include "sclp.h"
  #include "sclp_rw.h"
  
  #define TRACE(x...) debug_sprintf_event(sdias_dbf, 1, x)
411ed3225   Michael Holzheu   [S390] zfcpdump s...
20
21
22
  
  #define SDIAS_RETRIES 300
  #define SDIAS_SLEEP_TICKS 50
411ed3225   Michael Holzheu   [S390] zfcpdump s...
23
24
25
  static struct debug_info *sdias_dbf;
  
  static struct sclp_register sclp_sdias_register = {
6d4740c89   Stefan Haberland   [S390] sclp: fix ...
26
  	.send_mask = EVTYP_SDIAS_MASK,
411ed3225   Michael Holzheu   [S390] zfcpdump s...
27
  };
411ed3225   Michael Holzheu   [S390] zfcpdump s...
28
  static struct sdias_sccb sccb __attribute__((aligned(4096)));
e3c652b53   Michael Holzheu   [S390] zfcpdump: ...
29
  static struct sdias_evbuf sdias_evbuf;
411ed3225   Michael Holzheu   [S390] zfcpdump s...
30

e3c652b53   Michael Holzheu   [S390] zfcpdump: ...
31
32
  static DECLARE_COMPLETION(evbuf_accepted);
  static DECLARE_COMPLETION(evbuf_done);
411ed3225   Michael Holzheu   [S390] zfcpdump s...
33
  static DEFINE_MUTEX(sdias_mutex);
e3c652b53   Michael Holzheu   [S390] zfcpdump: ...
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  /*
   * Called by SCLP base when read event data has been completed (async mode only)
   */
  static void sclp_sdias_receiver_fn(struct evbuf_header *evbuf)
  {
  	memcpy(&sdias_evbuf, evbuf,
  	       min_t(unsigned long, sizeof(sdias_evbuf), evbuf->length));
  	complete(&evbuf_done);
  	TRACE("sclp_sdias_receiver_fn done
  ");
  }
  
  /*
   * Called by SCLP base when sdias event has been accepted
   */
411ed3225   Michael Holzheu   [S390] zfcpdump s...
49
50
  static void sdias_callback(struct sclp_req *request, void *data)
  {
e3c652b53   Michael Holzheu   [S390] zfcpdump: ...
51
  	complete(&evbuf_accepted);
411ed3225   Michael Holzheu   [S390] zfcpdump s...
52
53
54
55
56
57
58
59
60
61
  	TRACE("callback done
  ");
  }
  
  static int sdias_sclp_send(struct sclp_req *req)
  {
  	int retries;
  	int rc;
  
  	for (retries = SDIAS_RETRIES; retries; retries--) {
411ed3225   Michael Holzheu   [S390] zfcpdump s...
62
63
64
65
66
67
68
69
70
71
72
73
  		TRACE("add request
  ");
  		rc = sclp_add_request(req);
  		if (rc) {
  			/* not initiated, wait some time and retry */
  			set_current_state(TASK_INTERRUPTIBLE);
  			TRACE("add request failed: rc = %i
  ",rc);
  			schedule_timeout(SDIAS_SLEEP_TICKS);
  			continue;
  		}
  		/* initiated, wait for completion of service call */
e3c652b53   Michael Holzheu   [S390] zfcpdump: ...
74
  		wait_for_completion(&evbuf_accepted);
411ed3225   Michael Holzheu   [S390] zfcpdump s...
75
76
77
  		if (req->status == SCLP_REQ_FAILED) {
  			TRACE("sclp request failed
  ");
411ed3225   Michael Holzheu   [S390] zfcpdump s...
78
79
  			continue;
  		}
e3c652b53   Michael Holzheu   [S390] zfcpdump: ...
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
  		/* if not accepted, retry */
  		if (!(sccb.evbuf.hdr.flags & 0x80)) {
  			TRACE("sclp request failed: flags=%x
  ",
  			      sccb.evbuf.hdr.flags);
  			continue;
  		}
  		/*
  		 * for the sync interface the response is in the initial sccb
  		 */
  		if (!sclp_sdias_register.receiver_fn) {
  			memcpy(&sdias_evbuf, &sccb.evbuf, sizeof(sdias_evbuf));
  			TRACE("sync request done
  ");
  			return 0;
  		}
  		/* otherwise we wait for completion */
  		wait_for_completion(&evbuf_done);
411ed3225   Michael Holzheu   [S390] zfcpdump s...
98
99
  		TRACE("request done
  ");
e3c652b53   Michael Holzheu   [S390] zfcpdump: ...
100
  		return 0;
411ed3225   Michael Holzheu   [S390] zfcpdump s...
101
  	}
e3c652b53   Michael Holzheu   [S390] zfcpdump: ...
102
  	return -EIO;
411ed3225   Michael Holzheu   [S390] zfcpdump s...
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
  }
  
  /*
   * Get number of blocks (4K) available in the HSA
   */
  int sclp_sdias_blk_count(void)
  {
  	struct sclp_req request;
  	int rc;
  
  	mutex_lock(&sdias_mutex);
  
  	memset(&sccb, 0, sizeof(sccb));
  	memset(&request, 0, sizeof(request));
  
  	sccb.hdr.length = sizeof(sccb);
  	sccb.evbuf.hdr.length = sizeof(struct sdias_evbuf);
6d4740c89   Stefan Haberland   [S390] sclp: fix ...
120
  	sccb.evbuf.hdr.type = EVTYP_SDIAS;
f8049e3e8   Michael Holzheu   s390/sclp: Move d...
121
122
  	sccb.evbuf.event_qual = SDIAS_EQ_SIZE;
  	sccb.evbuf.data_id = SDIAS_DI_FCP_DUMP;
411ed3225   Michael Holzheu   [S390] zfcpdump s...
123
124
125
126
127
128
129
130
131
132
  	sccb.evbuf.event_id = 4712;
  	sccb.evbuf.dbs = 1;
  
  	request.sccb = &sccb;
  	request.command = SCLP_CMDW_WRITE_EVENT_DATA;
  	request.status = SCLP_REQ_FILLED;
  	request.callback = sdias_callback;
  
  	rc = sdias_sclp_send(&request);
  	if (rc) {
b3ff088b3   Martin Schwidefsky   [S390] convert sc...
133
134
  		pr_err("sclp_send failed for get_nr_blocks
  ");
411ed3225   Michael Holzheu   [S390] zfcpdump s...
135
136
137
138
139
140
141
142
  		goto out;
  	}
  	if (sccb.hdr.response_code != 0x0020) {
  		TRACE("send failed: %x
  ", sccb.hdr.response_code);
  		rc = -EIO;
  		goto out;
  	}
e3c652b53   Michael Holzheu   [S390] zfcpdump: ...
143
  	switch (sdias_evbuf.event_status) {
411ed3225   Michael Holzheu   [S390] zfcpdump s...
144
  		case 0:
e3c652b53   Michael Holzheu   [S390] zfcpdump: ...
145
  			rc = sdias_evbuf.blk_cnt;
411ed3225   Michael Holzheu   [S390] zfcpdump s...
146
147
  			break;
  		default:
e3c652b53   Michael Holzheu   [S390] zfcpdump: ...
148
149
  			pr_err("SCLP error: %x
  ", sdias_evbuf.event_status);
411ed3225   Michael Holzheu   [S390] zfcpdump s...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  			rc = -EIO;
  			goto out;
  	}
  	TRACE("%i blocks
  ", rc);
  out:
  	mutex_unlock(&sdias_mutex);
  	return rc;
  }
  
  /*
   * Copy from HSA to absolute storage (not reentrant):
   *
   * @dest     : Address of buffer where data should be copied
   * @start_blk: Start Block (beginning with 1)
   * @nr_blks  : Number of 4K blocks to copy
   *
   * Return Value: 0 : Requested 'number' of blocks of data copied
   *		 <0: ERROR - negative event status
   */
  int sclp_sdias_copy(void *dest, int start_blk, int nr_blks)
  {
  	struct sclp_req request;
  	int rc;
  
  	mutex_lock(&sdias_mutex);
  
  	memset(&sccb, 0, sizeof(sccb));
  	memset(&request, 0, sizeof(request));
  
  	sccb.hdr.length = sizeof(sccb);
  	sccb.evbuf.hdr.length = sizeof(struct sdias_evbuf);
6d4740c89   Stefan Haberland   [S390] sclp: fix ...
182
  	sccb.evbuf.hdr.type = EVTYP_SDIAS;
411ed3225   Michael Holzheu   [S390] zfcpdump s...
183
  	sccb.evbuf.hdr.flags = 0;
f8049e3e8   Michael Holzheu   s390/sclp: Move d...
184
185
  	sccb.evbuf.event_qual = SDIAS_EQ_STORE_DATA;
  	sccb.evbuf.data_id = SDIAS_DI_FCP_DUMP;
411ed3225   Michael Holzheu   [S390] zfcpdump s...
186
  	sccb.evbuf.event_id = 4712;
f4815ac6c   Heiko Carstens   s390/headers: rep...
187
  #ifdef CONFIG_64BIT
f8049e3e8   Michael Holzheu   s390/sclp: Move d...
188
  	sccb.evbuf.asa_size = SDIAS_ASA_SIZE_64;
411ed3225   Michael Holzheu   [S390] zfcpdump s...
189
  #else
f8049e3e8   Michael Holzheu   s390/sclp: Move d...
190
  	sccb.evbuf.asa_size = SDIAS_ASA_SIZE_32;
411ed3225   Michael Holzheu   [S390] zfcpdump s...
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
  #endif
  	sccb.evbuf.event_status = 0;
  	sccb.evbuf.blk_cnt = nr_blks;
  	sccb.evbuf.asa = (unsigned long)dest;
  	sccb.evbuf.fbn = start_blk;
  	sccb.evbuf.lbn = 0;
  	sccb.evbuf.dbs = 1;
  
  	request.sccb	 = &sccb;
  	request.command  = SCLP_CMDW_WRITE_EVENT_DATA;
  	request.status	 = SCLP_REQ_FILLED;
  	request.callback = sdias_callback;
  
  	rc = sdias_sclp_send(&request);
  	if (rc) {
b3ff088b3   Martin Schwidefsky   [S390] convert sc...
206
207
  		pr_err("sclp_send failed: %x
  ", rc);
411ed3225   Michael Holzheu   [S390] zfcpdump s...
208
209
210
211
212
213
214
215
  		goto out;
  	}
  	if (sccb.hdr.response_code != 0x0020) {
  		TRACE("copy failed: %x
  ", sccb.hdr.response_code);
  		rc = -EIO;
  		goto out;
  	}
e3c652b53   Michael Holzheu   [S390] zfcpdump: ...
216
  	switch (sdias_evbuf.event_status) {
f8049e3e8   Michael Holzheu   s390/sclp: Move d...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
  	case SDIAS_EVSTATE_ALL_STORED:
  		TRACE("all stored
  ");
  		break;
  	case SDIAS_EVSTATE_PART_STORED:
  		TRACE("part stored: %i
  ", sdias_evbuf.blk_cnt);
  		break;
  	case SDIAS_EVSTATE_NO_DATA:
  		TRACE("no data
  ");
  		/* fall through */
  	default:
  		pr_err("Error from SCLP while copying hsa. Event status = %x
  ",
  		       sdias_evbuf.event_status);
  		rc = -EIO;
411ed3225   Michael Holzheu   [S390] zfcpdump s...
234
235
236
237
238
  	}
  out:
  	mutex_unlock(&sdias_mutex);
  	return rc;
  }
e3c652b53   Michael Holzheu   [S390] zfcpdump: ...
239
  static int __init sclp_sdias_register_check(void)
411ed3225   Michael Holzheu   [S390] zfcpdump s...
240
241
  {
  	int rc;
e3c652b53   Michael Holzheu   [S390] zfcpdump: ...
242
243
244
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
  	rc = sclp_register(&sclp_sdias_register);
  	if (rc)
  		return rc;
  	if (sclp_sdias_blk_count() == 0) {
  		sclp_unregister(&sclp_sdias_register);
  		return -ENODEV;
  	}
  	return 0;
  }
  
  static int __init sclp_sdias_init_sync(void)
  {
  	TRACE("Try synchronous mode
  ");
  	sclp_sdias_register.receive_mask = 0;
  	sclp_sdias_register.receiver_fn = NULL;
  	return sclp_sdias_register_check();
  }
  
  static int __init sclp_sdias_init_async(void)
  {
  	TRACE("Try asynchronous mode
  ");
  	sclp_sdias_register.receive_mask = EVTYP_SDIAS_MASK;
  	sclp_sdias_register.receiver_fn = sclp_sdias_receiver_fn;
  	return sclp_sdias_register_check();
  }
  
  int __init sclp_sdias_init(void)
  {
411ed3225   Michael Holzheu   [S390] zfcpdump s...
272
273
274
275
276
  	if (ipl_info.type != IPL_TYPE_FCP_DUMP)
  		return 0;
  	sdias_dbf = debug_register("dump_sdias", 4, 1, 4 * sizeof(long));
  	debug_register_view(sdias_dbf, &debug_sprintf_view);
  	debug_set_level(sdias_dbf, 6);
e3c652b53   Michael Holzheu   [S390] zfcpdump: ...
277
278
279
280
281
282
283
284
  	if (sclp_sdias_init_sync() == 0)
  		goto out;
  	if (sclp_sdias_init_async() == 0)
  		goto out;
  	TRACE("init failed
  ");
  	return -ENODEV;
  out:
411ed3225   Michael Holzheu   [S390] zfcpdump s...
285
286
287
288
  	TRACE("init done
  ");
  	return 0;
  }
763968e21   Heiko Carstens   [S390] Avoid spar...
289
  void __exit sclp_sdias_exit(void)
411ed3225   Michael Holzheu   [S390] zfcpdump s...
290
291
292
293
  {
  	debug_unregister(sdias_dbf);
  	sclp_unregister(&sclp_sdias_register);
  }