xref: /openbmc/linux/drivers/s390/char/sclp_sdias.c (revision c819e2cf)
1 /*
2  * SCLP "store data in absolute storage"
3  *
4  * Copyright IBM Corp. 2003, 2013
5  * Author(s): Michael Holzheu
6  */
7 
8 #define KMSG_COMPONENT "sclp_sdias"
9 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
10 
11 #include <linux/completion.h>
12 #include <linux/sched.h>
13 #include <asm/sclp.h>
14 #include <asm/debug.h>
15 #include <asm/ipl.h>
16 
17 #include "sclp_sdias.h"
18 #include "sclp.h"
19 #include "sclp_rw.h"
20 
21 #define TRACE(x...) debug_sprintf_event(sdias_dbf, 1, x)
22 
23 #define SDIAS_RETRIES 300
24 #define SDIAS_SLEEP_TICKS 50
25 
26 static struct debug_info *sdias_dbf;
27 
28 static struct sclp_register sclp_sdias_register = {
29 	.send_mask = EVTYP_SDIAS_MASK,
30 };
31 
32 static struct sdias_sccb sccb __attribute__((aligned(4096)));
33 static struct sdias_evbuf sdias_evbuf;
34 
35 static DECLARE_COMPLETION(evbuf_accepted);
36 static DECLARE_COMPLETION(evbuf_done);
37 static DEFINE_MUTEX(sdias_mutex);
38 
39 /*
40  * Called by SCLP base when read event data has been completed (async mode only)
41  */
42 static void sclp_sdias_receiver_fn(struct evbuf_header *evbuf)
43 {
44 	memcpy(&sdias_evbuf, evbuf,
45 	       min_t(unsigned long, sizeof(sdias_evbuf), evbuf->length));
46 	complete(&evbuf_done);
47 	TRACE("sclp_sdias_receiver_fn done\n");
48 }
49 
50 /*
51  * Called by SCLP base when sdias event has been accepted
52  */
53 static void sdias_callback(struct sclp_req *request, void *data)
54 {
55 	complete(&evbuf_accepted);
56 	TRACE("callback done\n");
57 }
58 
59 static int sdias_sclp_send(struct sclp_req *req)
60 {
61 	int retries;
62 	int rc;
63 
64 	for (retries = SDIAS_RETRIES; retries; retries--) {
65 		TRACE("add request\n");
66 		rc = sclp_add_request(req);
67 		if (rc) {
68 			/* not initiated, wait some time and retry */
69 			set_current_state(TASK_INTERRUPTIBLE);
70 			TRACE("add request failed: rc = %i\n",rc);
71 			schedule_timeout(SDIAS_SLEEP_TICKS);
72 			continue;
73 		}
74 		/* initiated, wait for completion of service call */
75 		wait_for_completion(&evbuf_accepted);
76 		if (req->status == SCLP_REQ_FAILED) {
77 			TRACE("sclp request failed\n");
78 			continue;
79 		}
80 		/* if not accepted, retry */
81 		if (!(sccb.evbuf.hdr.flags & 0x80)) {
82 			TRACE("sclp request failed: flags=%x\n",
83 			      sccb.evbuf.hdr.flags);
84 			continue;
85 		}
86 		/*
87 		 * for the sync interface the response is in the initial sccb
88 		 */
89 		if (!sclp_sdias_register.receiver_fn) {
90 			memcpy(&sdias_evbuf, &sccb.evbuf, sizeof(sdias_evbuf));
91 			TRACE("sync request done\n");
92 			return 0;
93 		}
94 		/* otherwise we wait for completion */
95 		wait_for_completion(&evbuf_done);
96 		TRACE("request done\n");
97 		return 0;
98 	}
99 	return -EIO;
100 }
101 
102 /*
103  * Get number of blocks (4K) available in the HSA
104  */
105 int sclp_sdias_blk_count(void)
106 {
107 	struct sclp_req request;
108 	int rc;
109 
110 	mutex_lock(&sdias_mutex);
111 
112 	memset(&sccb, 0, sizeof(sccb));
113 	memset(&request, 0, sizeof(request));
114 
115 	sccb.hdr.length = sizeof(sccb);
116 	sccb.evbuf.hdr.length = sizeof(struct sdias_evbuf);
117 	sccb.evbuf.hdr.type = EVTYP_SDIAS;
118 	sccb.evbuf.event_qual = SDIAS_EQ_SIZE;
119 	sccb.evbuf.data_id = SDIAS_DI_FCP_DUMP;
120 	sccb.evbuf.event_id = 4712;
121 	sccb.evbuf.dbs = 1;
122 
123 	request.sccb = &sccb;
124 	request.command = SCLP_CMDW_WRITE_EVENT_DATA;
125 	request.status = SCLP_REQ_FILLED;
126 	request.callback = sdias_callback;
127 
128 	rc = sdias_sclp_send(&request);
129 	if (rc) {
130 		pr_err("sclp_send failed for get_nr_blocks\n");
131 		goto out;
132 	}
133 	if (sccb.hdr.response_code != 0x0020) {
134 		TRACE("send failed: %x\n", sccb.hdr.response_code);
135 		rc = -EIO;
136 		goto out;
137 	}
138 
139 	switch (sdias_evbuf.event_status) {
140 		case 0:
141 			rc = sdias_evbuf.blk_cnt;
142 			break;
143 		default:
144 			pr_err("SCLP error: %x\n", sdias_evbuf.event_status);
145 			rc = -EIO;
146 			goto out;
147 	}
148 	TRACE("%i blocks\n", rc);
149 out:
150 	mutex_unlock(&sdias_mutex);
151 	return rc;
152 }
153 
154 /*
155  * Copy from HSA to absolute storage (not reentrant):
156  *
157  * @dest     : Address of buffer where data should be copied
158  * @start_blk: Start Block (beginning with 1)
159  * @nr_blks  : Number of 4K blocks to copy
160  *
161  * Return Value: 0 : Requested 'number' of blocks of data copied
162  *		 <0: ERROR - negative event status
163  */
164 int sclp_sdias_copy(void *dest, int start_blk, int nr_blks)
165 {
166 	struct sclp_req request;
167 	int rc;
168 
169 	mutex_lock(&sdias_mutex);
170 
171 	memset(&sccb, 0, sizeof(sccb));
172 	memset(&request, 0, sizeof(request));
173 
174 	sccb.hdr.length = sizeof(sccb);
175 	sccb.evbuf.hdr.length = sizeof(struct sdias_evbuf);
176 	sccb.evbuf.hdr.type = EVTYP_SDIAS;
177 	sccb.evbuf.hdr.flags = 0;
178 	sccb.evbuf.event_qual = SDIAS_EQ_STORE_DATA;
179 	sccb.evbuf.data_id = SDIAS_DI_FCP_DUMP;
180 	sccb.evbuf.event_id = 4712;
181 #ifdef CONFIG_64BIT
182 	sccb.evbuf.asa_size = SDIAS_ASA_SIZE_64;
183 #else
184 	sccb.evbuf.asa_size = SDIAS_ASA_SIZE_32;
185 #endif
186 	sccb.evbuf.event_status = 0;
187 	sccb.evbuf.blk_cnt = nr_blks;
188 	sccb.evbuf.asa = (unsigned long)dest;
189 	sccb.evbuf.fbn = start_blk;
190 	sccb.evbuf.lbn = 0;
191 	sccb.evbuf.dbs = 1;
192 
193 	request.sccb	 = &sccb;
194 	request.command  = SCLP_CMDW_WRITE_EVENT_DATA;
195 	request.status	 = SCLP_REQ_FILLED;
196 	request.callback = sdias_callback;
197 
198 	rc = sdias_sclp_send(&request);
199 	if (rc) {
200 		pr_err("sclp_send failed: %x\n", rc);
201 		goto out;
202 	}
203 	if (sccb.hdr.response_code != 0x0020) {
204 		TRACE("copy failed: %x\n", sccb.hdr.response_code);
205 		rc = -EIO;
206 		goto out;
207 	}
208 
209 	switch (sdias_evbuf.event_status) {
210 	case SDIAS_EVSTATE_ALL_STORED:
211 		TRACE("all stored\n");
212 		break;
213 	case SDIAS_EVSTATE_PART_STORED:
214 		TRACE("part stored: %i\n", sdias_evbuf.blk_cnt);
215 		break;
216 	case SDIAS_EVSTATE_NO_DATA:
217 		TRACE("no data\n");
218 		/* fall through */
219 	default:
220 		pr_err("Error from SCLP while copying hsa. Event status = %x\n",
221 		       sdias_evbuf.event_status);
222 		rc = -EIO;
223 	}
224 out:
225 	mutex_unlock(&sdias_mutex);
226 	return rc;
227 }
228 
229 static int __init sclp_sdias_register_check(void)
230 {
231 	int rc;
232 
233 	rc = sclp_register(&sclp_sdias_register);
234 	if (rc)
235 		return rc;
236 	if (sclp_sdias_blk_count() == 0) {
237 		sclp_unregister(&sclp_sdias_register);
238 		return -ENODEV;
239 	}
240 	return 0;
241 }
242 
243 static int __init sclp_sdias_init_sync(void)
244 {
245 	TRACE("Try synchronous mode\n");
246 	sclp_sdias_register.receive_mask = 0;
247 	sclp_sdias_register.receiver_fn = NULL;
248 	return sclp_sdias_register_check();
249 }
250 
251 static int __init sclp_sdias_init_async(void)
252 {
253 	TRACE("Try asynchronous mode\n");
254 	sclp_sdias_register.receive_mask = EVTYP_SDIAS_MASK;
255 	sclp_sdias_register.receiver_fn = sclp_sdias_receiver_fn;
256 	return sclp_sdias_register_check();
257 }
258 
259 int __init sclp_sdias_init(void)
260 {
261 	if (ipl_info.type != IPL_TYPE_FCP_DUMP)
262 		return 0;
263 	sdias_dbf = debug_register("dump_sdias", 4, 1, 4 * sizeof(long));
264 	debug_register_view(sdias_dbf, &debug_sprintf_view);
265 	debug_set_level(sdias_dbf, 6);
266 	if (sclp_sdias_init_sync() == 0)
267 		goto out;
268 	if (sclp_sdias_init_async() == 0)
269 		goto out;
270 	TRACE("init failed\n");
271 	return -ENODEV;
272 out:
273 	TRACE("init done\n");
274 	return 0;
275 }
276 
277 void __exit sclp_sdias_exit(void)
278 {
279 	debug_unregister(sdias_dbf);
280 	sclp_unregister(&sclp_sdias_register);
281 }
282