Skip to content

Commit

Permalink
p9dsu: detect p9dsu variant even when hostboot doesn't tell us
Browse files Browse the repository at this point in the history
The SuperMicro BMC can tell us what riser type we have, which dictates
the PCI slot tables. Usually, in an environment that a customer would
experience, Hostboot will do the query with an SMC specific patch
(not upstream as there's no platform specific code in hostboot)
and skiboot knows what variant it is based on the compatible string.

However, if you're using upstream hostboot, you only get the bare
'p9dsu' compatible type. We can work around this by asking the BMC
ourselves and setting the slot table appropriately. We do this
syncronously in platform init so that we don't start probing
PCI before we setup the slot table.

This adds a bit of funky logic in the p9dsu platform file, but on
the whole makes things simpler.

Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
  • Loading branch information
stewartsmith committed Apr 24, 2018
1 parent 376b5e3 commit d32ddea
Showing 1 changed file with 80 additions and 68 deletions.
148 changes: 80 additions & 68 deletions platforms/astbmc/p9dsu.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* Copyright 2017 Supermicro Inc.
* Copyright 2018 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -21,6 +22,8 @@
#include <ipmi.h>
#include <psi.h>
#include <npu-regs.h>
#include <opal-internal.h>
#include <cpu.h>

#include "astbmc.h"

Expand Down Expand Up @@ -578,9 +581,12 @@ static void p9dsu_dt_fixups(void)
}
}

static bool p9dsu1u_probe(void)
static bool p9dsu_probe(void)
{
if (!dt_node_is_compatible(dt_root, "supermicro,p9dsu1u"))
if (!(dt_node_is_compatible(dt_root, "supermicro,p9dsu") ||
dt_node_is_compatible(dt_root, "supermicro,p9dsu1u") ||
dt_node_is_compatible(dt_root, "supermicro,p9dsu2u") ||
dt_node_is_compatible(dt_root, "supermicro,p9dsu2uess")))
return false;

/* Lot of common early inits here */
Expand All @@ -591,71 +597,93 @@ static bool p9dsu1u_probe(void)

p9dsu_dt_fixups();

slot_table_init(p9dsu1u_phb_table);
if (dt_node_is_compatible(dt_root, "supermicro,p9dsu1u")) {
prlog(PR_INFO, "Detected p9dsu1u variant\n");
slot_table_init(p9dsu1u_phb_table);
} else if (dt_node_is_compatible(dt_root, "supermicro,p9dsu2u")) {
prlog(PR_INFO, "Detected p9dsu2u variant\n");
slot_table_init(p9dsu2u_phb_table);
} else if (dt_node_is_compatible(dt_root, "supermicro,p9dsu2uess")) {
prlog(PR_INFO, "Detected p9dsu2uess variant\n");
slot_table_init(p9dsu2uess_phb_table);
}
/*
* else we need to ask the BMC what subtype we are, but we need IPMI
* which we don't get until astbmc_init(), so we delay setting up the
* slot table until later.
*
* This only applies if you're using a Hostboot that doesn't do this
* for us.
*/

return true;
}
static bool p9dsu2u_probe(void)
{
if (!dt_node_is_compatible(dt_root, "supermicro,p9dsu2u"))
return false;

/* Lot of common early inits here */
astbmc_early_init();

/* Setup UART for use by OPAL (Linux hvc) */
uart_set_console_policy(UART_CONSOLE_OPAL);

p9dsu_dt_fixups();

slot_table_init(p9dsu2u_phb_table);

return true;
static void p9dsu_riser_query_complete(struct ipmi_msg *m)
{
u8 *riser_id = (u8*)m->user_data;
lwsync();
*riser_id = m->data[0];
ipmi_free_msg(m);
}


static bool p9dsu2uess_probe(void)
static void p9dsu_init(void)
{
if (!dt_node_is_compatible(dt_root, "supermicro,p9dsu2uess"))
return false;

/* Lot of common early inits here */
astbmc_early_init();

/* Setup UART for use by OPAL (Linux hvc) */
uart_set_console_policy(UART_CONSOLE_OPAL);

p9dsu_dt_fixups();

slot_table_init(p9dsu2uess_phb_table);

return true;
u8 smc_riser_req[] = {0x03, 0x70, 0x01, 0x02};
struct ipmi_msg *ipmi_msg;
u8 riser_id = 0;
const char *p9dsu_variant;

astbmc_init();
/*
* Now we have IPMI up and running we can ask the BMC for what p9dsu
* variant we are if Hostboot isn't the patched one that does this
* for us.
*/
if (dt_node_is_compatible(dt_root, "supermicro,p9dsu")) {
ipmi_msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE,
IPMI_CODE(IPMI_NETFN_APP, 0x52),
p9dsu_riser_query_complete,
&riser_id,
smc_riser_req, sizeof(smc_riser_req), 1);
ipmi_queue_msg(ipmi_msg);
while(riser_id==0) {
opal_run_pollers();
cpu_relax();
}
switch (riser_id) {
default:
prlog(PR_INFO,"Defaulting to p9dsu1u\n");
/* fallthrough */
case 0x9:
p9dsu_variant = "supermicro,p9dsu1u";
slot_table_init(p9dsu1u_phb_table);
break;
case 0x19:
p9dsu_variant = "supermicro,p9dsu2u";
slot_table_init(p9dsu2u_phb_table);
break;
case 0x1D:
p9dsu_variant = "supermicro,p9dsuess";
slot_table_init(p9dsu2uess_phb_table);
break;
}
prlog(PR_INFO,"Detected %s variant via IPMI\n", p9dsu_variant);
dt_check_del_prop(dt_root, "compatible");
dt_add_property_strings(dt_root, "compatible", "ibm,powernv",
"supermicro,p9dsu", p9dsu_variant);
}
}


