LCOV - code coverage report
Current view: top level - hdata - iohub.c (source / functions) Coverage Total Hit
Test: skiboot.info Lines: 25.6 % 390 100
Test Date: 2025-01-24 18:40:10 Functions: 40.0 % 20 8
Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
       2                 :             : /* Copyright 2013-2019 IBM Corp. */
       3                 :             : 
       4                 :             : #include <skiboot.h>
       5                 :             : #include "spira.h"
       6                 :             : #include <cpu.h>
       7                 :             : #include <fsp.h>
       8                 :             : #include <opal.h>
       9                 :             : #include <ccan/str/str.h>
      10                 :             : #include <ccan/array_size/array_size.h>
      11                 :             : #include <device.h>
      12                 :             : #include <vpd.h>
      13                 :             : #include <inttypes.h>
      14                 :             : #include <string.h>
      15                 :             : 
      16                 :             : #include "hdata.h"
      17                 :             : 
      18                 :           1 : static bool io_get_lx_info(const void *kwvpd, unsigned int kwvpd_sz,
      19                 :             :                            int lx_idx, struct dt_node *hn)
      20                 :             : {
      21                 :             :         const void *lxr;
      22                 :             :         char recname[5];
      23                 :           1 :         beint32_t lxrbuf[2] = { 0, 0 };
      24                 :             : 
      25                 :             :         /* Find LXRn, where n is the index passed in*/
      26                 :           1 :         strcpy(recname, "LXR0");
      27                 :           1 :         recname[3] += lx_idx;
      28                 :           1 :         lxr = vpd_find(kwvpd, kwvpd_sz, recname, "LX", NULL);
      29                 :           1 :         if (!lxr) {
      30                 :             :                 /* Not found, try VINI */
      31                 :           0 :                 lxr = vpd_find(kwvpd, kwvpd_sz, "VINI",
      32                 :             :                                "LX",  NULL);
      33                 :           0 :                 if (lxr)
      34                 :           0 :                         lx_idx = VPD_LOAD_LXRN_VINI;
      35                 :             :         }
      36                 :           1 :         if (!lxr) {
      37                 :           0 :                 prlog(PR_DEBUG, "CEC:     LXR%x not found !\n", lx_idx);
      38                 :           0 :                 return false;
      39                 :             :         }
      40                 :             : 
      41                 :           1 :         memcpy(lxrbuf, lxr, sizeof(beint32_t)*2);
      42                 :             : 
      43                 :           1 :         prlog(PR_DEBUG, "CEC:     LXRn=%d LXR=%08x%08x\n", lx_idx, be32_to_cpu(lxrbuf[0]), be32_to_cpu(lxrbuf[1]));
      44                 :           1 :         prlog(PR_DEBUG, "CEC:     LX Info added to %llx\n", (long long)hn);
      45                 :             : 
      46                 :             :         /* Add the LX info */
      47                 :           1 :         if (!dt_has_node_property(hn, "ibm,vpd-lx-info", NULL)) {
      48                 :           1 :                 dt_add_property_cells(hn, "ibm,vpd-lx-info",
      49                 :             :                                       lx_idx,
      50                 :             :                                       be32_to_cpu(lxrbuf[0]),
      51                 :             :                                       be32_to_cpu(lxrbuf[1]));
      52                 :             :         }
      53                 :             : 
      54                 :           1 :         return true;
      55                 :             : }
      56                 :             : 
      57                 :             : 
      58                 :           5 : static void io_get_loc_code(const void *sp_iohubs, struct dt_node *hn, const char *prop_name)
      59                 :             : {
      60                 :             :         const struct spira_fru_id *fru_id;
      61                 :             :         unsigned int fru_id_sz;
      62                 :             :         char loc_code[LOC_CODE_SIZE + 1];
      63                 :             :         const char *slca_loc_code;
      64                 :             : 
      65                 :             :         /* Find SLCA Index */
      66                 :           5 :         fru_id = HDIF_get_idata(sp_iohubs, CECHUB_FRU_ID_DATA, &fru_id_sz);
      67                 :           5 :         if (fru_id) {
      68                 :           5 :                 memset(loc_code, 0, sizeof(loc_code));
      69                 :             : 
      70                 :             :                 /* Find LOC Code from SLCA Index */
      71                 :           5 :                 slca_loc_code = slca_get_loc_code_index(be16_to_cpu(fru_id->slca_index));
      72                 :           5 :                 if (slca_loc_code) {
      73                 :           5 :                         strncpy(loc_code, slca_loc_code, LOC_CODE_SIZE);
      74                 :           5 :                         if (!dt_has_node_property(hn, prop_name, NULL)) {
      75                 :           5 :                                 dt_add_property(hn, prop_name, loc_code,
      76                 :           5 :                                                 strlen(loc_code) + 1);
      77                 :             :                         }
      78                 :           5 :                         prlog(PR_DEBUG, "CEC:     %s: %s (SLCA rsrc 0x%x)\n",
      79                 :             :                               prop_name, loc_code,
      80                 :             :                               be16_to_cpu(fru_id->rsrc_id));
      81                 :             :                 } else {
      82                 :           0 :                         prlog(PR_DEBUG, "CEC:     SLCA Loc not found: "
      83                 :             :                               "index %d\n", fru_id->slca_index);
      84                 :             :                 }
      85                 :             :         } else {
      86                 :           0 :                 prlog(PR_DEBUG, "CEC:     Hub FRU ID not found...\n");
      87                 :             :         }
      88                 :           5 : }
      89                 :             : 
      90                 :           4 : static struct dt_node *io_add_phb3(const struct cechub_io_hub *hub,
      91                 :             :                                    const struct HDIF_common_hdr *sp_iohubs,
      92                 :             :                                    unsigned int index, struct dt_node *xcom,
      93                 :             :                                    unsigned int pe_xscom,
      94                 :             :                                    unsigned int pci_xscom,
      95                 :             :                                    unsigned int spci_xscom)
      96                 :             : {
      97                 :             :         struct dt_node *pbcq;
      98                 :             :         unsigned int hdif_vers;
      99                 :             : 
     100                 :             :         /* Get HDIF version */
     101                 :           4 :         hdif_vers = be16_to_cpu(sp_iohubs->version);
     102                 :             : 
     103                 :             :         /* Create PBCQ node under xscom */
     104                 :           4 :         pbcq = dt_new_addr(xcom, "pbcq", pe_xscom);
     105                 :           4 :         if (!pbcq)
     106                 :           0 :                 return NULL;
     107                 :             : 
     108                 :             :         /* "reg" property contains in order the PE, PCI and SPCI XSCOM
     109                 :             :          * addresses
     110                 :             :          */
     111                 :           4 :         dt_add_property_cells(pbcq, "reg",
     112                 :             :                                 pe_xscom, 0x20,
     113                 :             :                                 pci_xscom, 0x05,
     114                 :             :                                 spci_xscom, 0x15);
     115                 :             : 
     116                 :             :         /* A couple more things ... */
     117                 :           4 :         dt_add_property_strings(pbcq, "compatible", "ibm,power8-pbcq");
     118                 :           4 :         dt_add_property_cells(pbcq, "ibm,phb-index", index);
     119                 :           4 :         dt_add_property_cells(pbcq, "ibm,hub-id", be16_to_cpu(hub->hub_num));
     120                 :             : 
     121                 :             :         /* The loc code of the PHB itself is different from the base
     122                 :             :          * loc code of the slots (It's actually the DCM's loc code).
     123                 :             :          */
     124                 :           4 :         io_get_loc_code(sp_iohubs, pbcq, "ibm,loc-code");
     125                 :             : 
     126                 :             :         /* We indicate that this is an IBM setup, which means that
     127                 :             :          * the presence detect A/B bits are meaningful. So far we
     128                 :             :          * don't know whether they make any sense on customer setups
     129                 :             :          * so we only set that when booting with HDAT
     130                 :             :          */
     131                 :           4 :         dt_add_property(pbcq, "ibm,use-ab-detect", NULL, 0);
     132                 :             : 
     133                 :             :         /* HDAT spec has these in version 0x6A and later */
     134                 :           4 :         if (hdif_vers >= 0x6a) {
     135                 :           4 :                 u64 eq0 = be64_to_cpu(hub->phb_lane_eq[index][0]);
     136                 :           4 :                 u64 eq1 = be64_to_cpu(hub->phb_lane_eq[index][1]);
     137                 :           4 :                 u64 eq2 = be64_to_cpu(hub->phb_lane_eq[index][2]);
     138                 :           4 :                 u64 eq3 = be64_to_cpu(hub->phb_lane_eq[index][3]);
     139                 :             : 
     140                 :           4 :                 dt_add_property_u64s(pbcq, "ibm,lane-eq", eq0, eq1, eq2, eq3);
     141                 :             :         }
     142                 :             : 
     143                 :             :         /* Currently we only create a PBCQ node, the actual PHB nodes
     144                 :             :          * will be added by sapphire later on.
     145                 :             :          */
     146                 :           4 :         return pbcq;
     147                 :             : }
     148                 :             : 
     149                 :           0 : static struct dt_node *add_pec_stack(const struct cechub_io_hub *hub,
     150                 :             :                                      struct dt_node *pbcq, int stack_index,
     151                 :             :                                      int phb_index, u8 active_phbs)
     152                 :             : {
     153                 :             :         struct dt_node *stack;
     154                 :             :         const char *compat;
     155                 :             :         u64 eq[12];
     156                 :             :         u8 *ptr;
     157                 :             :         int i;
     158                 :             : 
     159                 :           0 :         stack = dt_new_addr(pbcq, "stack", stack_index);
     160                 :           0 :         assert(stack);
     161                 :             : 
     162                 :           0 :         if (proc_gen == proc_gen_p9)
     163                 :           0 :                 compat = "ibm,power9-phb-stack";
     164                 :             :         else
     165                 :           0 :                 compat = "ibm,power10-phb-stack";
     166                 :             : 
     167                 :           0 :         dt_add_property_cells(stack, "reg", stack_index);
     168                 :           0 :         dt_add_property_cells(stack, "ibm,phb-index", phb_index);
     169                 :           0 :         dt_add_property_string(stack, "compatible", compat);
     170                 :             : 
     171                 :             :         /* XXX: This should probably just return if the PHB is disabled
     172                 :             :          *      rather than adding the extra properties.
     173                 :             :          */
     174                 :             : 
     175                 :           0 :         if (active_phbs & (0x80 >> phb_index))
     176                 :           0 :                 dt_add_property_string(stack, "status", "okay");
     177                 :             :         else
     178                 :           0 :                 dt_add_property_string(stack, "status", "disabled");
     179                 :             : 
     180                 :           0 :         for (i = 0; i < 4; i++) /* gen 3 eq settings */
     181                 :           0 :                 eq[i] = be64_to_cpu(hub->phb_lane_eq[phb_index][i]);
     182                 :           0 :         for (i = 0; i < 4; i++) /* gen 4 eq settings */
     183                 :           0 :                 eq[i+4] = be64_to_cpu(hub->phb4_lane_eq[phb_index][i]);
     184                 :           0 :         for (i = 0; i < 4; i++) /* gen 5 eq settings */
     185                 :           0 :                 eq[i+8] = be64_to_cpu(hub->phb5_lane_eq[phb_index][i]);
     186                 :             : 
     187                 :             :         /* Lane-eq settings are packed 2 bytes per lane for 16 lanes
     188                 :             :          * On P9 DD2 and P10, 1 byte per lane is used in the hardware
     189                 :             :          */
     190                 :             : 
     191                 :             :         /* Repack 2 byte lane settings into 1 byte for gen 4 & 5 */
     192                 :           0 :         ptr = (u8 *)&eq[4];
     193                 :           0 :         for (i = 0; i < 32; i++)
     194                 :           0 :                 ptr[i] = ptr[2*i];
     195                 :             : 
     196                 :           0 :         if (proc_gen == proc_gen_p9)
     197                 :           0 :                 dt_add_property_u64s(stack, "ibm,lane-eq",
     198                 :             :                                      eq[0], eq[1], eq[2], eq[3],
     199                 :             :                                      eq[4], eq[5]);
     200                 :             :         else
     201                 :           0 :                 dt_add_property_u64s(stack, "ibm,lane-eq",
     202                 :             :                                      eq[0], eq[1], eq[2], eq[3],
     203                 :             :                                      eq[4], eq[5],
     204                 :             :                                      eq[6], eq[7]);
     205                 :           0 :         return stack;
     206                 :             : }
     207                 :             : 
     208                 :             : /* Add PHB4 on p9, PHB5 on p10 */
     209                 :           0 : static struct dt_node *io_add_phb4(const struct cechub_io_hub *hub,
     210                 :             :                                    const struct HDIF_common_hdr *sp_iohubs,
     211                 :             :                                    struct dt_node *xcom,
     212                 :             :                                    unsigned int pec_index,
     213                 :             :                                    int stacks,
     214                 :             :                                    int phb_base)
     215                 :             : {
     216                 :             :         struct dt_node *pbcq;
     217                 :           0 :         uint8_t active_phb_mask = hub->fab_br0_pdt;
     218                 :             :         uint32_t pe_xscom;
     219                 :             :         uint32_t pci_xscom;
     220                 :             :         const char *compat;
     221                 :             :         int i;
     222                 :             : 
     223                 :           0 :         if (proc_gen == proc_gen_p9) {
     224                 :           0 :                 pe_xscom  = 0x4010c00 + (pec_index * 0x0000400);
     225                 :           0 :                 pci_xscom = 0xd010800 + (pec_index * 0x1000000);
     226                 :           0 :                 compat = "ibm,power9-pbcq";
     227                 :             :         } else {
     228                 :           0 :                 pe_xscom  = 0x3011800 - (pec_index * 0x1000000);
     229                 :           0 :                 pci_xscom = 0x8010800 + (pec_index * 0x1000000);
     230                 :           0 :                 compat = "ibm,power10-pbcq";
     231                 :             :         }
     232                 :             : 
     233                 :             :         /* Create PBCQ node under xscom */
     234                 :           0 :         pbcq = dt_new_addr(xcom, "pbcq", pe_xscom);
     235                 :           0 :         if (!pbcq)
     236                 :           0 :                 return NULL;
     237                 :             : 
     238                 :             :         /* "reg" property contains (in order) the PE and PCI XSCOM addresses */
     239                 :           0 :         dt_add_property_cells(pbcq, "reg",
     240                 :             :                                 pe_xscom, 0x100,
     241                 :             :                                 pci_xscom, 0x200);
     242                 :             : 
     243                 :             :         /* The hubs themselves go under the stacks */
     244                 :           0 :         dt_add_property_strings(pbcq, "compatible", compat);
     245                 :           0 :         dt_add_property_cells(pbcq, "ibm,pec-index", pec_index);
     246                 :           0 :         dt_add_property_cells(pbcq, "#address-cells", 1);
     247                 :           0 :         dt_add_property_cells(pbcq, "#size-cells", 0);
     248                 :             : 
     249                 :           0 :         for (i = 0; i < stacks; i++)
     250                 :           0 :                 add_pec_stack(hub, pbcq, i, phb_base + i, active_phb_mask);
     251                 :             : 
     252                 :           0 :         dt_add_property_cells(pbcq, "ibm,hub-id", be16_to_cpu(hub->hub_num));
     253                 :             : 
     254                 :             :         /* The loc code of the PHB itself is different from the base
     255                 :             :          * loc code of the slots (It's actually the DCM's loc code).
     256                 :             :          */
     257                 :           0 :         io_get_loc_code(sp_iohubs, pbcq, "ibm,loc-code");
     258                 :             : 
     259                 :           0 :         prlog(PR_INFO, "CEC: Added PBCQ %d with %d stacks\n",
     260                 :             :                 pec_index, stacks);
     261                 :             : 
     262                 :             :         /* the actual PHB nodes created later on by skiboot */
     263                 :           0 :         return pbcq;
     264                 :             : }
     265                 :             : 
     266                 :           2 : static struct dt_node *io_add_p8(const struct cechub_io_hub *hub,
     267                 :             :                                  const struct HDIF_common_hdr *sp_iohubs)
     268                 :             : {
     269                 :             :         struct dt_node *xscom;
     270                 :             :         unsigned int i, chip_id;
     271                 :             : 
     272                 :           2 :         chip_id = pcid_to_chip_id(be32_to_cpu(hub->proc_chip_id));
     273                 :             : 
     274                 :           2 :         prlog(PR_INFO, "CEC:     HW CHIP=0x%x, HW TOPO=0x%04x\n", chip_id,
     275                 :             :               be16_to_cpu(hub->hw_topology));
     276                 :             : 
     277                 :           2 :         xscom = find_xscom_for_chip(chip_id);
     278                 :           2 :         if (!xscom) {
     279                 :           0 :                 prerror("P8: Can't find XSCOM for chip %d\n", chip_id);
     280                 :           0 :                 return NULL;
     281                 :             :         }
     282                 :             : 
     283                 :             :         /* Create PHBs, max 3 */
     284                 :           8 :         for (i = 0; i < 3; i++) {
     285                 :           6 :                 if (hub->fab_br0_pdt & (0x80 >> i))
     286                 :             :                         /* XSCOM addresses are the same on Murano and Venice */
     287                 :           4 :                         io_add_phb3(hub, sp_iohubs, i, xscom,
     288                 :           4 :                                     0x02012000 + (i * 0x400),
     289                 :           4 :                                     0x09012000 + (i * 0x400),
     290                 :           4 :                                     0x09013c00 + (i * 0x40));
     291                 :             :         }
     292                 :             : 
     293                 :             :         /* HACK: We return the XSCOM device for the VPD info */
     294                 :           2 :         return xscom;
     295                 :             : }
     296                 :             : 
     297                 :             : /* Add PBCQs for p9/p10 */
     298                 :           0 : static struct dt_node *io_add_p9(const struct cechub_io_hub *hub,
     299                 :             :                                  const struct HDIF_common_hdr *sp_iohubs)
     300                 :             : {
     301                 :             :         struct dt_node *xscom;
     302                 :             :         unsigned int chip_id;
     303                 :             : 
     304                 :           0 :         chip_id = pcid_to_chip_id(be32_to_cpu(hub->proc_chip_id));
     305                 :             : 
     306                 :           0 :         prlog(PR_INFO, "CEC:     HW CHIP=0x%x, HW TOPO=0x%04x\n", chip_id,
     307                 :             :               be16_to_cpu(hub->hw_topology));
     308                 :             : 
     309                 :           0 :         xscom = find_xscom_for_chip(chip_id);
     310                 :           0 :         if (!xscom) {
     311                 :           0 :                 prerror("IOHUB: Can't find XSCOM for chip %d\n", chip_id);
     312                 :           0 :                 return NULL;
     313                 :             :         }
     314                 :             : 
     315                 :           0 :         prlog(PR_DEBUG, "IOHUB: PHB active bridge mask %x\n",
     316                 :             :                 (u32) hub->fab_br0_pdt);
     317                 :             : 
     318                 :             :         /* Create PBCQs */
     319                 :           0 :         if (proc_gen == proc_gen_p9) {
     320                 :           0 :                 io_add_phb4(hub, sp_iohubs, xscom, 0, 1, 0);
     321                 :           0 :                 io_add_phb4(hub, sp_iohubs, xscom, 1, 2, 1);
     322                 :           0 :                 io_add_phb4(hub, sp_iohubs, xscom, 2, 3, 3);
     323                 :             :         } else { /* p10 */
     324                 :           0 :                 io_add_phb4(hub, sp_iohubs, xscom, 0, 3, 0);
     325                 :           0 :                 io_add_phb4(hub, sp_iohubs, xscom, 1, 3, 3);
     326                 :             :         }
     327                 :             : 
     328                 :           0 :         return xscom;
     329                 :             : }
     330                 :             : 
     331                 :             : 
     332                 :           1 : static void io_add_p8_cec_vpd(const struct HDIF_common_hdr *sp_iohubs)
     333                 :             : {
     334                 :             :         const struct HDIF_child_ptr *iokids;
     335                 :             :         const void *iokid;      
     336                 :             :         const void *kwvpd;
     337                 :             :         unsigned int kwvpd_sz;
     338                 :             : 
     339                 :             :         /* P8 LXR0 kept in IO KID Keyword VPD */
     340                 :           1 :         iokids = HDIF_child_arr(sp_iohubs, CECHUB_CHILD_IO_KIDS);
     341                 :           1 :         if (!CHECK_SPPTR(iokids)) {
     342                 :           0 :                 prlog(PR_WARNING, "CEC:     No IOKID child array !\n");
     343                 :           0 :                 return;
     344                 :             :         }
     345                 :           1 :         if (!iokids->count) {
     346                 :           0 :                 prlog(PR_WARNING, "CEC:     IOKID count is 0 !\n");
     347                 :           0 :                 return;
     348                 :             :         }
     349                 :           1 :         if (be32_to_cpu(iokids->count) > 1) {
     350                 :           0 :                 prlog(PR_WARNING, "CEC:     WARNING ! More than 1 IO KID !!! (%d)\n",
     351                 :             :                       be32_to_cpu(iokids->count));
     352                 :             :                 /* Ignoring the additional ones */
     353                 :             :         }
     354                 :             : 
     355                 :           1 :         iokid = HDIF_child(sp_iohubs, iokids, 0, "IO KID");
     356                 :           1 :         if (!iokid) {
     357                 :           0 :                 prlog(PR_WARNING, "CEC:     No IO KID structure in child array !\n");
     358                 :           0 :                 return;
     359                 :             :         }
     360                 :             : 
     361                 :             :         /* Grab base location code for slots */
     362                 :           1 :         io_get_loc_code(iokid, dt_root, "ibm,io-base-loc-code");
     363                 :             : 
     364                 :           1 :         kwvpd = HDIF_get_idata(iokid, CECHUB_ASCII_KEYWORD_VPD, &kwvpd_sz);
     365                 :           1 :         if (!kwvpd) {
     366                 :           0 :                 prlog(PR_WARNING, "CEC:     No VPD entry in IO KID !\n");
     367                 :           0 :                 return;
     368                 :             :         }
     369                 :             : 
     370                 :             :         /* Grab LX load info */
     371                 :           1 :         io_get_lx_info(kwvpd, kwvpd_sz, 0, dt_root);
     372                 :             : }
     373                 :             : 
     374                 :             : /*
     375                 :             :  * Assumptions:
     376                 :             :  *
     377                 :             :  * a) the IOSLOT index is the hub ID -CHECK
     378                 :             :  *
     379                 :             :  */
     380                 :             : 
     381                 :             : static struct dt_node *dt_slots;
     382                 :             : 
     383                 :           0 : static void add_i2c_link(struct dt_node *node, const char *link_name,
     384                 :             :                         u32 i2c_link)
     385                 :             : {
     386                 :             :         /* FIXME: Do something not shit */
     387                 :           0 :         dt_add_property_cells(node, link_name, i2c_link);
     388                 :           0 : }
     389                 :             : 
     390                 :             : /*
     391                 :             :  * the root of the slots node has #address-cells = 2, <hub-index, phb-index>
     392                 :             :  * can we ditch hub-index?
     393                 :             :  */
     394                 :             : 
     395                 :             : 
     396                 :           0 : static const struct slot_map_details *find_slot_details(
     397                 :             :                 const struct HDIF_common_hdr *ioslot, int entry)
     398                 :             : {
     399                 :           0 :         const struct slot_map_details *details = NULL;
     400                 :             :         const struct HDIF_array_hdr *arr;
     401                 :             :         unsigned int i;
     402                 :             : 
     403                 :           0 :         arr = HDIF_get_iarray(ioslot, IOSLOT_IDATA_DETAILS, NULL);
     404                 :           0 :         HDIF_iarray_for_each(arr, i, details)
     405                 :           0 :                 if (be16_to_cpu(details->entry) == entry)
     406                 :           0 :                         break;
     407                 :             : 
     408                 :           0 :         return details;
     409                 :             : }
     410                 :             : 
     411                 :           0 : static void parse_slot_details(struct dt_node *slot,
     412                 :             :                 const struct slot_map_details *details)
     413                 :             : {
     414                 :             :         u32 slot_caps;
     415                 :             : 
     416                 :             :         /*
     417                 :             :          * generic slot options
     418                 :             :          */
     419                 :             : 
     420                 :           0 :         dt_add_property_cells(slot, "max-power",
     421                 :             :                 be16_to_cpu(details->max_power));
     422                 :             : 
     423                 :           0 :         if (details->perst_ctl_type == SLOT_PERST_PHB_OR_SW)
     424                 :           0 :                 dt_add_property(slot, "pci-perst", NULL, 0);
     425                 :           0 :         else if (details->perst_ctl_type == SLOT_PERST_SW_GPIO)
     426                 :           0 :                 dt_add_property_cells(slot, "gpio-perst", details->perst_gpio);
     427                 :             : 
     428                 :           0 :         if (details->presence_det_type == SLOT_PRESENCE_PCI)
     429                 :           0 :                 dt_add_property(slot, "pci-presence-detect", NULL, 0);
     430                 :             : 
     431                 :             :         /*
     432                 :             :          * specific slot capabilities
     433                 :             :          */
     434                 :           0 :         slot_caps = be32_to_cpu(details->slot_caps);
     435                 :             : 
     436                 :           0 :         if (slot_caps & SLOT_CAP_LSI)
     437                 :           0 :                 dt_add_property(slot, "lsi", NULL, 0);
     438                 :             : 
     439                 :           0 :         if (slot_caps & SLOT_CAP_CAPI) {
     440                 :             :                 /* XXX: should we be more specific here?
     441                 :             :                  *
     442                 :             :                  * Also we should double check that this slot
     443                 :             :                  * is a root connected slot.
     444                 :             :                  */
     445                 :           0 :                 dt_add_property(slot, "capi", NULL, 0);
     446                 :             :         }
     447                 :             : 
     448                 :           0 :         if (slot_caps & SLOT_CAP_CCARD) {
     449                 :           0 :                 dt_add_property(slot, "cable-card", NULL, 0);
     450                 :             : 
     451                 :           0 :                 if (details->presence_det_type == SLOT_PRESENCE_I2C)
     452                 :           0 :                         add_i2c_link(slot, "i2c-presence-detect",
     453                 :           0 :                                 be32_to_cpu(details->i2c_cable_card));
     454                 :             :         }
     455                 :             : 
     456                 :           0 :         if (slot_caps & SLOT_CAP_HOTPLUG) {
     457                 :           0 :                 dt_add_property(slot, "hotplug", NULL, 0);
     458                 :             : 
     459                 :             :                 /*
     460                 :             :                  * Power control should only exist when the slot is hotplug
     461                 :             :                  * capable
     462                 :             :                  */
     463                 :           0 :                 if (details->power_ctrl_type == SLOT_PWR_I2C)
     464                 :           0 :                         add_i2c_link(slot, "i2c-power-ctrl",
     465                 :           0 :                                 be32_to_cpu(details->i2c_power_ctl));
     466                 :             :         }
     467                 :             : 
     468                 :             :         /*
     469                 :             :          * NB: Additional NVLink specific info is added to this node
     470                 :             :          *     when the SMP Link structures are parsed later on.
     471                 :             :          */
     472                 :           0 :         if (slot_caps & SLOT_CAP_NVLINK)
     473                 :           0 :                 dt_add_property(slot, "nvlink", NULL, 0);
     474                 :           0 : }
     475                 :             : 
     476                 :           0 : struct dt_node *find_slot_entry_node(struct dt_node *root, u32 entry_id)
     477                 :             : {
     478                 :             :         struct dt_node *node;
     479                 :             : 
     480                 :           0 :         for (node = dt_first(root); node; node = dt_next(root, node)) {
     481                 :           0 :                 if (!dt_has_node_property(node, DT_PRIVATE "entry_id", NULL))
     482                 :           0 :                         continue;
     483                 :             : 
     484                 :           0 :                 if (dt_prop_get_u32(node, DT_PRIVATE "entry_id") == entry_id)
     485                 :           0 :                         return node;
     486                 :             :         }
     487                 :             : 
     488                 :           0 :         return NULL;
     489                 :             : }
     490                 :             : 
     491                 :             : /*
     492                 :             :  * The internal HDAT representation of the various types of slot is kinda
     493                 :             :  * dumb, translate it into something more sensible
     494                 :             :  */
     495                 :             : enum slot_types {
     496                 :             :         st_root,
     497                 :             :         st_slot,
     498                 :             :         st_rc_slot,
     499                 :             :         st_sw_upstream,
     500                 :             :         st_sw_downstream,
     501                 :             :         st_builtin
     502                 :             : };
     503                 :             : 
     504                 :           0 : static const char *st_name(enum slot_types type)
     505                 :             : {
     506                 :           0 :         switch(type) {
     507                 :           0 :         case st_root:           return "root-complex";
     508                 :           0 :         case st_slot:           return "pluggable";
     509                 :           0 :         case st_rc_slot:        return "pluggable"; /* differentiate? */
     510                 :           0 :         case st_sw_upstream:    return "switch-up";
     511                 :           0 :         case st_sw_downstream:  return "switch-down";
     512                 :           0 :         case st_builtin:        return "builtin";
     513                 :             :         }
     514                 :             : 
     515                 :           0 :         return "(none)";
     516                 :             : }
     517                 :             : 
     518                 :           0 : static enum slot_types xlate_type(uint8_t type, u32 features)
     519                 :             : {
     520                 :           0 :         bool is_slot = features & SLOT_FEAT_SLOT;
     521                 :             : 
     522                 :           0 :         switch (type) {
     523                 :           0 :         case SLOT_TYPE_ROOT_COMPLEX:
     524                 :           0 :                 return is_slot ? st_rc_slot : st_root;
     525                 :           0 :         case SLOT_TYPE_BUILTIN:
     526                 :           0 :                 return st_builtin;
     527                 :           0 :         case SLOT_TYPE_SWITCH_UP:
     528                 :           0 :                 return st_sw_upstream;
     529                 :           0 :         case SLOT_TYPE_SWITCH_DOWN:
     530                 :           0 :                 return is_slot ? st_slot : st_sw_downstream;
     531                 :             :         }
     532                 :             : 
     533                 :           0 :         return -1; /* shouldn't happen */
     534                 :             : }
     535                 :             : 
     536                 :           0 : static bool is_port(struct dt_node *n)
     537                 :             : {
     538                 :             :         //return dt_node_is_compatible(n, "compatible", "ibm,pcie-port");
     539                 :           0 :         return dt_node_is_compatible(n, "ibm,pcie-port");
     540                 :             : }
     541                 :             : 
     542                 :             : /* this only works inside parse_one_ioslot() */
     543                 :             : #define SM_LOG(level, fmt, ...) \
     544                 :             :         prlog(level, "SLOTMAP: %x:%d:%d " \
     545                 :             :                 fmt, /* user input */ \
     546                 :             :                 chip_id, entry->phb_index, eid, \
     547                 :             :                 ##__VA_ARGS__ /* user args */)
     548                 :             : 
     549                 :             : #define SM_ERR(fmt, ...) SM_LOG(PR_ERR, fmt, ##__VA_ARGS__)
     550                 :             : #define SM_DBG(fmt, ...) SM_LOG(PR_DEBUG, fmt, ##__VA_ARGS__)
     551                 :             : 
     552                 :           0 : static void parse_one_slot(const struct slot_map_entry *entry,
     553                 :             :                 const struct slot_map_details *details, int chip_id)
     554                 :             : {
     555                 :           0 :         struct dt_node *node, *parent = NULL;
     556                 :             :         u16 eid, pid, vid, did;
     557                 :             :         u32 flags;
     558                 :             :         int type;
     559                 :             : 
     560                 :           0 :         flags = be32_to_cpu(entry->features);
     561                 :           0 :         type = xlate_type(entry->type, flags);
     562                 :             : 
     563                 :           0 :         eid = be16_to_cpu(entry->entry_id);
     564                 :           0 :         pid = be16_to_cpu(entry->parent_id);
     565                 :             : 
     566                 :           0 :         SM_DBG("%s - eid = %d, pid = %d, name = %8s\n",
     567                 :             :                 st_name(type), eid, pid,
     568                 :             :                 strnlen(entry->name, 8) ? entry->name : "");
     569                 :             : 
     570                 :             :         /* empty slot, ignore it */
     571                 :           0 :         if (eid == 0x0 && pid == 0x0)
     572                 :           0 :                 return;
     573                 :             : 
     574                 :           0 :         if (type != st_root && type != st_rc_slot) {
     575                 :           0 :                 parent = find_slot_entry_node(dt_slots, pid);
     576                 :           0 :                 if (!parent) {
     577                 :           0 :                         SM_ERR("Unable to find node for parent slot (id = %d)\n",
     578                 :             :                                 pid);
     579                 :           0 :                         return;
     580                 :             :                 }
     581                 :             :         }
     582                 :             : 
     583                 :           0 :         switch (type) {
     584                 :           0 :         case st_root:
     585                 :             :         case st_rc_slot:
     586                 :           0 :                 node = dt_new_2addr(dt_slots, "root-complex",
     587                 :           0 :                                                 chip_id, entry->phb_index);
     588                 :           0 :                 if (!node) {
     589                 :           0 :                         SM_ERR("Couldn't add DT node\n");
     590                 :           0 :                         return;
     591                 :             :                 }
     592                 :           0 :                 dt_add_property_cells(node, "reg", chip_id, entry->phb_index);
     593                 :           0 :                 dt_add_property_cells(node, "#address-cells", 2);
     594                 :           0 :                 dt_add_property_cells(node, "#size-cells", 0);
     595                 :           0 :                 dt_add_property_strings(node, "compatible",
     596                 :             :                                 "ibm,pcie-port", "ibm,pcie-root-port");
     597                 :           0 :                 dt_add_property_cells(node, "ibm,chip-id", chip_id);
     598                 :           0 :                 parent = node;
     599                 :             : 
     600                 :             :                 /*
     601                 :             :                  * The representation of slots attached directly to the
     602                 :             :                  * root complex is a bit wierd. If this is just a root
     603                 :             :                  * complex then stop here, otherwise fall through to create
     604                 :             :                  * the slot node.
     605                 :             :                  */
     606                 :           0 :                 if (type == st_root)
     607                 :           0 :                         break;
     608                 :             : 
     609                 :             :                 /* fallthrough*/
     610                 :             :         case st_sw_upstream:
     611                 :             :         case st_builtin:
     612                 :             :         case st_slot:
     613                 :           0 :                 if (!is_port(parent)) {
     614                 :           0 :                         SM_ERR("%s connected to %s (%d), should be %s or %s!\n",
     615                 :             :                                 st_name(type), parent->name, pid,
     616                 :             :                                 st_name(st_root), st_name(st_sw_downstream));
     617                 :           0 :                         return;
     618                 :             :                 }
     619                 :             : 
     620                 :           0 :                 vid = (be32_to_cpu(entry->vendor_id) & 0xffff);
     621                 :           0 :                 did = (be32_to_cpu(entry->device_id) & 0xffff);
     622                 :             : 
     623                 :           0 :                 prlog(PR_DEBUG, "Found %s slot with %x:%x\n",
     624                 :             :                         st_name(type), vid, did);
     625                 :             : 
     626                 :             :                 /* The VID:DID is only meaningful for builtins and switches */
     627                 :           0 :                 if (type == st_sw_upstream && vid && did) {
     628                 :           0 :                         node = dt_new_2addr(parent, st_name(type), vid, did);
     629                 :           0 :                         dt_add_property_cells(node, "reg", vid, did);
     630                 :             :                 } else {
     631                 :             :                         /*
     632                 :             :                          * If we get no vdid then create a "wildcard" slot
     633                 :             :                          * that matches any device
     634                 :             :                          */
     635                 :           0 :                         node = dt_new(parent, st_name(type));
     636                 :             :                 }
     637                 :             : 
     638                 :           0 :                 if (type == st_sw_upstream) {
     639                 :           0 :                         dt_add_property_cells(node, "#address-cells", 1);
     640                 :           0 :                         dt_add_property_cells(node, "#size-cells", 0);
     641                 :           0 :                         dt_add_property_cells(node, "upstream-port",
     642                 :             :                                         entry->up_port);
     643                 :             :                 }
     644                 :           0 :                 break;
     645                 :             : 
     646                 :           0 :         case st_sw_downstream: /* slot connected to switch output */
     647                 :           0 :                 node = dt_new_addr(parent, "down-port", entry->down_port);
     648                 :           0 :                 dt_add_property_strings(node, "compatible",
     649                 :             :                                 "ibm,pcie-port");
     650                 :           0 :                 dt_add_property_cells(node, "reg", entry->down_port);
     651                 :             : 
     652                 :           0 :                 break;
     653                 :             : 
     654                 :           0 :         default:
     655                 :           0 :                 SM_ERR("Unknown slot map type %x\n", entry->type);
     656                 :           0 :                 return;
     657                 :             :         }
     658                 :             : 
     659                 :             :         /*
     660                 :             :          * Now add any generic slot map properties.
     661                 :             :          */
     662                 :             : 
     663                 :             :         /* private since we don't want hdat stuff leaking */
     664                 :           0 :         dt_add_property_cells(node, DT_PRIVATE "entry_id", eid);
     665                 :             : 
     666                 :           0 :         if (entry->mrw_slot_id)
     667                 :           0 :                 dt_add_property_cells(node, "mrw-slot-id",
     668                 :             :                                 be16_to_cpu(entry->mrw_slot_id));
     669                 :             : 
     670                 :           0 :         if (entry->lane_mask)
     671                 :           0 :                 dt_add_property_cells(node, "lane-mask",
     672                 :             :                                 be16_to_cpu(entry->lane_mask));
     673                 :             : 
     674                 :             :         /* what is the difference between this and the lane reverse? */
     675                 :           0 :         if (entry->lane_reverse)
     676                 :           0 :                 dt_add_property_cells(node, "lanes-reversed",
     677                 :             :                                 be16_to_cpu(entry->lane_reverse));
     678                 :             : 
     679                 :           0 :         if (strnlen(entry->name, sizeof(entry->name))) {
     680                 :             :                 /*
     681                 :             :                  * HACK: On some platforms (witherspoon) the slot label is
     682                 :             :                  * applied to the device rather than the pcie downstream port
     683                 :             :                  * that has the slot under it. Hack around this by moving the
     684                 :             :                  * slot label up if the parent port doesn't have one.
     685                 :             :                  */
     686                 :           0 :                 if (dt_node_is_compatible(node->parent, "ibm,pcie-port") &&
     687                 :           0 :                     !dt_find_property(node->parent, "ibm,slot-label")) {
     688                 :           0 :                         dt_add_property_nstr(node->parent, "ibm,slot-label",
     689                 :           0 :                                         entry->name, sizeof(entry->name));
     690                 :             :                 }
     691                 :             : 
     692                 :           0 :                 dt_add_property_nstr(node, "ibm,slot-label",
     693                 :           0 :                                 entry->name, sizeof(entry->name));
     694                 :             :         }
     695                 :             : 
     696                 :           0 :         if (entry->type == st_slot || entry->type == st_rc_slot)
     697                 :           0 :                 dt_add_property(node, "ibm,pluggable", NULL, 0);
     698                 :             : 
     699                 :           0 :         if (details)
     700                 :           0 :                 parse_slot_details(node, details);
     701                 :             : }
     702                 :             : 
     703                 :             : /*
     704                 :             :  * Under the IOHUB structure we have and idata array describing
     705                 :             :  * the PHBs under each chip. The IOHUB structure also has a child
     706                 :             :  * array called IOSLOT which describes slot map. The i`th element
     707                 :             :  * of the IOSLOT array corresponds to the slot map of the i`th
     708                 :             :  * element of the iohubs idata array.
     709                 :             :  *
     710                 :             :  * Probably.
     711                 :             :  *
     712                 :             :  * Furthermore, arrayarrayarrayarrayarray.
     713                 :             :  */
     714                 :             : 
     715                 :           0 : static struct dt_node *get_slot_node(void)
     716                 :             : {
     717                 :           0 :         struct dt_node *slots = dt_find_by_name(dt_root, "ibm,pcie-slots");
     718                 :             : 
     719                 :           0 :         if (!slots) {
     720                 :           0 :                 slots = dt_new(dt_root, "ibm,pcie-slots");
     721                 :           0 :                 dt_add_property_cells(slots, "#address-cells", 2);
     722                 :           0 :                 dt_add_property_cells(slots, "#size-cells", 0);
     723                 :             :         }
     724                 :             : 
     725                 :           0 :         return slots;
     726                 :             : }
     727                 :             : 
     728                 :           2 : static void io_parse_slots(const struct HDIF_common_hdr *sp_iohubs, int hub_id)
     729                 :             : {
     730                 :             :         const struct HDIF_child_ptr *ioslot_arr;
     731                 :             :         const struct HDIF_array_hdr *entry_arr;
     732                 :             :         const struct HDIF_common_hdr *ioslot;
     733                 :             :         const struct slot_map_entry *entry;
     734                 :             :         unsigned int i, count;
     735                 :             : 
     736                 :           2 :         if (be16_to_cpu(sp_iohubs->child_count) <= CECHUB_CHILD_IOSLOTS)
     737                 :           2 :                 return;
     738                 :             : 
     739                 :           0 :         ioslot_arr = HDIF_child_arr(sp_iohubs, CECHUB_CHILD_IOSLOTS);
     740                 :           0 :         if (!ioslot_arr)
     741                 :           0 :                 return;
     742                 :             : 
     743                 :           0 :         count = be32_to_cpu(ioslot_arr->count); /* should only be 1 */
     744                 :           0 :         if (!count)
     745                 :           0 :                 return;
     746                 :             : 
     747                 :           0 :         dt_slots = get_slot_node();
     748                 :             : 
     749                 :           0 :         prlog(PR_DEBUG, "CEC: Found slot map for IOHUB %d\n", hub_id);
     750                 :           0 :         if (count > 1)
     751                 :           0 :                 prerror("CEC: Multiple IOSLOTs found for IO HUB %d\n", hub_id);
     752                 :             : 
     753                 :           0 :         ioslot = HDIF_child(sp_iohubs, ioslot_arr, 0, "IOSLOT");
     754                 :           0 :         if (!ioslot)
     755                 :           0 :                 return;
     756                 :             : 
     757                 :           0 :         entry_arr = HDIF_get_iarray(ioslot, IOSLOT_IDATA_SLOTMAP, NULL);
     758                 :           0 :         HDIF_iarray_for_each(entry_arr, i, entry) {
     759                 :             :                 const struct slot_map_details *details;
     760                 :             : 
     761                 :           0 :                 details = find_slot_details(ioslot,
     762                 :           0 :                                 be16_to_cpu(entry->entry_id));
     763                 :           0 :                 parse_one_slot(entry, details, hub_id);
     764                 :             :         }
     765                 :             : }
     766                 :             : 
     767                 :           1 : static void io_parse_fru(const void *sp_iohubs)
     768                 :             : {
     769                 :             :         unsigned int i;
     770                 :             :         int count;
     771                 :             : 
     772                 :           1 :         count = HDIF_get_iarray_size(sp_iohubs, CECHUB_FRU_IO_HUBS);
     773                 :           1 :         if (count < 1) {
     774                 :           0 :                 prerror("CEC: IO FRU with no chips !\n");
     775                 :           0 :                 return;
     776                 :             :         }
     777                 :             : 
     778                 :           1 :         prlog(PR_INFO, "CEC:   %d chips in FRU\n", count);
     779                 :             : 
     780                 :             :         /* Iterate IO hub array */
     781                 :           3 :         for (i = 0; i < count; i++) {
     782                 :             :                 const struct cechub_io_hub *hub;
     783                 :             :                 unsigned int size, hub_id;
     784                 :             :                 uint32_t chip_id;
     785                 :             : 
     786                 :           2 :                 hub = HDIF_get_iarray_item(sp_iohubs, CECHUB_FRU_IO_HUBS,
     787                 :             :                                            i, &size);
     788                 :           2 :                 if (!hub || size < CECHUB_IOHUB_MIN_SIZE) {
     789                 :           0 :                         prerror("CEC:     IO-HUB Chip %d bad idata\n", i);
     790                 :           0 :                         continue;
     791                 :             :                 }
     792                 :             : 
     793                 :           2 :                 switch (hub->flags & CECHUB_HUB_FLAG_STATE_MASK) {
     794                 :           2 :                 case CECHUB_HUB_FLAG_STATE_OK:
     795                 :           2 :                         prlog(PR_DEBUG, "CEC:   IO Hub Chip #%d OK\n", i);
     796                 :           2 :                         break;
     797                 :           0 :                 case CECHUB_HUB_FLAG_STATE_FAILURES:
     798                 :           0 :                         prlog(PR_WARNING, "CEC:   IO Hub Chip #%d OK"
     799                 :             :                               " with failures\n", i);
     800                 :           0 :                         break;
     801                 :           0 :                 case CECHUB_HUB_FLAG_STATE_NOT_INST:
     802                 :           0 :                         prlog(PR_DEBUG, "CEC:   IO Hub Chip #%d"
     803                 :             :                               " Not installed\n", i);
     804                 :           0 :                         continue;
     805                 :           0 :                 case CECHUB_HUB_FLAG_STATE_UNUSABLE:
     806                 :           0 :                         prlog(PR_DEBUG, "CEC:   IO Hub Chip #%d Unusable\n", i);
     807                 :           0 :                         continue;
     808                 :             :                 }
     809                 :             : 
     810                 :           2 :                 hub_id = be16_to_cpu(hub->iohub_id);
     811                 :             : 
     812                 :             :                 /* GX BAR assignment */
     813                 :           2 :                 prlog(PR_DEBUG, "CEC:   PChip: %d HUB ID: %04x [EC=0x%x]"
     814                 :             :                       " Hub#=%d)\n",
     815                 :             :                       be32_to_cpu(hub->proc_chip_id), hub_id,
     816                 :             :                       be32_to_cpu(hub->ec_level), be16_to_cpu(hub->hub_num));
     817                 :             : 
     818                 :           2 :                 switch(hub_id) {
     819                 :           2 :                 case CECHUB_HUB_MURANO:
     820                 :             :                 case CECHUB_HUB_MURANO_SEGU:
     821                 :           2 :                         prlog(PR_INFO, "CEC:     Murano !\n");
     822                 :           2 :                         io_add_p8(hub, sp_iohubs);
     823                 :           2 :                         break;
     824                 :           0 :                 case CECHUB_HUB_VENICE_WYATT:
     825                 :           0 :                         prlog(PR_INFO, "CEC:     Venice !\n");
     826                 :           0 :                         io_add_p8(hub, sp_iohubs);
     827                 :           0 :                         break;
     828                 :           0 :                 case CECHUB_HUB_NIMBUS_SFORAZ:
     829                 :             :                 case CECHUB_HUB_NIMBUS_MONZA:
     830                 :             :                 case CECHUB_HUB_NIMBUS_LAGRANGE:
     831                 :           0 :                         prlog(PR_INFO, "CEC:     Nimbus !\n");
     832                 :           0 :                         io_add_p9(hub, sp_iohubs);
     833                 :           0 :                         break;
     834                 :           0 :                 case CECHUB_HUB_CUMULUS_DUOMO:
     835                 :           0 :                         prlog(PR_INFO, "CEC:     Cumulus !\n");
     836                 :           0 :                         io_add_p9(hub, sp_iohubs);
     837                 :           0 :                         break;
     838                 :           0 :                 case CECHUB_HUB_AXONE_HOPPER:
     839                 :           0 :                         prlog(PR_INFO, "CEC:     Axone !\n");
     840                 :           0 :                         io_add_p9(hub, sp_iohubs);
     841                 :           0 :                         break;
     842                 :           0 :                 case CECHUB_HUB_RAINIER:
     843                 :           0 :                         prlog(PR_INFO, "CEC:     Rainier !\n");
     844                 :           0 :                         io_add_p9(hub, sp_iohubs);
     845                 :           0 :                         break;
     846                 :           0 :                 case CECHUB_HUB_DENALI:
     847                 :           0 :                         prlog(PR_INFO, "CEC:     Denali !\n");
     848                 :           0 :                         io_add_p9(hub, sp_iohubs);
     849                 :           0 :                         break;
     850                 :           0 :                 default:
     851                 :           0 :                         prlog(PR_ERR, "CEC:     Hub ID 0x%04x unsupported !\n",
     852                 :             :                               hub_id);
     853                 :             :                 }
     854                 :             : 
     855                 :           2 :                 chip_id = pcid_to_chip_id(be32_to_cpu(hub->proc_chip_id));
     856                 :             : 
     857                 :             :                 /* parse the slot map if we have one */
     858                 :           2 :                 io_parse_slots(sp_iohubs, chip_id);
     859                 :             :         }
     860                 :             : 
     861                 :           1 :         if (proc_gen == proc_gen_p8 || proc_gen == proc_gen_p9 || proc_gen == proc_gen_p10)
     862                 :           1 :                 io_add_p8_cec_vpd(sp_iohubs);
     863                 :             : }
     864                 :             : 
     865                 :           1 : void io_parse(void)
     866                 :             : {
     867                 :             :         const struct HDIF_common_hdr *sp_iohubs;
     868                 :             :         unsigned int i, size;
     869                 :             : 
     870                 :             :         /* Look for IO Hubs */
     871                 :           1 :         if (!get_hdif(&spiras->ntuples.cec_iohub_fru, "IO HUB")) {
     872                 :           0 :                 prerror("CEC: Cannot locate IO Hub FRU data !\n");
     873                 :           0 :                 return;
     874                 :             :         }
     875                 :             : 
     876                 :             :         /*
     877                 :             :          * Note about LXRn numbering ...
     878                 :             :          *
     879                 :             :          * I can't completely make sense of what that is supposed to be, so
     880                 :             :          * for now, what we do is look for the first one we can find and
     881                 :             :          * increment it for each chip. Works for the machines I have here
     882                 :             :          */
     883                 :             : 
     884                 :           2 :         for_each_ntuple_idx(&spiras->ntuples.cec_iohub_fru, sp_iohubs, i,
     885                 :             :                             CECHUB_FRU_HDIF_SIG) {
     886                 :             :                 const struct cechub_hub_fru_id *fru_id_data;
     887                 :             :                 unsigned int type;
     888                 :             :                 static const char *typestr[] = {
     889                 :             :                         "Reservation",
     890                 :             :                         "Card",
     891                 :             :                         "CPU Card",
     892                 :             :                         "Backplane",
     893                 :             :                         "Backplane Extension"
     894                 :             :                 };
     895                 :           1 :                 fru_id_data = HDIF_get_idata(sp_iohubs, CECHUB_FRU_ID_DATA_AREA,
     896                 :             :                                              &size);
     897                 :           1 :                 if (!fru_id_data || size < sizeof(struct cechub_hub_fru_id)) {
     898                 :           0 :                         prerror("CEC: IO-HUB FRU %d, bad ID data\n", i);
     899                 :           0 :                         continue;
     900                 :             :                 }
     901                 :           1 :                 type = be32_to_cpu(fru_id_data->card_type);
     902                 :             : 
     903                 :           1 :                 prlog(PR_INFO, "CEC: HUB FRU %d is %s\n",
     904                 :             :                       i, type > 4 ? "Unknown" : typestr[type]);
     905                 :             : 
     906                 :             :                 /*
     907                 :             :                  * We currently only handle the backplane (Juno) and
     908                 :             :                  * processor FRU (P8 machines)
     909                 :             :                  */
     910                 :           1 :                 if (type != CECHUB_FRU_TYPE_CEC_BKPLANE &&
     911                 :             :                     type != CECHUB_FRU_TYPE_CPU_CARD) {
     912                 :           0 :                         prerror("CEC:   Unsupported type\n");
     913                 :           0 :                         continue;
     914                 :             :                 }
     915                 :             : 
     916                 :             :                 /* We don't support Hubs connected to pass-through ports */
     917                 :           1 :                 if (fru_id_data->flags & (CECHUB_FRU_FLAG_HEADLESS |
     918                 :             :                                           CECHUB_FRU_FLAG_PASSTHROUGH)) {
     919                 :           0 :                         prerror("CEC:   Headless or Passthrough unsupported\n");
     920                 :           0 :                         continue;
     921                 :             :                 }
     922                 :             : 
     923                 :             :                 /* Ok, we have a reasonable candidate */
     924                 :           1 :                 io_parse_fru(sp_iohubs);
     925                 :             :         }
     926                 :             : }
     927                 :             : 
        

Generated by: LCOV version 2.0-1