1
/* Copyright 2013-2014 IBM Corp.
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
7
* http://www.apache.org/licenses/LICENSE-2.0
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
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
18
* Service Processor serial console handling code
21
#include <processor.h>
28
#include <fsp-sysparam.h>
30
struct fsp_serbuf_hdr {
43
#define SER_BUF_DATA_SIZE (0x10000 - sizeof(struct fsp_serbuf_hdr))
52
char loc_code[LOC_CODE_SIZE];
54
struct fsp_serbuf_hdr *in_buf;
55
struct fsp_serbuf_hdr *out_buf;
56
struct fsp_msg *poke_msg;
60
#define SER_BUFFER_SIZE 0x00040000UL
63
static struct fsp_serial fsp_serials[MAX_SERIAL];
64
static bool got_intf_query;
65
static struct lock fsp_con_lock = LOCK_UNLOCKED;
66
static void* ser_buffer = NULL;
68
static void fsp_console_reinit(void)
74
/* Initialize out data structure pointers & TCE maps */
76
for (i = 0; i < MAX_SERIAL; i++) {
77
struct fsp_serial *ser = &fsp_serials[i];
80
ser->out_buf = base + SER_BUFFER_SIZE/2;
81
base += SER_BUFFER_SIZE;
83
fsp_tce_map(PSI_DMA_SER0_BASE, ser_buffer,
84
4 * PSI_DMA_SER0_SIZE);
86
for (i = 0; i < MAX_SERIAL; i++) {
87
struct fsp_serial *fs = &fsp_serials[i];
89
if (fs->rsrc_id == 0xffff)
91
prlog(PR_DEBUG, "FSP: Reassociating HVSI console %d\n", i);
92
msg = fsp_mkmsg(FSP_CMD_ASSOC_SERIAL, 2,
93
(fs->rsrc_id << 16) | 1, i);
95
prerror("FSPCON: Failed to allocate associate msg\n");
98
if (fsp_queue_msg(msg, fsp_freemsg)) {
100
prerror("FSPCON: Failed to queue associate msg\n");
106
static void fsp_close_consoles(void)
110
for (i = 0; i < MAX_SERIAL; i++) {
111
struct fsp_serial *fs = &fsp_serials[i];
116
if (fs->rsrc_id == 0xffff) /* Get clarity from benh */
122
fs->out_poke = false;
123
if (fs->poke_msg->state != fsp_msg_unused)
124
fsp_cancelmsg(fs->poke_msg);
125
fsp_freemsg(fs->poke_msg);
128
unlock(&fsp_con_lock);
130
prlog(PR_DEBUG, "FSPCON: Closed consoles due to FSP reset/reload\n");
133
static void fsp_pokemsg_reclaim(struct fsp_msg *msg)
135
struct fsp_serial *fs = msg->user_data;
138
* The poke_msg might have been "detached" from the console
139
* in vserial_close, so we need to check whether it's current
140
* before touching the state, otherwise, just free it
143
if (fs->open && fs->poke_msg == msg) {
145
if (fsp_queue_msg(fs->poke_msg, fsp_pokemsg_reclaim)) {
146
prerror("FSPCON: failed to queue poke msg\n");
149
fs->out_poke = false;
152
fs->poke_msg->state = fsp_msg_unused;
155
unlock(&fsp_con_lock);
158
/* Called with the fsp_con_lock held */
159
static size_t fsp_write_vserial(struct fsp_serial *fs, const char *buf,
162
struct fsp_serbuf_hdr *sb = fs->out_buf;
163
u16 old_nin = sb->next_in;
169
space = (sb->next_out + SER_BUF_DATA_SIZE - old_nin - 1)
176
chunk = SER_BUF_DATA_SIZE - old_nin;
179
memcpy(&sb->data[old_nin], buf, chunk);
181
memcpy(&sb->data[0], buf + chunk, len - chunk);
183
sb->next_in = (old_nin + len) % SER_BUF_DATA_SIZE;
186
if (sb->next_out == old_nin && fs->poke_msg) {
187
if (fs->poke_msg->state == fsp_msg_unused) {
188
if (fsp_queue_msg(fs->poke_msg, fsp_pokemsg_reclaim))
189
prerror("FSPCON: poke msg queuing failed\n");
193
#ifndef DISABLE_CON_PENDING_EVT
194
opal_update_pending_evt(OPAL_EVENT_CONSOLE_OUTPUT,
195
OPAL_EVENT_CONSOLE_OUTPUT);
201
static int fsp_con_port = -1;
202
static bool fsp_con_full;
205
* This is called by the code in console.c without the con_lock
206
* held. However it can be called as the result of any printf
207
* thus any other lock might be held including possibly the
210
static size_t fsp_con_write(const char *buf, size_t len)
214
if (fsp_con_port < 0)
218
written = fsp_write_vserial(&fsp_serials[fsp_con_port], buf, len);
219
fsp_con_full = (written < len);
220
unlock(&fsp_con_lock);
225
static struct con_ops fsp_con_ops = {
226
.write = fsp_con_write,
228
#endif /* DVS_CONSOLE */
230
static void fsp_open_vserial(struct fsp_msg *msg)
232
struct fsp_msg *resp;
234
u16 part_id = msg->data.words[0] & 0xffff;
235
u16 sess_id = msg->data.words[1] & 0xffff;
236
u8 hmc_sess = msg->data.bytes[0];
237
u8 hmc_indx = msg->data.bytes[1];
238
u8 authority = msg->data.bytes[4];
240
struct fsp_serial *fs;
242
prlog(PR_INFO, "FSPCON: Got VSerial Open\n");
243
prlog(PR_DEBUG, " part_id = 0x%04x\n", part_id);
244
prlog(PR_DEBUG, " sess_id = 0x%04x\n", sess_id);
245
prlog(PR_DEBUG, " hmc_sess = 0x%02x\n", hmc_sess);
246
prlog(PR_DEBUG, " hmc_indx = 0x%02x\n", hmc_indx);
247
prlog(PR_DEBUG, " authority = 0x%02x\n", authority);
249
if (sess_id >= MAX_SERIAL || !fsp_serials[sess_id].available) {
250
prlog(PR_WARNING, "FSPCON: 0x%04x NOT AVAILABLE!\n", sess_id);
251
resp = fsp_mkmsg(FSP_RSP_OPEN_VSERIAL | 0x2f, 0);
253
prerror("FSPCON: Response allocation failed\n");
256
if (fsp_queue_msg(resp, fsp_freemsg)) {
258
prerror("FSPCON: Failed to queue response msg\n");
263
fs = &fsp_serials[sess_id];
265
/* Hack ! On blades, the console opened via the mm has partition 1
266
* while the debug DVS generally has partition 0 (though you can
267
* use what you want really).
268
* We don't want a DVS open/close to crap on the blademm console
269
* thus if it's a raw console, gets an open with partID 1, we
270
* set a flag that ignores the close of partid 0
272
if (fs->rsrc_id == 0xffff) {
274
fs->has_part0 = true;
276
fs->has_part1 = true;
279
tce_in = PSI_DMA_SER0_BASE + PSI_DMA_SER0_SIZE * sess_id;
280
tce_out = tce_in + SER_BUFFER_SIZE/2;
284
prlog(PR_DEBUG, " already open, skipping init !\n");
285
unlock(&fsp_con_lock);
291
fs->poke_msg = fsp_mkmsg(FSP_CMD_VSERIAL_OUT, 2,
293
msg->data.words[1] & 0xffff);
294
fs->poke_msg->user_data = fs;
296
fs->in_buf->partition_id = fs->out_buf->partition_id = part_id;
297
fs->in_buf->session_id = fs->out_buf->session_id = sess_id;
298
fs->in_buf->hmc_id = fs->out_buf->hmc_id = hmc_indx;
299
fs->in_buf->data_offset = fs->out_buf->data_offset =
300
sizeof(struct fsp_serbuf_hdr);
301
fs->in_buf->last_valid = fs->out_buf->last_valid =
302
SER_BUF_DATA_SIZE - 1;
303
fs->in_buf->ovf_count = fs->out_buf->ovf_count = 0;
304
fs->in_buf->next_in = fs->out_buf->next_in = 0;
305
fs->in_buf->flags = fs->out_buf->flags = 0;
306
fs->in_buf->reserved = fs->out_buf->reserved = 0;
307
fs->in_buf->next_out = fs->out_buf->next_out = 0;
308
unlock(&fsp_con_lock);
311
resp = fsp_mkmsg(FSP_RSP_OPEN_VSERIAL, 6, msg->data.words[0],
312
msg->data.words[1] & 0xffff, 0, tce_in, 0, tce_out);
314
prerror("FSPCON: Failed to allocate open msg response\n");
317
if (fsp_queue_msg(resp, fsp_freemsg)) {
319
prerror("FSPCON: Failed to queue open msg response\n");
324
prlog(PR_DEBUG, " log_port = %d\n", fs->log_port);
326
fsp_con_port = sess_id;
329
* We mark the FSP lock as being in the console
330
* path. We do that only once, we never unmark it
331
* (there is really no much point)
333
fsp_used_by_console();
334
fsp_con_lock.in_con_path = true;
335
/* See comment in fsp_used_by_console */
337
unlock(&fsp_con_lock);
338
set_console(&fsp_con_ops);
343
static void fsp_close_vserial(struct fsp_msg *msg)
345
u16 part_id = msg->data.words[0] & 0xffff;
346
u16 sess_id = msg->data.words[1] & 0xffff;
347
u8 hmc_sess = msg->data.bytes[0];
348
u8 hmc_indx = msg->data.bytes[1];
349
u8 authority = msg->data.bytes[4];
350
struct fsp_serial *fs;
351
struct fsp_msg *resp;
353
prlog(PR_INFO, "FSPCON: Got VSerial Close\n");
354
prlog(PR_DEBUG, " part_id = 0x%04x\n", part_id);
355
prlog(PR_DEBUG, " sess_id = 0x%04x\n", sess_id);
356
prlog(PR_DEBUG, " hmc_sess = 0x%02x\n", hmc_sess);
357
prlog(PR_DEBUG, " hmc_indx = 0x%02x\n", hmc_indx);
358
prlog(PR_DEBUG, " authority = 0x%02x\n", authority);
360
if (sess_id >= MAX_SERIAL || !fsp_serials[sess_id].available) {
361
prlog(PR_WARNING, "FSPCON: 0x%04x NOT AVAILABLE!\n", sess_id);
365
fs = &fsp_serials[sess_id];
367
/* See "HACK" comment in open */
368
if (fs->rsrc_id == 0xffff) {
370
fs->has_part0 = false;
372
fs->has_part1 = false;
373
if (fs->has_part0 || fs->has_part1) {
374
prlog(PR_DEBUG, " skipping close !\n");
389
fs->out_poke = false;
390
if (fs->poke_msg && fs->poke_msg->state == fsp_msg_unused) {
391
fsp_freemsg(fs->poke_msg);
395
unlock(&fsp_con_lock);
397
resp = fsp_mkmsg(FSP_RSP_CLOSE_VSERIAL, 2, msg->data.words[0],
398
msg->data.words[1] & 0xffff);
400
prerror("FSPCON: Failed to allocate close msg response\n");
403
if (fsp_queue_msg(resp, fsp_freemsg)) {
405
prerror("FSPCON: Failed to queue close msg response\n");
409
static bool fsp_con_msg_hmc(u32 cmd_sub_mod, struct fsp_msg *msg)
411
struct fsp_msg *resp;
413
/* Associate response */
414
if ((cmd_sub_mod >> 8) == 0xe08a) {
415
prlog(PR_TRACE, "FSPCON: Got associate response, status"
416
" 0x%02x\n", cmd_sub_mod & 0xff);
419
if ((cmd_sub_mod >> 8) == 0xe08b) {
420
prlog(PR_TRACE, "Got unassociate response, status 0x%02x\n",
424
switch(cmd_sub_mod) {
425
case FSP_CMD_OPEN_VSERIAL:
426
fsp_open_vserial(msg);
428
case FSP_CMD_CLOSE_VSERIAL:
429
fsp_close_vserial(msg);
431
case FSP_CMD_HMC_INTF_QUERY:
432
prlog(PR_DEBUG, "FSPCON: Got HMC interface query\n");
433
got_intf_query = true;
434
resp = fsp_mkmsg(FSP_RSP_HMC_INTF_QUERY, 1,
435
msg->data.words[0] & 0x00ffffff);
437
prerror("FSPCON: Failed to allocate hmc intf response\n");
440
if (fsp_queue_msg(resp, fsp_freemsg)) {
442
prerror("FSPCON: Failed to queue hmc intf response\n");
449
static bool fsp_con_msg_vt(u32 cmd_sub_mod, struct fsp_msg *msg)
451
u16 sess_id = msg->data.words[1] & 0xffff;
453
if (cmd_sub_mod == FSP_CMD_VSERIAL_IN && sess_id < MAX_SERIAL) {
454
struct fsp_serial *fs = &fsp_serials[sess_id];
459
/* FSP is signaling some incoming data. We take the console
460
* lock to avoid racing with a simultaneous read, though we
461
* might want to consider to simplify all that locking into
462
* one single lock that covers the console and the pending
466
opal_update_pending_evt(OPAL_EVENT_CONSOLE_INPUT,
467
OPAL_EVENT_CONSOLE_INPUT);
468
unlock(&fsp_con_lock);
473
static bool fsp_con_msg_rr(u32 cmd_sub_mod, struct fsp_msg *msg)
477
switch (cmd_sub_mod) {
478
case FSP_RESET_START:
479
fsp_close_consoles();
481
case FSP_RELOAD_COMPLETE:
482
fsp_console_reinit();
488
static struct fsp_client fsp_con_client_hmc = {
489
.message = fsp_con_msg_hmc,
492
static struct fsp_client fsp_con_client_vt = {
493
.message = fsp_con_msg_vt,
496
static struct fsp_client fsp_con_client_rr = {
497
.message = fsp_con_msg_rr,
500
static void fsp_serial_add(int index, u16 rsrc_id, const char *loc_code,
503
struct fsp_serial *ser;
507
ser = &fsp_serials[index];
509
if (ser->available) {
510
unlock(&fsp_con_lock);
514
ser->rsrc_id = rsrc_id;
515
memset(ser->loc_code, 0x00, LOC_CODE_SIZE);
516
strncpy(ser->loc_code, loc_code, LOC_CODE_SIZE - 1);
517
ser->available = true;
518
ser->log_port = log_port;
519
unlock(&fsp_con_lock);
521
/* DVS doesn't have that */
522
if (rsrc_id != 0xffff) {
523
msg = fsp_mkmsg(FSP_CMD_ASSOC_SERIAL, 2,
524
(rsrc_id << 16) | 1, index);
526
prerror("FSPCON: Assoc serial alloc failed\n");
529
if (fsp_queue_msg(msg, fsp_freemsg)) {
531
prerror("FSPCON: Assoc serial queue failed\n");
537
void fsp_console_preinit(void)
545
ser_buffer = memalign(TCE_PSIZE, SER_BUFFER_SIZE * MAX_SERIAL);
547
/* Initialize out data structure pointers & TCE maps */
549
for (i = 0; i < MAX_SERIAL; i++) {
550
struct fsp_serial *ser = &fsp_serials[i];
553
ser->out_buf = base + SER_BUFFER_SIZE/2;
554
base += SER_BUFFER_SIZE;
556
fsp_tce_map(PSI_DMA_SER0_BASE, ser_buffer,
557
4 * PSI_DMA_SER0_SIZE);
559
/* Register for class E0 and E1 */
560
fsp_register_client(&fsp_con_client_hmc, FSP_MCLASS_HMC_INTFMSG);
561
fsp_register_client(&fsp_con_client_vt, FSP_MCLASS_HMC_VT);
562
fsp_register_client(&fsp_con_client_rr, FSP_MCLASS_RR_EVENT);
564
/* Add DVS ports. We currently have session 0 and 3, 0 is for
565
* OS use. 3 is our debug port. We need to add those before
566
* we complete the OPL or we'll potentially miss the
567
* console setup on Firebird blades.
569
fsp_serial_add(0, 0xffff, "DVS_OS", false);
570
op_display(OP_LOG, OP_MOD_FSPCON, 0x0001);
571
fsp_serial_add(3, 0xffff, "DVS_FW", true);
572
op_display(OP_LOG, OP_MOD_FSPCON, 0x0002);
576
static int64_t fsp_console_write(int64_t term_number, int64_t *length,
577
const uint8_t *buffer)
579
struct fsp_serial *fs;
580
size_t written, requested;
582
if (term_number < 0 || term_number >= MAX_SERIAL)
583
return OPAL_PARAMETER;
584
fs = &fsp_serials[term_number];
585
if (!fs->available || fs->log_port)
586
return OPAL_PARAMETER;
589
unlock(&fsp_con_lock);
592
/* Clamp to a reasonable size */
594
if (requested > 0x1000)
596
written = fsp_write_vserial(fs, buffer, requested);
598
#ifdef OPAL_DEBUG_CONSOLE_IO
599
prlog(PR_TRACE, "OPAL: console write req=%ld written=%ld"
601
requested, written, fs->out_buf->next_in, fs->out_buf->next_out);
602
prlog(PR_TRACE, " %02x %02x %02x %02x "
603
"%02x \'%c\' %02x \'%c\' %02x \'%c\'.%02x \'%c\'..\n",
604
buffer[0], buffer[1], buffer[2], buffer[3],
605
buffer[4], buffer[4], buffer[5], buffer[5],
606
buffer[6], buffer[6], buffer[7], buffer[7]);
607
#endif /* OPAL_DEBUG_CONSOLE_IO */
610
unlock(&fsp_con_lock);
612
return written ? OPAL_SUCCESS : OPAL_BUSY_EVENT;
615
static int64_t fsp_console_write_buffer_space(int64_t term_number,
618
struct fsp_serial *fs;
619
struct fsp_serbuf_hdr *sb;
621
if (term_number < 0 || term_number >= MAX_SERIAL)
622
return OPAL_PARAMETER;
623
fs = &fsp_serials[term_number];
624
if (!fs->available || fs->log_port)
625
return OPAL_PARAMETER;
628
unlock(&fsp_con_lock);
632
*length = (sb->next_out + SER_BUF_DATA_SIZE - sb->next_in - 1)
634
unlock(&fsp_con_lock);
639
static int64_t fsp_console_read(int64_t term_number, int64_t *length,
640
uint8_t *buffer __unused)
642
struct fsp_serial *fs;
643
struct fsp_serbuf_hdr *sb;
644
bool pending = false;
645
uint32_t old_nin, n, i, chunk, req = *length;
647
if (term_number < 0 || term_number >= MAX_SERIAL)
648
return OPAL_PARAMETER;
649
fs = &fsp_serials[term_number];
650
if (!fs->available || fs->log_port)
651
return OPAL_PARAMETER;
654
unlock(&fsp_con_lock);
660
old_nin = sb->next_in;
662
n = (old_nin + SER_BUF_DATA_SIZE - sb->next_out)
670
chunk = SER_BUF_DATA_SIZE - sb->next_out;
673
memcpy(buffer, &sb->data[sb->next_out], chunk);
675
memcpy(buffer + chunk, &sb->data[0], n - chunk);
676
sb->next_out = (sb->next_out + n) % SER_BUF_DATA_SIZE;
678
#ifdef OPAL_DEBUG_CONSOLE_IO
679
prlog(PR_TRACE, "OPAL: console read req=%d read=%d ni=%d no=%d\n",
680
req, n, sb->next_in, sb->next_out);
681
prlog(PR_TRACE, " %02x %02x %02x %02x %02x %02x %02x %02x ...\n",
682
buffer[0], buffer[1], buffer[2], buffer[3],
683
buffer[4], buffer[5], buffer[6], buffer[7]);
684
#endif /* OPAL_DEBUG_CONSOLE_IO */
686
/* Might clear the input pending flag */
687
for (i = 0; i < MAX_SERIAL && !pending; i++) {
688
struct fsp_serial *fs = &fsp_serials[i];
689
struct fsp_serbuf_hdr *sb = fs->in_buf;
691
if (fs->log_port || !fs->open)
693
if (sb->next_out != sb->next_in) {
695
* HACK: Some kernels (4.1+) may fail to properly
696
* register hvc1 and will never read it. This can lead
697
* to RCU stalls, so if we notice this console is not
698
* being read, do not set OPAL_EVENT_CONSOLE_INPUT even
701
if (fs->waiting < 5) {
708
opal_update_pending_evt(OPAL_EVENT_CONSOLE_INPUT, 0);
710
unlock(&fsp_con_lock);
715
void fsp_console_poll(void *data __unused)
717
#ifdef OPAL_DEBUG_CONSOLE_POLL
722
* We don't get messages for out buffer being consumed, so we
723
* need to poll. We also defer sending of poke messages from
724
* the sapphire console to avoid a locking nightmare with
725
* beging called from printf() deep into an existing lock nest
729
(opal_pending_events & OPAL_EVENT_CONSOLE_OUTPUT)) {
731
bool pending = false;
733
/* We take the console lock. This is somewhat inefficient
734
* but it guarantees we aren't racing with a write, and
735
* thus clearing an event improperly
738
for (i = 0; i < MAX_SERIAL && !pending; i++) {
739
struct fsp_serial *fs = &fsp_serials[i];
740
struct fsp_serbuf_hdr *sb = fs->out_buf;
744
if (sb->next_out == sb->next_in)
747
__flush_console(true);
749
#ifdef OPAL_DEBUG_CONSOLE_POLL
751
prlog(PR_DEBUG,"OPAL: %d still pending"
753
i, sb->next_in, sb->next_out);
756
#endif /* OPAL_DEBUG_CONSOLE_POLL */
761
opal_update_pending_evt(OPAL_EVENT_CONSOLE_OUTPUT, 0);
762
#ifdef OPAL_DEBUG_CONSOLE_POLL
766
unlock(&fsp_con_lock);
770
void fsp_console_init(void)
772
struct dt_node *serials, *ser;
778
opal_register(OPAL_CONSOLE_READ, fsp_console_read, 3);
779
opal_register(OPAL_CONSOLE_WRITE_BUFFER_SPACE,
780
fsp_console_write_buffer_space, 2);
781
opal_register(OPAL_CONSOLE_WRITE, fsp_console_write, 3);
783
/* Wait until we got the intf query before moving on */
784
while (!got_intf_query)
787
op_display(OP_LOG, OP_MOD_FSPCON, 0x0000);
789
/* Register poller */
790
opal_add_poller(fsp_console_poll, NULL);
792
/* Parse serial port data */
793
serials = dt_find_by_path(dt_root, "ipl-params/fsp-serial");
795
prerror("FSPCON: No FSP serial ports in device-tree\n");
800
dt_for_each_child(serials, ser) {
801
u32 rsrc_id = dt_prop_get_u32(ser, "reg");
802
const void *lc = dt_prop_get(ser, "ibm,loc-code");
804
prlog(PR_NOTICE, "FSPCON: Serial %d rsrc: %04x loc: %s\n",
805
i, rsrc_id, (const char *)lc);
806
fsp_serial_add(i++, rsrc_id, lc, false);
807
op_display(OP_LOG, OP_MOD_FSPCON, 0x0010 + i);
810
op_display(OP_LOG, OP_MOD_FSPCON, 0x0005);
813
static void flush_all_input(void)
818
for (i = 0; i < MAX_SERIAL; i++) {
819
struct fsp_serial *fs = &fsp_serials[i];
820
struct fsp_serbuf_hdr *sb = fs->in_buf;
825
sb->next_out = sb->next_in;
827
unlock(&fsp_con_lock);
830
static bool send_all_hvsi_close(void)
833
bool has_hvsi = false;
834
static const uint8_t close_packet[] = { 0xfe, 6, 0, 1, 0, 3 };
836
for (i = 0; i < MAX_SERIAL; i++) {
837
struct fsp_serial *fs = &fsp_serials[i];
838
struct fsp_serbuf_hdr *sb = fs->out_buf;
839
unsigned int space, timeout = 10;
843
if (fs->rsrc_id == 0xffff)
847
/* Do we have room ? Wait a bit if not */
849
space = (sb->next_out + SER_BUF_DATA_SIZE -
850
sb->next_in - 1) % SER_BUF_DATA_SIZE;
856
fsp_write_vserial(fs, close_packet, 6);
857
unlock(&fsp_con_lock);
863
static void reopen_all_hvsi(void)
867
for (i = 0; i < MAX_SERIAL; i++) {
868
struct fsp_serial *fs = &fsp_serials[i];
869
if (fs->rsrc_id == 0xffff)
871
prlog(PR_NOTICE, "FSP: Deassociating HVSI console %d\n", i);
872
fsp_sync_msg(fsp_mkmsg(FSP_CMD_UNASSOC_SERIAL, 1,
873
(i << 16) | 1), true);
875
for (i = 0; i < MAX_SERIAL; i++) {
876
struct fsp_serial *fs = &fsp_serials[i];
877
if (fs->rsrc_id == 0xffff)
879
prlog(PR_NOTICE, "FSP: Reassociating HVSI console %d\n", i);
880
fsp_sync_msg(fsp_mkmsg(FSP_CMD_ASSOC_SERIAL, 2,
881
(fs->rsrc_id << 16) | 1, i), true);
885
void fsp_console_reset(void)
887
prlog(PR_NOTICE, "FSP: Console reset !\n");
889
/* This is called on a fast-reset. To work around issues with HVSI
890
* initial negotiation, before we reboot the kernel, we flush all
891
* input and send an HVSI close packet.
895
/* Returns false if there is no HVSI console */
896
if (!send_all_hvsi_close())
907
void fsp_console_add_nodes(void)
910
struct dt_node *consoles;
912
consoles = dt_new(opal_node, "consoles");
913
dt_add_property_cells(consoles, "#address-cells", 1);
914
dt_add_property_cells(consoles, "#size-cells", 0);
915
for (i = 0; i < MAX_SERIAL; i++) {
916
struct fsp_serial *fs = &fsp_serials[i];
917
struct dt_node *fs_node;
920
if (fs->log_port || !fs->available)
923
snprintf(name, sizeof(name), "serial@%d", i);
924
fs_node = dt_new(consoles, name);
925
if (fs->rsrc_id == 0xffff)
926
dt_add_property_string(fs_node, "compatible",
927
"ibm,opal-console-raw");
929
dt_add_property_string(fs_node, "compatible",
930
"ibm,opal-console-hvsi");
931
dt_add_property_cells(fs_node,
932
"#write-buffer-size", SER_BUF_DATA_SIZE);
933
dt_add_property_cells(fs_node, "reg", i);
934
dt_add_property_string(fs_node, "device_type", "serial");
938
void fsp_console_select_stdout(void)
940
bool use_serial = false;
945
/* On P8, we have a sysparam ! yay ! */
946
if (proc_gen >= proc_gen_p8) {
950
rc = fsp_get_sys_param(SYS_PARAM_CONSOLE_SELECT,
951
¶m, 1, NULL, NULL);
953
prerror("FSPCON: Failed to get console"
954
" sysparam rc %d\n", rc);
964
prerror("FSPCON: Unknown console"
965
" sysparam %d\n", param);
969
struct dt_node *iplp;
973
* We hijack the "os-ipl-mode" setting in iplparams to select
974
* out output console. This is the "i5/OS partition mode boot"
975
* setting in ASMI converted to an integer: 0=A, 1=B.
977
iplp = dt_find_by_path(dt_root, "ipl-params/ipl-params");
979
ipl_mode = dt_prop_get_u32_def(iplp, "os-ipl-mode", 0);
980
use_serial = ipl_mode > 0;
983
* Now, if ipl_mode is > 0, we use serial port A else
984
* we use IPMI/SOL/DVS
988
if (fsp_serials[1].open && use_serial) {
989
dt_add_property_string(dt_chosen, "linux,stdout-path",
990
"/ibm,opal/consoles/serial@1");
991
prlog(PR_NOTICE, "FSPCON: default console set to serial A\n");
993
dt_add_property_string(dt_chosen, "linux,stdout-path",
994
"/ibm,opal/consoles/serial@0");
995
prlog(PR_NOTICE, "FSPCON: default console set to SOL/DVS\n");