static const struct bmc_platform astbmc_smc = {
.name = "SMC",
.ipmi_oem_partial_add_esel = IPMI_CODE(0x3a, 0xf0),
};

DECLARE_PLATFORM(p9dsu1u) = {
.name = "p9dsu1u",
.probe = p9dsu1u_probe,
.init = astbmc_init,
.start_preload_resource = flash_start_preload_resource,
.resource_loaded = flash_resource_loaded,
.bmc = &astbmc_smc,
.pci_get_slot_info = slot_table_get_slot_info,
.cec_power_down = astbmc_ipmi_power_down,
.cec_reboot = astbmc_ipmi_reboot,
.elog_commit = ipmi_elog_commit,
.exit = ipmi_wdt_final_reset,
.terminate = ipmi_terminate,
};
DECLARE_PLATFORM(p9dsu2u) = {
.name = "p9dsu2u",
.probe = p9dsu2u_probe,
.init = astbmc_init,
.name = "p9dsu",
.probe = p9dsu_probe,
.init = p9dsu_init,
.start_preload_resource = flash_start_preload_resource,
.resource_loaded = flash_resource_loaded,
.bmc = &astbmc_smc,
Expand All @@ -666,19 +694,3 @@ DECLARE_PLATFORM(p9dsu2u) = {
.exit = ipmi_wdt_final_reset,
.terminate = ipmi_terminate,
};

DECLARE_PLATFORM(p9dsu2uess) = {
.name = "p9dsu2uess",
.probe = p9dsu2uess_probe,
.init = astbmc_init,
.start_preload_resource = flash_start_preload_resource,
.resource_loaded = flash_resource_loaded,
.bmc = &astbmc_smc,
.pci_get_slot_info = slot_table_get_slot_info,
.cec_power_down = astbmc_ipmi_power_down,
.cec_reboot = astbmc_ipmi_reboot,
.elog_commit = ipmi_elog_commit,
.exit = ipmi_wdt_final_reset,
.terminate = ipmi_terminate,
};

0 comments on commit d32ddea

Please sign in to comment.