diff options
author | Oliver O'Halloran <oohall@gmail.com> | 2017-09-15 15:40:58 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-09-15 02:49:27 -0500 |
commit | 9b886a44d993ade2f05f3a554a098c674bb7cd7f (patch) | |
tree | 69cc1c95c1ec9f34ec02d73652d9401b5a0ea0ad | |
parent | ad484081ef8a51811e7902aec436fa8f1ca9604a (diff) | |
download | skiboot-9b886a44d993ade2f05f3a554a098c674bb7cd7f.zip skiboot-9b886a44d993ade2f05f3a554a098c674bb7cd7f.tar.gz skiboot-9b886a44d993ade2f05f3a554a098c674bb7cd7f.tar.bz2 |
hdata: Parse NVLink information
Add the per-chip structures that descibe how the A-Bus/NVLink/OpenCAPI
phy is configured. This generates the npu@xyz nodes for each chip on
systems that support it.
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r-- | hdata/hdata.h | 3 | ||||
-rw-r--r-- | hdata/iohub.c | 4 | ||||
-rw-r--r-- | hdata/spira.c | 168 | ||||
-rw-r--r-- | hdata/spira.h | 29 |
4 files changed, 202 insertions, 2 deletions
diff --git a/hdata/hdata.h b/hdata/hdata.h index cab0626..82479f5 100644 --- a/hdata/hdata.h +++ b/hdata/hdata.h @@ -68,5 +68,8 @@ extern bool hservices_from_hdat(const void *fdt, size_t size); int parse_i2c_devs(const struct HDIF_common_hdr *hdr, int idata_index, struct dt_node *xscom); +/* used to look up the device-tree node representing a slot */ +struct dt_node *find_slot_entry_node(struct dt_node *root, u32 entry_id); + #endif /* __HDATA_H */ diff --git a/hdata/iohub.c b/hdata/iohub.c index ecfc6de..567ab59 100644 --- a/hdata/iohub.c +++ b/hdata/iohub.c @@ -556,7 +556,7 @@ static void parse_slot_details(struct dt_node *slot, dt_add_property(slot, "nvlink", NULL, 0); } -static struct dt_node *find_slot_entry_node(struct dt_node *root, u32 entry_id) +struct dt_node *find_slot_entry_node(struct dt_node *root, u32 entry_id) { struct dt_node *node; @@ -756,7 +756,7 @@ static void parse_one_slot(const struct slot_map_entry *entry, be16_to_cpu(entry->lane_reverse)); if (strnlen(entry->name, sizeof(entry->name))) - dt_add_property_nstr(node, "slot-name", + dt_add_property_nstr(node, "ibm,slot-label", entry->name, sizeof(entry->name)); if (entry->type == st_slot || entry->type == st_rc_slot) dt_add_property(node, "ibm,pluggable", NULL, 0); diff --git a/hdata/spira.c b/hdata/spira.c index 240f344..73a678f 100644 --- a/hdata/spira.c +++ b/hdata/spira.c @@ -1275,6 +1275,170 @@ static void add_stop_levels(void) "ibm,enabled-stop-levels", stop_levels); } +#define NPU_BASE 0x5011000 +#define NPU_SIZE 0x2c +#define NPU_INDIRECT0 0x8000000009010c3f +#define NPU_INDIRECT1 0x800000000c010c3f + +static void add_npu(struct dt_node *xscom, const struct HDIF_array_hdr *links, + int npu_index, int phb_index) +{ + const struct sppcrd_smp_link *link; + struct dt_node *npu; + int group_target[6]; /* Tracks the PCI slot targeted each link group */ + int group_count = 0; + int link_count = 0; + uint32_t chip_id; + int i; + + chip_id = dt_get_chip_id(xscom); + + memset(group_target, 0, sizeof(group_target)); + + npu = dt_new_addr(xscom, "npu", NPU_BASE); + dt_add_property_cells(npu, "reg", NPU_BASE, NPU_SIZE); + dt_add_property_cells(npu, "#size-cells", 0); + dt_add_property_cells(npu, "#address-cells", 1); + + dt_add_property_strings(npu, "compatible", "ibm,power9-npu"); + dt_add_property_cells(npu, "ibm,phb-index", phb_index); + dt_add_property_cells(npu, "ibm,npu-index", npu_index); + + HDIF_iarray_for_each(links, i, link) { + uint16_t slot_id = be16_to_cpu(link->pci_slot_idx); + uint32_t link_id = be32_to_cpu(link->link_id); + struct dt_node *node; + + /* only add a link node if this link is targeted at at device */ + if (be32_to_cpu(link->usage) != SMP_LINK_USE_DEVICE) + continue; + + /* + * XXX: The link_id that we get from HDAT is essentially an + * arbitrary ID number so we can't use it as the reg for the + * link node. + * + * a) There's a 1-1 mapping between entries in the SMP link + * structure and the NPU links. + * + * b) The SMP link array contains them in ascending order. + * + * We have some assurances that b) is correct, but if we get + * broken link numbering it's something to watch for. + * + * If we every have actual A-Bus (SMP) link info in here + * this is going to break. + */ + + prlog(PR_DEBUG, "NPU: %04x:%d: Link (%d) targets slot %u", + chip_id, link_count, link_count, slot_id); + + if (link_count >= 6) { + prerror("NPU: %04x:%d: Ignoring extra link (max 6)\n", + chip_id, link_count); + break; + } + + node = dt_new_addr(npu, "link", link_count); + if (!node) { + prerror("NPU: %04x:%d: Creating link node failed\n", + chip_id, link_count); + continue; + } + + dt_add_property_string(node, "compatible", "ibm,npu-link"); + dt_add_property_cells(node, "reg", link_count); + dt_add_property_cells(node, "ibm,npu-link-index", link_count); + dt_add_property_cells(node, "ibm,workbook-link-id", link_id); + + dt_add_property_u64s(node, "ibm,npu-phy", + link_count < 3 ? NPU_INDIRECT0 : NPU_INDIRECT1); + dt_add_property_cells(node, "ibm,npu-lane-mask", + be32_to_cpu(link->lane_mask)); + dt_add_property_cells(node, "ibm,npu-brick-id", + be32_to_cpu(link->brick_id)); + + link_count++; + + /* + * Add the group details if this is an NVlink. + * + * TODO: Cable card stuff. + */ + if (slot_id) { + struct dt_node *slot; + const char *name; + int group; + + /* + * Search the existing groups for one targeting + * this PCI slot + */ + for (group = 0; group < group_count; group++) + if (group_target[group] == slot_id) + break; + + /* no group, make a new one */ + if (group == group_count) { + group_target[group] = slot_id; + group_count++; + } + + dt_add_property_cells(node, "ibm,npu-group-id", group); + + slot = find_slot_entry_node(dt_root, slot_id); + if (!slot) { + prerror("NPU: %04x:%d: Unable find node for targeted PCIe slot\n", + chip_id, link_count - 1); + continue; + } + + name = dt_prop_get_def(slot, "ibm,slot-label", + (char *)"<SLOT NAME MISSING>"); + + prlog(PR_DEBUG, "NPU: %04x:%d: Target slot %s\n", + chip_id, link_count - 1, name); + + dt_add_property_string(node, "ibm,slot-label", name); + dt_add_property_cells(node, "ibm,pcie-slot", + slot->phandle); + } + } + + dt_add_property_cells(npu, "ibm,npu-links", link_count); +} + +static void add_npus(void) +{ + struct dt_node *xscom; + int phb_index = 7; /* Start counting from 7, for no reason */ + int npu_index = 0; + + if (proc_gen < proc_gen_p9) + return; + + dt_for_each_compatible(dt_root, xscom, "ibm,xscom") { + const struct HDIF_array_hdr *links; + + links = xscom_to_pcrd(xscom, SPPCRD_IDATA_SMP_LINK); + if (!links) { + prerror("NPU: Unable to find matching SPPCRD for %s\n", + xscom->name); + continue; + } + + /* should never happen, but stranger things have */ + if (!dt_find_by_name(dt_root, "ibm,pcie-slots")) { + prerror("PCIe slot information missing, can't add npu"); + continue; + } + + /* some hostboots will give us an empty array */ + if (be32_to_cpu(links->ecnt)) + add_npu(xscom, links, npu_index, phb_index); + } +} + /* * Legacy SPIRA is being deprecated and we have new SPIRA-H/S structures. * But on older system (p7?) we will continue to get legacy SPIRA. @@ -1375,6 +1539,10 @@ int parse_hdat(bool is_opal) /* Add IO HUBs and/or PHBs */ io_parse(); + /* Add NPU nodes */ + if (proc_gen >= proc_gen_p9) + add_npus(); + /* Parse VPD */ vpd_parse(); diff --git a/hdata/spira.h b/hdata/spira.h index 8e8c74e..9b427cb 100644 --- a/hdata/spira.h +++ b/hdata/spira.h @@ -1151,6 +1151,35 @@ struct sppcrd_chip_tod { /* Idata index 5 : Chip attached I2C devices */ #define SPPCRD_IDATA_HOST_I2C 5 +/* Idata index 5 : Chip attached I2C devices */ +#define SPPCRD_IDATA_PNOR 6 + +/* Idata index 6 : OpenCAPI/NVlink info */ +#define SPPCRD_IDATA_SMP_LINK 7 +struct sppcrd_smp_link { + __be32 link_id; + __be32 usage; +#define SMP_LINK_USE_NONE 0 +#define SMP_LINK_USE_DEVICE 1 +#define SMP_LINK_USE_INTERPOSER 2 +#define SMP_LINK_USE_DRAWER 3 +#define SMP_LINK_USE_D2D 4 /* GPU to GPU */ + __be32 brick_id; + __be32 lane_mask; + + /* bonded pci slots (mostly a NVLink thing) */ + __be16 pci_slot_idx; + __be16 pci_sideband_slot_idx; + + __be16 slca_idx; /* SLCA index of the *external* port */ + __be16 reserved; + + /* nvlink/ocapi detection devices */ + __be32 i2c_link_cable; + __be32 i2c_presence; + __be32 i2c_micro; +} __packed; + /* * Host Services Data. */ |