xref: /openbmc/linux/drivers/s390/char/sclp_sdias.c (revision 94cdda6b)
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 	sccb.evbuf.asa_size = SDIAS_ASA_SIZE_64;
182 	sccb.evbuf.event_status = 0;
183 	sccb.evbuf.blk_cnt = nr_blks;
184 	sccb.evbuf.asa = (unsigned long)dest;
185 	sccb.evbuf.fbn = start_blk;
186 	sccb.evbuf.lbn = 0;
187 	sccb.evbuf.dbs = 1;
188 
189 	request.sccb	 = &sccb;
190 	request.command  = SCLP_CMDW_WRITE_EVENT_DATA;
191 	request.status	 = SCLP_REQ_FILLED;
192 	request.callback = sdias_callback;
193 
194 	rc = sdias_sclp_send(&request);
195 	if (rc) {
196 		pr_err("sclp_send failed: %x\n", rc);
197 		goto out;
198 	}
199 	if (sccb.hdr.response_code != 0x0020) {
200 		TRACE("copy failed: %x\n", sccb.hdr.response_code);
201 		rc = -EIO;
202 		goto out;
203 	}
204 
205 	switch (sdias_evbuf.event_status) {
206 	case SDIAS_EVSTATE_ALL_STORED:
207 		TRACE("all stored\n");
208 		break;
209 	case SDIAS_EVSTATE_PART_STORED:
210 		TRACE("part stored: %i\n", sdias_evbuf.blk_cnt);
211 		break;
212 	case SDIAS_EVSTATE_NO_DATA:
213 		TRACE("no data\n");
214 		/* fall through */
215 	default:
216 		pr_err("Error from SCLP while copying hsa. Event status = %x\n",
217 		       sdias_evbuf.event_status);
218 		rc = -EIO;
219 	}
220 out:
221 	mutex_unlock(&sdias_mutex);
222 	return rc;
223 }
224 
225 static int __init sclp_sdias_register_check(void)
226 {
227 	int rc;
228 
229 	rc = sclp_register(&sclp_sdias_register);
230 	if (rc)
231 		return rc;
232 	if (sclp_sdias_blk_count() == 0) {
233 		sclp_unregister(&sclp_sdias_register);
234 		return -ENODEV;
235 	}
236 	return 0;
237 }
238 
239 static int __init sclp_sdias_init_sync(void)
240 {
241 	TRACE("Try synchronous mode\n");
242 	sclp_sdias_register.receive_mask = 0;
243 	sclp_sdias_register.receiver_fn = NULL;
244 	return sclp_sdias_register_check();
245 }
246 
247 static int __init sclp_sdias_init_async(void)
248 {
249 	TRACE("Try asynchronous mode\n");
250 	sclp_sdias_register.receive_mask = EVTYP_SDIAS_MASK;
251 	sclp_sdias_register.receiver_fn = sclp_sdias_receiver_fn;
252 	return sclp_sdias_register_check();
253 }
254 
255 int __init sclp_sdias_init(void)
256 {
257 	if (ipl_info.type != IPL_TYPE_FCP_DUMP)
258 		return 0;
259 	sdias_dbf = debug_register("dump_sdias", 4, 1, 4 * sizeof(long));
260 	debug_register_view(sdias_dbf, &debug_sprintf_view);
261 	debug_set_level(sdias_dbf, 6);
262 	if (sclp_sdias_init_sync() == 0)
263 		goto out;
264 	if (sclp_sdias_init_async() == 0)
265 		goto out;
266 	TRACE("init failed\n");
267 	return -ENODEV;
268 out:
269 	TRACE("init done\n");
270 	return 0;
271 }
272 
273 void __exit sclp_sdias_exit(void)
274 {
275 	debug_unregister(sdias_dbf);
276 	sclp_unregister(&sclp_sdias_register);
277 }
278