1 /* Copyright 2013-2014 IBM Corp.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * 	http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12  * implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * Service Processor serial console handling code
19  */
20 #include <skiboot.h>
21 #include <processor.h>
22 #include <io.h>
23 #include <fsp.h>
24 #include <console.h>
25 #include <opal.h>
26 #include <timebase.h>
27 #include <device.h>
28 #include <fsp-sysparam.h>
29 #include <errorlog.h>
30 #include <lock.h>
31 
32 DEFINE_LOG_ENTRY(OPAL_RC_CONSOLE_HANG, OPAL_PLATFORM_ERR_EVT, OPAL_CONSOLE,
33 		 OPAL_PLATFORM_FIRMWARE,
34 		 OPAL_PREDICTIVE_ERR_GENERAL, OPAL_NA);
35 
36 struct fsp_serbuf_hdr {
37 	u16	partition_id;
38 	u8	session_id;
39 	u8	hmc_id;
40 	u16	data_offset;
41 	u16	last_valid;
42 	u16	ovf_count;
43 	u16	next_in;
44 	u8	flags;
45 	u8	reserved;
46 	u16	next_out;
47 	u8	data[];
48 };
49 #define SER_BUF_DATA_SIZE	(0x10000 - sizeof(struct fsp_serbuf_hdr))
50 
51 struct fsp_serial {
52 	bool			available;
53 	bool			open;
54 	bool			has_part0;
55 	bool			has_part1;
56 	bool			log_port;
57 	bool			out_poke;
58 	char			loc_code[LOC_CODE_SIZE];
59 	u16			rsrc_id;
60 	struct fsp_serbuf_hdr	*in_buf;
61 	struct fsp_serbuf_hdr	*out_buf;
62 	struct fsp_msg		*poke_msg;
63 	u8			waiting;
64 	u64			irq;
65 	u16			out_buf_prev_len;
66 	u64			out_buf_timeout;
67 };
68 
69 #define SER_BUFFER_SIZE 0x00040000UL
70 #define MAX_SERIAL	4
71 
72 #define SER_BUFFER_OUT_TIMEOUT	10
73 
74 static struct fsp_serial fsp_serials[MAX_SERIAL];
75 static bool got_intf_query;
76 static struct lock fsp_con_lock = LOCK_UNLOCKED;
77 static void* ser_buffer = NULL;
78 
fsp_console_reinit(void)79 static void fsp_console_reinit(void)
80 {
81 	int i;
82 	void *base;
83 	struct fsp_msg *msg;
84 
85 	/* Initialize out data structure pointers & TCE maps */
86 	base = ser_buffer;
87 	for (i = 0; i < MAX_SERIAL; i++) {
88 		struct fsp_serial *ser = &fsp_serials[i];
89 
90 		ser->in_buf = base;
91 		ser->out_buf = base + SER_BUFFER_SIZE/2;
92 		base += SER_BUFFER_SIZE;
93 	}
94 	fsp_tce_map(PSI_DMA_SER0_BASE, ser_buffer,
95 			4 * PSI_DMA_SER0_SIZE);
96 
97 	for (i = 0; i < MAX_SERIAL; i++) {
98 		struct fsp_serial *fs = &fsp_serials[i];
99 
100 		if (!fs->available)
101 			continue;
102 
103 		if (fs->rsrc_id == 0xffff)
104 			continue;
105 		prlog(PR_DEBUG, "FSP: Reassociating HVSI console %d\n", i);
106 		msg = fsp_mkmsg(FSP_CMD_ASSOC_SERIAL, 2,
107 				(fs->rsrc_id << 16) | 1, i);
108 		if (!msg) {
109 			prerror("FSPCON: Failed to allocate associate msg\n");
110 			return;
111 		}
112 		if (fsp_queue_msg(msg, fsp_freemsg)) {
113 			fsp_freemsg(msg);
114 			prerror("FSPCON: Failed to queue associate msg\n");
115 			return;
116 		}
117 	}
118 }
119 
fsp_close_consoles(void)120 static void fsp_close_consoles(void)
121 {
122 	unsigned int i;
123 
124 	for (i = 0; i < MAX_SERIAL; i++) {
125 		struct fsp_serial *fs = &fsp_serials[i];
126 
127 		if (!fs->available)
128 			continue;
129 
130 		lock(&fsp_con_lock);
131 		if (fs->open) {
132 			fs->open = false;
133 			fs->out_poke = false;
134 			if (fs->poke_msg->state != fsp_msg_unused)
135 				fsp_cancelmsg(fs->poke_msg);
136 			fsp_freemsg(fs->poke_msg);
137 			fs->poke_msg = NULL;
138 		}
139 		unlock(&fsp_con_lock);
140 	}
141 	prlog(PR_DEBUG, "FSPCON: Closed consoles due to FSP reset/reload\n");
142 }
143 
fsp_pokemsg_reclaim(struct fsp_msg * msg)144 static void fsp_pokemsg_reclaim(struct fsp_msg *msg)
145 {
146 	struct fsp_serial *fs = msg->user_data;
147 
148 	/*
149 	 * The poke_msg might have been "detached" from the console
150 	 * in vserial_close, so we need to check whether it's current
151 	 * before touching the state, otherwise, just free it
152 	 */
153 	lock(&fsp_con_lock);
154 	if (fs->open && fs->poke_msg == msg) {
155 		if (fs->out_poke) {
156 			if (fsp_queue_msg(fs->poke_msg, fsp_pokemsg_reclaim)) {
157 				prerror("FSPCON: failed to queue poke msg\n");
158 			} else {
159 				fs->out_poke = false;
160 			}
161 		} else
162 			fs->poke_msg->state = fsp_msg_unused;
163 	} else
164 		fsp_freemsg(msg);
165 	unlock(&fsp_con_lock);
166 }
167 
168 /* Called with the fsp_con_lock held */
fsp_write_vserial(struct fsp_serial * fs,const char * buf,size_t len)169 static size_t fsp_write_vserial(struct fsp_serial *fs, const char *buf,
170 				size_t len)
171 {
172 	struct fsp_serbuf_hdr *sb = fs->out_buf;
173 	u16 old_nin = sb->next_in;
174 	u16 space, chunk;
175 
176 	if (!fs->open)
177 		return 0;
178 
179 	space = (sb->next_out + SER_BUF_DATA_SIZE - old_nin - 1)
180 		% SER_BUF_DATA_SIZE;
181 	if (space < len)
182 		len = space;
183 	if (!len)
184 		return 0;
185 
186 	chunk = SER_BUF_DATA_SIZE - old_nin;
187 	if (chunk > len)
188 		chunk = len;
189 	memcpy(&sb->data[old_nin], buf, chunk);
190 	if (chunk < len)
191 		memcpy(&sb->data[0], buf + chunk, len - chunk);
192 	lwsync();
193 	sb->next_in = (old_nin + len) % SER_BUF_DATA_SIZE;
194 	sync();
195 
196 	if (sb->next_out == old_nin && fs->poke_msg) {
197 		if (fs->poke_msg->state == fsp_msg_unused) {
198 			if (fsp_queue_msg(fs->poke_msg, fsp_pokemsg_reclaim))
199 				prerror("FSPCON: poke msg queuing failed\n");
200 		} else
201 			fs->out_poke = true;
202 	}
203 #ifndef DISABLE_CON_PENDING_EVT
204 	opal_update_pending_evt(OPAL_EVENT_CONSOLE_OUTPUT,
205 				OPAL_EVENT_CONSOLE_OUTPUT);
206 #endif
207 	return len;
208 }
209 
210 #ifdef DVS_CONSOLE
211 static int fsp_con_port = -1;
212 static bool fsp_con_full;
213 
214 /*
215  * This is called by the code in console.c without the con_lock
216  * held. However it can be called as the result of any printf
217  * thus any other lock might be held including possibly the
218  * FSP lock
219  */
fsp_con_write(const char * buf,size_t len)220 static size_t fsp_con_write(const char *buf, size_t len)
221 {
222 	size_t written;
223 
224 	if (fsp_con_port < 0)
225 		return 0;
226 
227 	lock(&fsp_con_lock);
228 	written = fsp_write_vserial(&fsp_serials[fsp_con_port], buf, len);
229 	fsp_con_full = (written < len);
230 	unlock(&fsp_con_lock);
231 
232 	return written;
233 }
234 
235 static struct con_ops fsp_con_ops = {
236 	.write = fsp_con_write,
237 };
238 #endif /* DVS_CONSOLE */
239 
fsp_open_vserial(struct fsp_msg * msg)240 static void fsp_open_vserial(struct fsp_msg *msg)
241 {
242 	struct fsp_msg *resp;
243 
244 	u16 part_id = msg->data.words[0] & 0xffff;
245 	u16 sess_id = msg->data.words[1] & 0xffff;
246 	u8 hmc_sess = msg->data.bytes[0];
247 	u8 hmc_indx = msg->data.bytes[1];
248 	u8 authority = msg->data.bytes[4];
249 	u32 tce_in, tce_out;
250 	struct fsp_serial *fs;
251 
252 	prlog(PR_INFO, "FSPCON: Got VSerial Open\n");
253 	prlog(PR_DEBUG, "  part_id   = 0x%04x\n", part_id);
254 	prlog(PR_DEBUG, "  sess_id   = 0x%04x\n", sess_id);
255 	prlog(PR_DEBUG, "  hmc_sess  = 0x%02x\n", hmc_sess);
256 	prlog(PR_DEBUG, "  hmc_indx  = 0x%02x\n", hmc_indx);
257 	prlog(PR_DEBUG, "  authority = 0x%02x\n", authority);
258 
259 	if (sess_id >= MAX_SERIAL || !fsp_serials[sess_id].available) {
260 		prlog(PR_WARNING, "FSPCON: 0x%04x  NOT AVAILABLE!\n", sess_id);
261 		resp = fsp_mkmsg(FSP_RSP_OPEN_VSERIAL | 0x2f, 0);
262 		if (!resp) {
263 			prerror("FSPCON: Response allocation failed\n");
264 			return;
265 		}
266 		if (fsp_queue_msg(resp, fsp_freemsg)) {
267 			fsp_freemsg(resp);
268 			prerror("FSPCON: Failed to queue response msg\n");
269 		}
270 		return;
271 	}
272 
273 	fs = &fsp_serials[sess_id];
274 
275 	/* Hack ! On blades, the console opened via the mm has partition 1
276 	 * while the debug DVS generally has partition 0 (though you can
277 	 * use what you want really).
278 	 * We don't want a DVS open/close to crap on the blademm console
279 	 * thus if it's a raw console, gets an open with partID 1, we
280 	 * set a flag that ignores the close of partid 0
281 	 */
282 	if (fs->rsrc_id == 0xffff) {
283 		if (part_id == 0)
284 			fs->has_part0 = true;
285 		if (part_id == 1)
286 			fs->has_part1 = true;
287 	}
288 
289 	tce_in = PSI_DMA_SER0_BASE + PSI_DMA_SER0_SIZE * sess_id;
290 	tce_out = tce_in + SER_BUFFER_SIZE/2;
291 
292 	lock(&fsp_con_lock);
293 	if (fs->open) {
294 		prlog(PR_DEBUG, "  already open, skipping init !\n");
295 		unlock(&fsp_con_lock);
296 		goto already_open;
297 	}
298 
299 	fs->poke_msg = fsp_mkmsg(FSP_CMD_VSERIAL_OUT, 2,
300 				 msg->data.words[0],
301 				 msg->data.words[1] & 0xffff);
302 	if (fs->poke_msg == NULL) {
303 		prerror("FSPCON: Failed to allocate poke_msg\n");
304 		unlock(&fsp_con_lock);
305 		return;
306 	}
307 
308 	fs->open = true;
309 	fs->poke_msg->user_data = fs;
310 
311 	fs->in_buf->partition_id = fs->out_buf->partition_id = part_id;
312 	fs->in_buf->session_id	 = fs->out_buf->session_id   = sess_id;
313 	fs->in_buf->hmc_id       = fs->out_buf->hmc_id       = hmc_indx;
314 	fs->in_buf->data_offset  = fs->out_buf->data_offset  =
315 		sizeof(struct fsp_serbuf_hdr);
316 	fs->in_buf->last_valid   = fs->out_buf->last_valid   =
317 		SER_BUF_DATA_SIZE - 1;
318 	fs->in_buf->ovf_count    = fs->out_buf->ovf_count    = 0;
319 	fs->in_buf->next_in      = fs->out_buf->next_in      = 0;
320 	fs->in_buf->flags        = fs->out_buf->flags        = 0;
321 	fs->in_buf->reserved     = fs->out_buf->reserved     = 0;
322 	fs->in_buf->next_out     = fs->out_buf->next_out     = 0;
323 	fs->out_buf_prev_len     = 0;
324 	fs->out_buf_timeout      = 0;
325 	unlock(&fsp_con_lock);
326 
327  already_open:
328 	resp = fsp_mkmsg(FSP_RSP_OPEN_VSERIAL, 6, msg->data.words[0],
329 			msg->data.words[1] & 0xffff, 0, tce_in, 0, tce_out);
330 	if (!resp) {
331 		prerror("FSPCON: Failed to allocate open msg response\n");
332 		return;
333 	}
334 	if (fsp_queue_msg(resp, fsp_freemsg)) {
335 		fsp_freemsg(resp);
336 		prerror("FSPCON: Failed to queue open msg response\n");
337 		return;
338 	}
339 
340 #ifdef DVS_CONSOLE
341 	prlog(PR_DEBUG, "  log_port  = %d\n", fs->log_port);
342 	if (fs->log_port) {
343 		fsp_con_port = sess_id;
344 		sync();
345 		/*
346 		 * We mark the FSP lock as being in the console
347 		 * path. We do that only once, we never unmark it
348 		 * (there is really no much point)
349 		 */
350 		fsp_used_by_console();
351 		fsp_con_lock.in_con_path = true;
352 		/* See comment in fsp_used_by_console */
353 		lock(&fsp_con_lock);
354 		unlock(&fsp_con_lock);
355 		set_console(&fsp_con_ops);
356 	}
357 #endif
358 }
359 
fsp_close_vserial(struct fsp_msg * msg)360 static void fsp_close_vserial(struct fsp_msg *msg)
361 {
362 	u16 part_id = msg->data.words[0] & 0xffff;
363 	u16 sess_id = msg->data.words[1] & 0xffff;
364 	u8 hmc_sess = msg->data.bytes[0];
365 	u8 hmc_indx = msg->data.bytes[1];
366 	u8 authority = msg->data.bytes[4];
367 	struct fsp_serial *fs;
368 	struct fsp_msg *resp;
369 
370 	prlog(PR_INFO, "FSPCON: Got VSerial Close\n");
371 	prlog(PR_DEBUG, "  part_id   = 0x%04x\n", part_id);
372 	prlog(PR_DEBUG, "  sess_id   = 0x%04x\n", sess_id);
373 	prlog(PR_DEBUG, "  hmc_sess  = 0x%02x\n", hmc_sess);
374 	prlog(PR_DEBUG, "  hmc_indx  = 0x%02x\n", hmc_indx);
375 	prlog(PR_DEBUG, "  authority = 0x%02x\n", authority);
376 
377 	if (sess_id >= MAX_SERIAL || !fsp_serials[sess_id].available) {
378 		prlog(PR_WARNING, "FSPCON: 0x%04x  NOT AVAILABLE!\n", sess_id);
379 		goto skip_close;
380 	}
381 
382 	fs = &fsp_serials[sess_id];
383 
384 	/* See "HACK" comment in open */
385 	if (fs->rsrc_id == 0xffff) {
386 		if (part_id == 0)
387 			fs->has_part0 = false;
388 		if (part_id == 1)
389 			fs->has_part1 = false;
390 		if (fs->has_part0 || fs->has_part1) {
391 			prlog(PR_DEBUG, "  skipping close !\n");
392 			goto skip_close;
393 		}
394 	}
395 
396 #ifdef DVS_CONSOLE
397 	if (fs->log_port) {
398 		fsp_con_port = -1;
399 		set_console(NULL);
400 	}
401 #endif
402 
403 	lock(&fsp_con_lock);
404 	if (fs->open) {
405 		fs->open = false;
406 		fs->out_poke = false;
407 		if (fs->poke_msg && fs->poke_msg->state == fsp_msg_unused) {
408 			fsp_freemsg(fs->poke_msg);
409 			fs->poke_msg = NULL;
410 		}
411 	}
412 	unlock(&fsp_con_lock);
413  skip_close:
414 	resp = fsp_mkmsg(FSP_RSP_CLOSE_VSERIAL, 2, msg->data.words[0],
415 			msg->data.words[1] & 0xffff);
416 	if (!resp) {
417 		prerror("FSPCON: Failed to allocate close msg response\n");
418 		return;
419 	}
420 	if (fsp_queue_msg(resp, fsp_freemsg)) {
421 		fsp_freemsg(resp);
422 		prerror("FSPCON: Failed to queue close msg response\n");
423 	}
424 }
425 
fsp_con_msg_hmc(u32 cmd_sub_mod,struct fsp_msg * msg)426 static bool fsp_con_msg_hmc(u32 cmd_sub_mod, struct fsp_msg *msg)
427 {
428 	struct fsp_msg *resp;
429 
430 	/* Associate response */
431 	if ((cmd_sub_mod >> 8) == 0xe08a) {
432 		prlog(PR_TRACE, "FSPCON: Got associate response, status"
433 		      " 0x%02x\n", cmd_sub_mod & 0xff);
434 		return true;
435 	}
436 	if ((cmd_sub_mod >> 8) == 0xe08b) {
437 		prlog(PR_TRACE, "Got unassociate response, status 0x%02x\n",
438 		      cmd_sub_mod & 0xff);
439 		return true;
440 	}
441 	switch(cmd_sub_mod) {
442 	case FSP_CMD_OPEN_VSERIAL:
443 		fsp_open_vserial(msg);
444 		return true;
445 	case FSP_CMD_CLOSE_VSERIAL:
446 		fsp_close_vserial(msg);
447 		return true;
448 	case FSP_CMD_HMC_INTF_QUERY:
449 		prlog(PR_DEBUG, "FSPCON: Got HMC interface query\n");
450 		got_intf_query = true;
451 		resp = fsp_mkmsg(FSP_RSP_HMC_INTF_QUERY, 1,
452 				msg->data.words[0] & 0x00ffffff);
453 		if (!resp) {
454 			prerror("FSPCON: Failed to allocate hmc intf response\n");
455 			return true;
456 		}
457 		if (fsp_queue_msg(resp, fsp_freemsg)) {
458 			fsp_freemsg(resp);
459 			prerror("FSPCON: Failed to queue hmc intf response\n");
460 		}
461 		return true;
462 	}
463 	return false;
464 }
465 
fsp_con_msg_vt(u32 cmd_sub_mod,struct fsp_msg * msg)466 static bool fsp_con_msg_vt(u32 cmd_sub_mod, struct fsp_msg *msg)
467 {
468 	u16 sess_id = msg->data.words[1] & 0xffff;
469 
470 	if (cmd_sub_mod == FSP_CMD_VSERIAL_IN && sess_id < MAX_SERIAL) {
471 		struct fsp_serial *fs = &fsp_serials[sess_id];
472 
473 		if (!fs->open)
474 			return true;
475 
476 		/* FSP is signaling some incoming data. We take the console
477 		 * lock to avoid racing with a simultaneous read, though we
478 		 * might want to consider to simplify all that locking into
479 		 * one single lock that covers the console and the pending
480 		 * events.
481 		 */
482 		lock(&fsp_con_lock);
483 		opal_update_pending_evt(OPAL_EVENT_CONSOLE_INPUT,
484 					OPAL_EVENT_CONSOLE_INPUT);
485 		opal_update_pending_evt(fs->irq, fs->irq);
486 		unlock(&fsp_con_lock);
487 	}
488 	return true;
489 }
490 
fsp_con_msg_rr(u32 cmd_sub_mod,struct fsp_msg * msg)491 static bool fsp_con_msg_rr(u32 cmd_sub_mod, struct fsp_msg *msg)
492 {
493 	assert(msg == NULL);
494 
495 	switch (cmd_sub_mod) {
496 	case FSP_RESET_START:
497 		fsp_close_consoles();
498 		return true;
499 	case FSP_RELOAD_COMPLETE:
500 		fsp_console_reinit();
501 		return true;
502 	}
503 	return false;
504 }
505 
506 static struct fsp_client fsp_con_client_hmc = {
507 	.message = fsp_con_msg_hmc,
508 };
509 
510 static struct fsp_client fsp_con_client_vt = {
511 	.message = fsp_con_msg_vt,
512 };
513 
514 static struct fsp_client fsp_con_client_rr = {
515 	.message = fsp_con_msg_rr,
516 };
517 
fsp_serial_add(int index,u16 rsrc_id,const char * loc_code,bool log_port)518 static void fsp_serial_add(int index, u16 rsrc_id, const char *loc_code,
519 			   bool log_port)
520 {
521 	struct fsp_serial *ser;
522 	struct fsp_msg *msg;
523 
524 	lock(&fsp_con_lock);
525 	ser = &fsp_serials[index];
526 
527 	if (ser->available) {
528 		unlock(&fsp_con_lock);
529 		return;
530 	}
531 
532 	ser->rsrc_id = rsrc_id;
533 	memset(ser->loc_code, 0x00, LOC_CODE_SIZE);
534 	strncpy(ser->loc_code, loc_code, LOC_CODE_SIZE - 1);
535 	ser->available = true;
536 	ser->log_port = log_port;
537 	unlock(&fsp_con_lock);
538 
539 	/* DVS doesn't have that */
540 	if (rsrc_id != 0xffff) {
541 		msg = fsp_mkmsg(FSP_CMD_ASSOC_SERIAL, 2,
542 				(rsrc_id << 16) | 1, index);
543 		if (!msg) {
544 			prerror("FSPCON: Assoc serial alloc failed\n");
545 			return;
546 		}
547 		if (fsp_queue_msg(msg, fsp_freemsg)) {
548 			fsp_freemsg(msg);
549 			prerror("FSPCON: Assoc serial queue failed\n");
550 			return;
551 		}
552 	}
553 }
554 
fsp_console_preinit(void)555 void fsp_console_preinit(void)
556 {
557 	int i;
558 	void *base;
559 
560 	if (!fsp_present())
561 		return;
562 
563 	ser_buffer = memalign(TCE_PSIZE, SER_BUFFER_SIZE * MAX_SERIAL);
564 
565 	/* Initialize out data structure pointers & TCE maps */
566 	base = ser_buffer;
567 	for (i = 0; i < MAX_SERIAL; i++) {
568 		struct fsp_serial *ser = &fsp_serials[i];
569 
570 		ser->in_buf = base;
571 		ser->out_buf = base + SER_BUFFER_SIZE/2;
572 		base += SER_BUFFER_SIZE;
573 	}
574 	fsp_tce_map(PSI_DMA_SER0_BASE, ser_buffer,
575 		    4 * PSI_DMA_SER0_SIZE);
576 
577 	/* Register for class E0 and E1 */
578 	fsp_register_client(&fsp_con_client_hmc, FSP_MCLASS_HMC_INTFMSG);
579 	fsp_register_client(&fsp_con_client_vt, FSP_MCLASS_HMC_VT);
580 	fsp_register_client(&fsp_con_client_rr, FSP_MCLASS_RR_EVENT);
581 
582 	/* Add DVS ports. We currently have session 0 and 3, 0 is for
583 	 * OS use. 3 is our debug port. We need to add those before
584 	 * we complete the OPL or we'll potentially miss the
585 	 * console setup on Firebird blades.
586 	 */
587 	fsp_serial_add(0, 0xffff, "DVS_OS", false);
588 	op_display(OP_LOG, OP_MOD_FSPCON, 0x0001);
589 	fsp_serial_add(3, 0xffff, "DVS_FW", true);
590 	op_display(OP_LOG, OP_MOD_FSPCON, 0x0002);
591 
592 }
593 
fsp_console_write(int64_t term_number,int64_t * length,const uint8_t * buffer)594 static int64_t fsp_console_write(int64_t term_number, int64_t *length,
595 				 const uint8_t *buffer)
596 {
597 	struct fsp_serial *fs;
598 	size_t written, requested;
599 
600 	if (term_number < 0 || term_number >= MAX_SERIAL)
601 		return OPAL_PARAMETER;
602 	fs = &fsp_serials[term_number];
603 	if (!fs->available || fs->log_port)
604 		return OPAL_PARAMETER;
605 	lock(&fsp_con_lock);
606 	if (!fs->open) {
607 		unlock(&fsp_con_lock);
608 		return OPAL_CLOSED;
609 	}
610 	/* Clamp to a reasonable size */
611 	requested = *length;
612 	if (requested > 0x1000)
613 		requested = 0x1000;
614 	written = fsp_write_vserial(fs, buffer, requested);
615 
616 	if (written) {
617 		/* If we wrote anything, reset timeout */
618 		fs->out_buf_prev_len = 0;
619 		fs->out_buf_timeout = 0;
620 	}
621 
622 #ifdef OPAL_DEBUG_CONSOLE_IO
623 	prlog(PR_TRACE, "OPAL: console write req=%ld written=%ld"
624 	      " ni=%d no=%d\n",
625 	      requested, written, fs->out_buf->next_in, fs->out_buf->next_out);
626 	prlog(PR_TRACE, "      %02x %02x %02x %02x "
627 	      "%02x \'%c\' %02x \'%c\' %02x \'%c\'.%02x \'%c\'..\n",
628 	      buffer[0], buffer[1], buffer[2], buffer[3],
629 	      buffer[4], buffer[4], buffer[5], buffer[5],
630 	      buffer[6], buffer[6], buffer[7], buffer[7]);
631 #endif /* OPAL_DEBUG_CONSOLE_IO */
632 
633 	*length = written;
634 	unlock(&fsp_con_lock);
635 
636 	if (written)
637 		return OPAL_SUCCESS;
638 
639 	return OPAL_HARDWARE;
640 }
641 
fsp_console_write_buffer_space(int64_t term_number,int64_t * length)642 static int64_t fsp_console_write_buffer_space(int64_t term_number,
643 					      int64_t *length)
644 {
645 	static bool elog_generated = false;
646 	struct fsp_serial *fs;
647 	struct fsp_serbuf_hdr *sb;
648 
649 	if (term_number < 0 || term_number >= MAX_SERIAL)
650 		return OPAL_PARAMETER;
651 	fs = &fsp_serials[term_number];
652 	if (!fs->available || fs->log_port)
653 		return OPAL_PARAMETER;
654 	lock(&fsp_con_lock);
655 	if (!fs->open) {
656 		unlock(&fsp_con_lock);
657 		return OPAL_CLOSED;
658 	}
659 	sb = fs->out_buf;
660 	*length = (sb->next_out + SER_BUF_DATA_SIZE - sb->next_in - 1)
661 		% SER_BUF_DATA_SIZE;
662 	unlock(&fsp_con_lock);
663 
664 	/* Console buffer has enough space to write incoming data */
665 	if (*length != fs->out_buf_prev_len) {
666 		fs->out_buf_prev_len = *length;
667 		fs->out_buf_timeout = 0;
668 
669 		return OPAL_SUCCESS;
670 	}
671 
672 	/*
673 	 * Buffer is full, start internal timer. We will continue returning
674 	 * SUCCESS until timeout happens, hoping FSP will consume data within
675 	 * timeout period.
676 	 */
677 	if (fs->out_buf_timeout == 0) {
678 		fs->out_buf_timeout = mftb() +
679 			secs_to_tb(SER_BUFFER_OUT_TIMEOUT);
680 	}
681 
682 	if (tb_compare(mftb(), fs->out_buf_timeout) != TB_AAFTERB)
683 		return OPAL_SUCCESS;
684 
685 	/*
686 	 * FSP is still active but not reading console data. Hence
687 	 * our console buffer became full. Most likely IPMI daemon
688 	 * on FSP is buggy. Lets log error and return OPAL_RESOURCE
689 	 * to payload (Linux).
690 	 */
691 	if (!elog_generated) {
692 		elog_generated = true;
693 		log_simple_error(&e_info(OPAL_RC_CONSOLE_HANG), "FSPCON: Console "
694 				 "buffer is full, dropping console data\n");
695 	}
696 
697 	/* Timeout happened. Lets drop incoming data */
698 	return OPAL_RESOURCE;
699 }
700 
fsp_console_read(int64_t term_number,int64_t * length,uint8_t * buffer)701 static int64_t fsp_console_read(int64_t term_number, int64_t *length,
702 				uint8_t *buffer)
703 {
704 	struct fsp_serial *fs;
705 	struct fsp_serbuf_hdr *sb;
706 	bool pending = false;
707 	uint32_t old_nin, n, i, chunk, req = *length;
708 	int rc = OPAL_SUCCESS;
709 
710 	if (term_number < 0 || term_number >= MAX_SERIAL)
711 		return OPAL_PARAMETER;
712 	fs = &fsp_serials[term_number];
713 	if (!fs->available || fs->log_port)
714 		return OPAL_PARAMETER;
715 	lock(&fsp_con_lock);
716 	if (!fs->open) {
717 		rc = OPAL_CLOSED;
718 		goto clr_flag;
719 	}
720 	if (fs->waiting)
721 		fs->waiting = 0;
722 	sb = fs->in_buf;
723 	old_nin = sb->next_in;
724 	lwsync();
725 	n = (old_nin + SER_BUF_DATA_SIZE - sb->next_out)
726 		% SER_BUF_DATA_SIZE;
727 	if (n > req) {
728 		pending = true;
729 		n = req;
730 	}
731 	*length = n;
732 
733 	chunk = SER_BUF_DATA_SIZE - sb->next_out;
734 	if (chunk > n)
735 		chunk = n;
736 	memcpy(buffer, &sb->data[sb->next_out], chunk);
737 	if (chunk < n)
738 		memcpy(buffer + chunk, &sb->data[0], n - chunk);
739 	sb->next_out = (sb->next_out + n) % SER_BUF_DATA_SIZE;
740 
741 #ifdef OPAL_DEBUG_CONSOLE_IO
742 	prlog(PR_TRACE, "OPAL: console read req=%d read=%d ni=%d no=%d\n",
743 	      req, n, sb->next_in, sb->next_out);
744 	prlog(PR_TRACE, "      %02x %02x %02x %02x %02x %02x %02x %02x ...\n",
745 	       buffer[0], buffer[1], buffer[2], buffer[3],
746 	       buffer[4], buffer[5], buffer[6], buffer[7]);
747 #endif /* OPAL_DEBUG_CONSOLE_IO */
748 
749 clr_flag:
750 	/* Might clear the input pending flag */
751 	for (i = 0; i < MAX_SERIAL && !pending; i++) {
752 		struct fsp_serial *fs = &fsp_serials[i];
753 		struct fsp_serbuf_hdr *sb = fs->in_buf;
754 
755 		if (fs->log_port || !fs->open)
756 			continue;
757 		if (sb->next_out != sb->next_in) {
758 			/*
759 			 * HACK: Some kernels (4.1+) may fail to properly
760 			 * register hvc1 and will never read it. This can lead
761 			 * to RCU stalls, so if we notice this console is not
762 			 * being read, do not set OPAL_EVENT_CONSOLE_INPUT even
763 			 * if it has data
764 			 */
765 			if (fs->waiting < 5) {
766 				pending = true;
767 				fs->waiting++;
768 			}
769 		}
770 	}
771 	if (!pending) {
772 		opal_update_pending_evt(fs->irq, 0);
773 		opal_update_pending_evt(OPAL_EVENT_CONSOLE_INPUT, 0);
774 	}
775 
776 	unlock(&fsp_con_lock);
777 
778 	return rc;
779 }
780 
fsp_console_poll(void * data __unused)781 void fsp_console_poll(void *data __unused)
782 {
783 #ifdef OPAL_DEBUG_CONSOLE_POLL
784        	static int debug;
785 #endif
786 
787 	/*
788 	 * We don't get messages for out buffer being consumed, so we
789 	 * need to poll. We also defer sending of poke messages from
790 	 * the sapphire console to avoid a locking nightmare with
791 	 * beging called from printf() deep into an existing lock nest
792 	 * stack.
793 	 */
794 	if (fsp_con_full ||
795 	    (opal_pending_events & OPAL_EVENT_CONSOLE_OUTPUT)) {
796 		unsigned int i;
797 		bool pending = false;
798 
799 		/* We take the console lock. This is somewhat inefficient
800 		 * but it guarantees we aren't racing with a write, and
801 		 * thus clearing an event improperly
802 		 */
803 		lock(&fsp_con_lock);
804 		for (i = 0; i < MAX_SERIAL && !pending; i++) {
805 			struct fsp_serial *fs = &fsp_serials[i];
806 			struct fsp_serbuf_hdr *sb = fs->out_buf;
807 
808 			if (!fs->open)
809 				continue;
810 			if (sb->next_out == sb->next_in) {
811 				continue;
812 			}
813 			if (fs->log_port) {
814 				flush_console();
815 			} else {
816 #ifdef OPAL_DEBUG_CONSOLE_POLL
817 				if (debug < 5) {
818 					prlog(PR_DEBUG,"OPAL: %d still pending"
819 					      " ni=%d no=%d\n",
820 					      i, sb->next_in, sb->next_out);
821 					debug++;
822 				}
823 #endif /* OPAL_DEBUG_CONSOLE_POLL */
824 				pending = true;
825 			}
826 		}
827 		if (!pending) {
828 			opal_update_pending_evt(OPAL_EVENT_CONSOLE_OUTPUT, 0);
829 #ifdef OPAL_DEBUG_CONSOLE_POLL
830 			debug = 0;
831 #endif
832 		}
833 		unlock(&fsp_con_lock);
834 	}
835 }
836 
fsp_console_init(void)837 void fsp_console_init(void)
838 {
839 	struct dt_node *serials, *ser;
840 	int i;
841 
842 	if (!fsp_present())
843 		return;
844 
845 	/* Wait until we got the intf query before moving on */
846 	while (!got_intf_query)
847 		opal_run_pollers();
848 
849 	op_display(OP_LOG, OP_MOD_FSPCON, 0x0000);
850 
851 	/* Register poller */
852 	opal_add_poller(fsp_console_poll, NULL);
853 
854 	/* Register OPAL console backend */
855 	set_opal_console(&fsp_opal_con);
856 
857 	/* Parse serial port data */
858 	serials = dt_find_by_path(dt_root, "ipl-params/fsp-serial");
859 	if (!serials) {
860 		prerror("FSPCON: No FSP serial ports in device-tree\n");
861 		return;
862 	}
863 
864 	i = 1;
865 	dt_for_each_child(serials, ser) {
866 		u32 rsrc_id = dt_prop_get_u32(ser, "reg");
867 		const void *lc = dt_prop_get(ser, "ibm,loc-code");
868 
869 		prlog(PR_NOTICE, "FSPCON: Serial %d rsrc: %04x loc: %s\n",
870 		      i, rsrc_id, (const char *)lc);
871 		fsp_serial_add(i++, rsrc_id, lc, false);
872 		op_display(OP_LOG, OP_MOD_FSPCON, 0x0010 + i);
873 	}
874 
875 	op_display(OP_LOG, OP_MOD_FSPCON, 0x0005);
876 }
877 
fsp_console_flush(int64_t terminal __unused)878 static int64_t fsp_console_flush(int64_t terminal __unused)
879 {
880 	/* FIXME: There's probably something we can do here... */
881 	return OPAL_PARAMETER;
882 }
883 
884 struct opal_con_ops fsp_opal_con = {
885 	.name = "FSP OPAL console",
886 	.init = NULL, /* all the required setup is done in fsp_console_init() */
887 	.read = fsp_console_read,
888 	.write = fsp_console_write,
889 	.space = fsp_console_write_buffer_space,
890 	.flush = fsp_console_flush,
891 };
892 
flush_all_input(void)893 static void flush_all_input(void)
894 {
895 	unsigned int i;
896 
897 	lock(&fsp_con_lock);
898  	for (i = 0; i < MAX_SERIAL; i++) {
899 		struct fsp_serial *fs = &fsp_serials[i];
900 		struct fsp_serbuf_hdr *sb = fs->in_buf;
901 
902 		if (fs->log_port)
903 			continue;
904 
905 		sb->next_out = sb->next_in;
906 	}
907 	unlock(&fsp_con_lock);
908 }
909 
send_all_hvsi_close(void)910 static bool send_all_hvsi_close(void)
911 {
912 	unsigned int i;
913 	bool has_hvsi = false;
914 	static const uint8_t close_packet[] = { 0xfe, 6, 0, 1, 0, 3 };
915 
916  	for (i = 0; i < MAX_SERIAL; i++) {
917 		struct fsp_serial *fs = &fsp_serials[i];
918 		struct fsp_serbuf_hdr *sb = fs->out_buf;
919 		unsigned int space, timeout = 10;
920 
921 		if (fs->log_port)
922 			continue;
923 		if (fs->rsrc_id == 0xffff)
924 			continue;
925 		has_hvsi = true;
926 
927 		/* Do we have room ? Wait a bit if not */
928 		while(timeout--) {
929 			space = (sb->next_out + SER_BUF_DATA_SIZE -
930 				 sb->next_in - 1) % SER_BUF_DATA_SIZE;
931 			if (space >= 6)
932 				break;
933 			time_wait_ms(500);
934 		}
935 		lock(&fsp_con_lock);
936 		fsp_write_vserial(fs, close_packet, 6);
937 		unlock(&fsp_con_lock);
938 	}
939 
940 	return has_hvsi;
941 }
942 
reopen_all_hvsi(void)943 static void reopen_all_hvsi(void)
944 {
945 	unsigned int i;
946 
947  	for (i = 0; i < MAX_SERIAL; i++) {
948 		struct fsp_serial *fs = &fsp_serials[i];
949 
950 		if (!fs->available)
951 			continue;
952 
953 		if (fs->rsrc_id == 0xffff)
954 			continue;
955 		prlog(PR_NOTICE, "FSP: Deassociating HVSI console %d\n", i);
956 		fsp_sync_msg(fsp_mkmsg(FSP_CMD_UNASSOC_SERIAL, 1,
957 				       (i << 16) | 1), true);
958 	}
959  	for (i = 0; i < MAX_SERIAL; i++) {
960 		struct fsp_serial *fs = &fsp_serials[i];
961 
962 		if (!fs->available)
963 			continue;
964 
965 		if (fs->rsrc_id == 0xffff)
966 			continue;
967 		prlog(PR_NOTICE, "FSP: Reassociating HVSI console %d\n", i);
968 		fsp_sync_msg(fsp_mkmsg(FSP_CMD_ASSOC_SERIAL, 2,
969 				       (fs->rsrc_id << 16) | 1, i), true);
970 	}
971 }
972 
fsp_console_reset(void)973 void fsp_console_reset(void)
974 {
975 	if (!fsp_present())
976 		return;
977 
978 	prlog(PR_NOTICE, "FSP: Console reset !\n");
979 
980 	/* This is called on a fast-reset. To work around issues with HVSI
981 	 * initial negotiation, before we reboot the kernel, we flush all
982 	 * input and send an HVSI close packet.
983 	 */
984 	flush_all_input();
985 
986 	/* Returns false if there is no HVSI console */
987 	if (!send_all_hvsi_close())
988 		return;
989 
990 	time_wait_ms(500);
991 
992 	reopen_all_hvsi();
993 
994 }
995 
fsp_console_add_nodes(void)996 void fsp_console_add_nodes(void)
997 {
998 	struct dt_node *opal_event;
999 	unsigned int i;
1000 
1001 	opal_event = dt_find_by_name(opal_node, "event");
1002 
1003 	for (i = 0; i < MAX_SERIAL; i++) {
1004 		struct fsp_serial *fs = &fsp_serials[i];
1005 		struct dt_node *fs_node;
1006 		const char *type;
1007 
1008 		if (fs->log_port || !fs->available)
1009 			continue;
1010 
1011 		if (fs->rsrc_id == 0xffff)
1012 			type = "raw";
1013 		else
1014 			type = "hvsi";
1015 
1016 		fs_node = add_opal_console_node(i, type, SER_BUF_DATA_SIZE);
1017 
1018 		fs->irq = opal_dynamic_event_alloc();
1019 		dt_add_property_cells(fs_node, "interrupts", ilog2(fs->irq));
1020 
1021 		if (opal_event)
1022 			dt_add_property_cells(fs_node, "interrupt-parent",
1023 					      opal_event->phandle);
1024 	}
1025 }
1026 
fsp_console_select_stdout(void)1027 void fsp_console_select_stdout(void)
1028 {
1029 	bool use_serial = false;
1030 
1031 	if (!fsp_present())
1032 		return;
1033 
1034 	/* On P8, we have a sysparam ! yay ! */
1035 	if (proc_gen >= proc_gen_p8) {
1036 		int rc;
1037 		u8 param;
1038 
1039 		rc = fsp_get_sys_param(SYS_PARAM_CONSOLE_SELECT,
1040 				       &param, 1, NULL, NULL);
1041 		if (rc != 1)
1042 			prerror("FSPCON: Failed to get console"
1043 				" sysparam rc %d\n", rc);
1044 		else {
1045 			switch(param) {
1046 			case 0:
1047 				use_serial = false;
1048 				break;
1049 			case 1:
1050 				use_serial = true;
1051 				break;
1052 			default:
1053 				prerror("FSPCON: Unknown console"
1054 					" sysparam %d\n", param);
1055 			}
1056 		}
1057 	} else {
1058 		struct dt_node *iplp;
1059 		u32 ipl_mode = 0;
1060 
1061 		/*
1062 		 * We hijack the "os-ipl-mode" setting in iplparams to select
1063 		 * out output console. This is the "i5/OS partition mode boot"
1064 		 * setting in ASMI converted to an integer: 0=A, 1=B.
1065 		 */
1066 		iplp = dt_find_by_path(dt_root, "ipl-params/ipl-params");
1067 		if (iplp) {
1068 			ipl_mode = dt_prop_get_u32_def(iplp, "os-ipl-mode", 0);
1069 			use_serial = ipl_mode > 0;
1070 
1071 			/*
1072 			 * Now, if ipl_mode is > 0, we use serial port A else
1073 			 * we use IPMI/SOL/DVS
1074 			 */
1075 		}
1076 	}
1077 	dt_check_del_prop(dt_chosen, "linux,stdout-path");
1078 
1079 	if (fsp_serials[1].open && use_serial) {
1080 		dt_add_property_string(dt_chosen, "linux,stdout-path",
1081 				       "/ibm,opal/consoles/serial@1");
1082 		prlog(PR_NOTICE, "FSPCON: default console set to serial A\n");
1083 	} else {
1084 		dt_add_property_string(dt_chosen, "linux,stdout-path",
1085 				       "/ibm,opal/consoles/serial@0");
1086 		prlog(PR_NOTICE, "FSPCON: default console set to SOL/DVS\n");
1087 	}
1088 }
1089 
1090