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 ¶m, 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