14df55fdeSJanie Lu /*
24df55fdeSJanie Lu * CDDL HEADER START
34df55fdeSJanie Lu *
44df55fdeSJanie Lu * The contents of this file are subject to the terms of the
54df55fdeSJanie Lu * Common Development and Distribution License (the "License").
64df55fdeSJanie Lu * You may not use this file except in compliance with the License.
74df55fdeSJanie Lu *
84df55fdeSJanie Lu * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94df55fdeSJanie Lu * or http://www.opensolaris.org/os/licensing.
104df55fdeSJanie Lu * See the License for the specific language governing permissions
114df55fdeSJanie Lu * and limitations under the License.
124df55fdeSJanie Lu *
134df55fdeSJanie Lu * When distributing Covered Code, include this CDDL HEADER in each
144df55fdeSJanie Lu * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154df55fdeSJanie Lu * If applicable, add the following below this CDDL HEADER, with the
164df55fdeSJanie Lu * fields enclosed by brackets "[]" replaced with your own identifying
174df55fdeSJanie Lu * information: Portions Copyright [yyyy] [name of copyright owner]
184df55fdeSJanie Lu *
194df55fdeSJanie Lu * CDDL HEADER END
204df55fdeSJanie Lu */
214df55fdeSJanie Lu
224df55fdeSJanie Lu /*
234f764f91SCheng Sean Ye * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*ffb64830SJordan Paige Hendricks * Copyright 2019 Joyent, Inc.
254df55fdeSJanie Lu */
264df55fdeSJanie Lu #include <strings.h>
274df55fdeSJanie Lu #include <fm/topo_hc.h>
284df55fdeSJanie Lu #include <sys/fm/util.h>
294df55fdeSJanie Lu #include <libxml/xpath.h>
304df55fdeSJanie Lu #include <libxml/parser.h>
314df55fdeSJanie Lu #include <libxml/xpathInternals.h>
324df55fdeSJanie Lu #include <libxml/tree.h>
334df55fdeSJanie Lu
344df55fdeSJanie Lu #include "fabric-xlate.h"
354df55fdeSJanie Lu
364df55fdeSJanie Lu #define HAS_PROP(node, name) xmlHasProp(node, (const xmlChar *)name)
374df55fdeSJanie Lu #define GET_PROP(node, name) ((char *)xmlGetProp(node, (const xmlChar *)name))
384df55fdeSJanie Lu #define FREE_PROP(prop) xmlFree((xmlChar *)prop)
394df55fdeSJanie Lu
404df55fdeSJanie Lu extern xmlXPathContextPtr fab_xpathCtx;
414df55fdeSJanie Lu
424df55fdeSJanie Lu /* ARGSUSED */
434df55fdeSJanie Lu int
fab_prep_basic_erpt(fmd_hdl_t * hdl,nvlist_t * nvl,nvlist_t * erpt,boolean_t isRC)444df55fdeSJanie Lu fab_prep_basic_erpt(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *erpt,
454df55fdeSJanie Lu boolean_t isRC)
464df55fdeSJanie Lu {
474df55fdeSJanie Lu uint64_t *now;
484df55fdeSJanie Lu uint64_t ena;
494df55fdeSJanie Lu uint_t nelem;
504df55fdeSJanie Lu nvlist_t *detector, *new_detector;
514df55fdeSJanie Lu char rcpath[255];
524df55fdeSJanie Lu int err = 0;
534df55fdeSJanie Lu
544df55fdeSJanie Lu /* Grab the tod, ena and detector(FMRI) */
554df55fdeSJanie Lu err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem);
564df55fdeSJanie Lu err |= nvlist_lookup_uint64(nvl, "ena", &ena);
574df55fdeSJanie Lu err |= nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector);
584df55fdeSJanie Lu if (err)
594df55fdeSJanie Lu return (err);
604df55fdeSJanie Lu
614df55fdeSJanie Lu /* Make a copy of the detector */
624df55fdeSJanie Lu err = nvlist_dup(detector, &new_detector, NV_UNIQUE_NAME);
634df55fdeSJanie Lu if (err)
644df55fdeSJanie Lu return (err);
654df55fdeSJanie Lu
664df55fdeSJanie Lu /* Copy the tod and ena to erpt */
674df55fdeSJanie Lu (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena);
684df55fdeSJanie Lu (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem);
694df55fdeSJanie Lu
704df55fdeSJanie Lu /*
714df55fdeSJanie Lu * Create the correct ROOT FMRI from PCIe leaf fabric ereports. Used
724df55fdeSJanie Lu * only by fab_prep_fake_rc_erpt. See the fab_pciex_fake_rc_erpt_tbl
734df55fdeSJanie Lu * comments for more information.
744df55fdeSJanie Lu */
754df55fdeSJanie Lu if (isRC && fab_get_rcpath(hdl, nvl, rcpath)) {
764df55fdeSJanie Lu /* Create the correct PCIe RC new_detector aka FMRI */
774df55fdeSJanie Lu (void) nvlist_remove(new_detector, FM_FMRI_DEV_PATH,
784df55fdeSJanie Lu DATA_TYPE_STRING);
794df55fdeSJanie Lu (void) nvlist_add_string(new_detector, FM_FMRI_DEV_PATH,
804df55fdeSJanie Lu rcpath);
814df55fdeSJanie Lu }
824df55fdeSJanie Lu
834df55fdeSJanie Lu /* Copy the FMRI to erpt */
844df55fdeSJanie Lu (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, new_detector);
854df55fdeSJanie Lu
864df55fdeSJanie Lu nvlist_free(new_detector);
874df55fdeSJanie Lu return (err);
884df55fdeSJanie Lu }
894df55fdeSJanie Lu
904df55fdeSJanie Lu void
fab_send_tgt_erpt(fmd_hdl_t * hdl,fab_data_t * data,const char * class,boolean_t isPrimary)914df55fdeSJanie Lu fab_send_tgt_erpt(fmd_hdl_t *hdl, fab_data_t *data, const char *class,
924df55fdeSJanie Lu boolean_t isPrimary)
934df55fdeSJanie Lu {
944df55fdeSJanie Lu nvlist_t *nvl = data->nvl;
954df55fdeSJanie Lu nvlist_t *erpt;
964df55fdeSJanie Lu char *fmri = NULL;
974df55fdeSJanie Lu uint32_t tgt_trans;
984df55fdeSJanie Lu uint64_t tgt_addr;
994df55fdeSJanie Lu uint16_t tgt_bdf;
1004df55fdeSJanie Lu
1014df55fdeSJanie Lu if (isPrimary) {
1024df55fdeSJanie Lu tgt_trans = data->pcie_ue_tgt_trans;
1034df55fdeSJanie Lu tgt_addr = data->pcie_ue_tgt_addr;
1044df55fdeSJanie Lu tgt_bdf = data->pcie_ue_tgt_bdf;
1054df55fdeSJanie Lu } else {
1064df55fdeSJanie Lu tgt_trans = data->pcie_sue_tgt_trans;
1074df55fdeSJanie Lu tgt_addr = data->pcie_sue_tgt_addr;
1084df55fdeSJanie Lu tgt_bdf = data->pcie_sue_tgt_bdf;
1094df55fdeSJanie Lu }
1104df55fdeSJanie Lu
1114df55fdeSJanie Lu fmd_hdl_debug(hdl, "Sending Target Ereport: "
1124df55fdeSJanie Lu "type 0x%x addr 0x%llx fltbdf 0x%x\n",
1134df55fdeSJanie Lu tgt_trans, tgt_addr, tgt_bdf);
1144df55fdeSJanie Lu
1154df55fdeSJanie Lu if (!tgt_trans)
1164df55fdeSJanie Lu return;
1174df55fdeSJanie Lu
1184df55fdeSJanie Lu if ((tgt_trans == PF_ADDR_PIO) && tgt_addr)
1194df55fdeSJanie Lu fmri = fab_find_addr(hdl, nvl, tgt_addr);
1204df55fdeSJanie Lu else if ((tgt_trans == PF_ADDR_CFG || (tgt_trans == PF_ADDR_DMA)) &&
1214df55fdeSJanie Lu tgt_bdf)
1224df55fdeSJanie Lu fmri = fab_find_bdf(hdl, nvl, tgt_bdf);
1234df55fdeSJanie Lu
1244df55fdeSJanie Lu if (fmri) {
1254df55fdeSJanie Lu uint64_t *now;
1264df55fdeSJanie Lu uint64_t ena;
1274df55fdeSJanie Lu uint_t nelem;
1284df55fdeSJanie Lu nvlist_t *detector;
1294df55fdeSJanie Lu int err = 0;
1304df55fdeSJanie Lu
1314df55fdeSJanie Lu /* Allocate space for new erpt */
1324df55fdeSJanie Lu if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
1334df55fdeSJanie Lu goto done;
1344df55fdeSJanie Lu
1354df55fdeSJanie Lu /* Generate the target ereport class */
1364df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
1374df55fdeSJanie Lu PCI_ERROR_SUBCLASS, class);
1384df55fdeSJanie Lu (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
1394df55fdeSJanie Lu
1404df55fdeSJanie Lu /* Grab the tod, ena and detector(FMRI) */
1414df55fdeSJanie Lu err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem);
1424df55fdeSJanie Lu err |= nvlist_lookup_uint64(nvl, "ena", &ena);
1434df55fdeSJanie Lu
1444df55fdeSJanie Lu /* Copy the tod and ena to erpt */
1454df55fdeSJanie Lu (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena);
1464df55fdeSJanie Lu (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem);
1474df55fdeSJanie Lu
1484df55fdeSJanie Lu /* Create the correct FMRI */
1494df55fdeSJanie Lu if (nvlist_alloc(&detector, NV_UNIQUE_NAME, 0) != 0) {
1504df55fdeSJanie Lu nvlist_free(erpt);
1514df55fdeSJanie Lu goto done;
1524df55fdeSJanie Lu }
1534df55fdeSJanie Lu (void) nvlist_add_uint8(detector, FM_VERSION,
1544df55fdeSJanie Lu FM_DEV_SCHEME_VERSION);
1554df55fdeSJanie Lu (void) nvlist_add_string(detector, FM_FMRI_SCHEME,
1564df55fdeSJanie Lu FM_FMRI_SCHEME_DEV);
1574df55fdeSJanie Lu (void) nvlist_add_string(detector, FM_FMRI_DEV_PATH, fmri);
1584df55fdeSJanie Lu (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, detector);
1594df55fdeSJanie Lu nvlist_free(detector);
1604df55fdeSJanie Lu
1614df55fdeSJanie Lu /* Add the address payload */
1624df55fdeSJanie Lu (void) nvlist_add_uint64(erpt, PCI_PA, tgt_addr);
1634df55fdeSJanie Lu
1644df55fdeSJanie Lu fmd_hdl_debug(hdl, "Sending target ereport: %s 0x%x\n",
1654df55fdeSJanie Lu fab_buf, tgt_addr);
1664df55fdeSJanie Lu fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
1674df55fdeSJanie Lu if (fmd_xprt_error(hdl, fab_fmd_xprt))
1684df55fdeSJanie Lu goto done;
1694df55fdeSJanie Lu fmd_hdl_strfree(hdl, fmri);
1704df55fdeSJanie Lu } else {
1714df55fdeSJanie Lu fmd_hdl_debug(hdl,
1724df55fdeSJanie Lu "Cannot find Target FMRI addr:0x%llx bdf 0x%x\n",
1734df55fdeSJanie Lu tgt_addr, tgt_bdf);
1744df55fdeSJanie Lu }
1754df55fdeSJanie Lu
1764df55fdeSJanie Lu return;
1774df55fdeSJanie Lu done:
1784df55fdeSJanie Lu if (fmri)
1794df55fdeSJanie Lu xmlFree(fmri);
1804df55fdeSJanie Lu fmd_hdl_debug(hdl, "Failed to send Target PCI ereport\n");
1814df55fdeSJanie Lu }
1824df55fdeSJanie Lu
1834df55fdeSJanie Lu void
fab_send_erpt(fmd_hdl_t * hdl,fab_data_t * data,fab_err_tbl_t * tbl)1844df55fdeSJanie Lu fab_send_erpt(fmd_hdl_t *hdl, fab_data_t *data, fab_err_tbl_t *tbl)
1854df55fdeSJanie Lu {
1864df55fdeSJanie Lu fab_erpt_tbl_t *erpt_tbl, *entry;
1874df55fdeSJanie Lu nvlist_t *erpt;
1884df55fdeSJanie Lu uint32_t reg;
189*ffb64830SJordan Paige Hendricks int err;
1904df55fdeSJanie Lu
1914df55fdeSJanie Lu erpt_tbl = tbl->erpt_tbl;
1924df55fdeSJanie Lu if (tbl->reg_size == 16) {
1934df55fdeSJanie Lu reg = (uint32_t)*((uint16_t *)
1944df55fdeSJanie Lu ((uint32_t)data + tbl->reg_offset));
1954df55fdeSJanie Lu } else {
1964df55fdeSJanie Lu reg = *((uint32_t *)((uint32_t)data + tbl->reg_offset));
1974df55fdeSJanie Lu }
1984df55fdeSJanie Lu
1994df55fdeSJanie Lu for (entry = erpt_tbl; entry->err_class; entry++) {
2004df55fdeSJanie Lu if (!(reg & entry->reg_bit))
2014df55fdeSJanie Lu continue;
2024df55fdeSJanie Lu
2034df55fdeSJanie Lu if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
2044df55fdeSJanie Lu goto done;
205*ffb64830SJordan Paige Hendricks
206*ffb64830SJordan Paige Hendricks err = tbl->fab_prep(hdl, data, erpt, entry);
207*ffb64830SJordan Paige Hendricks if (err != 0 && err != PF_EREPORT_IGNORE) {
2084df55fdeSJanie Lu fmd_hdl_debug(hdl, "Prepping ereport failed: "
2094df55fdeSJanie Lu "class = %s\n", entry->err_class);
2104df55fdeSJanie Lu nvlist_free(erpt);
2114df55fdeSJanie Lu continue;
2124df55fdeSJanie Lu }
2134df55fdeSJanie Lu
214036ec191SCheng Sean Ye if (data->pcie_rp_send_all) {
215036ec191SCheng Sean Ye fab_send_erpt_all_rps(hdl, erpt);
216036ec191SCheng Sean Ye nvlist_free(erpt);
217036ec191SCheng Sean Ye return;
218036ec191SCheng Sean Ye }
219036ec191SCheng Sean Ye
2204df55fdeSJanie Lu fmd_hdl_debug(hdl, "Sending ereport: %s 0x%x\n", fab_buf, reg);
2214df55fdeSJanie Lu fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
2224df55fdeSJanie Lu if (fmd_xprt_error(hdl, fab_fmd_xprt)) {
2234df55fdeSJanie Lu fmd_hdl_debug(hdl, "Failed to send PCI ereport\n");
2244df55fdeSJanie Lu return;
2254df55fdeSJanie Lu }
2264df55fdeSJanie Lu }
2274df55fdeSJanie Lu
2284df55fdeSJanie Lu return;
2294df55fdeSJanie Lu done:
2304df55fdeSJanie Lu fmd_hdl_debug(hdl, "Failed to send PCI ereport\n");
2314df55fdeSJanie Lu }
2324df55fdeSJanie Lu
2334df55fdeSJanie Lu char *
fab_xpath_query(fmd_hdl_t * hdl,const char * query)2344df55fdeSJanie Lu fab_xpath_query(fmd_hdl_t *hdl, const char *query)
2354df55fdeSJanie Lu {
2364df55fdeSJanie Lu xmlXPathObjectPtr xpathObj;
2374df55fdeSJanie Lu xmlNodeSetPtr nodes;
2384df55fdeSJanie Lu char *temp, *res;
2394df55fdeSJanie Lu
2404df55fdeSJanie Lu fmd_hdl_debug(hdl, "xpathObj query %s\n", query);
2414df55fdeSJanie Lu
2424df55fdeSJanie Lu xpathObj = xmlXPathEvalExpression((const xmlChar *)query,
2434df55fdeSJanie Lu fab_xpathCtx);
2444df55fdeSJanie Lu
2454df55fdeSJanie Lu if (xpathObj == NULL)
2464df55fdeSJanie Lu return (NULL);
2474df55fdeSJanie Lu
2484df55fdeSJanie Lu fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj,
2494df55fdeSJanie Lu xpathObj->type);
2504df55fdeSJanie Lu nodes = xpathObj->nodesetval;
2514df55fdeSJanie Lu
2524df55fdeSJanie Lu if (nodes) {
2534df55fdeSJanie Lu temp = (char *)xmlNodeGetContent(nodes->nodeTab[0]);
2544df55fdeSJanie Lu fmd_hdl_debug(hdl, "query result: %s\n", temp);
2554df55fdeSJanie Lu res = fmd_hdl_strdup(hdl, temp, FMD_SLEEP);
2564df55fdeSJanie Lu xmlFree(temp);
2574df55fdeSJanie Lu xmlXPathFreeObject(xpathObj);
2584df55fdeSJanie Lu return (res);
2594df55fdeSJanie Lu }
2604df55fdeSJanie Lu xmlXPathFreeObject(xpathObj);
2614df55fdeSJanie Lu return (NULL);
2624df55fdeSJanie Lu }
2634df55fdeSJanie Lu
2644df55fdeSJanie Lu #define FAB_HC2DEV_QUERY_SIZE_MIN 160
2654df55fdeSJanie Lu #define FAB_HC2DEV_QUERY_SIZE(sz) \
2664df55fdeSJanie Lu ((sz + FAB_HC2DEV_QUERY_SIZE_MIN) * sizeof (char))
2674df55fdeSJanie Lu
2684df55fdeSJanie Lu /*
2694df55fdeSJanie Lu * hc_path is in form of "/motherboard=0/hostbridge=0/pciexrc=0"
2704df55fdeSJanie Lu */
2714df55fdeSJanie Lu boolean_t
fab_hc2dev(fmd_hdl_t * hdl,const char * hc_path,char ** dev_path)2724df55fdeSJanie Lu fab_hc2dev(fmd_hdl_t *hdl, const char *hc_path, char **dev_path)
2734df55fdeSJanie Lu {
2744df55fdeSJanie Lu char *query;
2754df55fdeSJanie Lu uint_t len = FAB_HC2DEV_QUERY_SIZE_MIN + strlen(hc_path);
2764df55fdeSJanie Lu
2774df55fdeSJanie Lu query = fmd_hdl_alloc(hdl, len, FMD_SLEEP);
2784df55fdeSJanie Lu (void) snprintf(query, len, "//propval[@name='resource' and contains("
2794df55fdeSJanie Lu "substring(@value, string-length(@value) - %d + 1), '%s')]"
2804df55fdeSJanie Lu "/parent::*/following-sibling::*/propval[@name='dev']/@value",
2814df55fdeSJanie Lu strlen(hc_path) + 1, hc_path);
2824df55fdeSJanie Lu
2834df55fdeSJanie Lu *dev_path = fab_xpath_query(hdl, query);
2844df55fdeSJanie Lu
2854df55fdeSJanie Lu fmd_hdl_free(hdl, query, len);
2864df55fdeSJanie Lu
2874df55fdeSJanie Lu return (*dev_path != NULL);
2884df55fdeSJanie Lu }
2894df55fdeSJanie Lu
2904df55fdeSJanie Lu static boolean_t
fab_hc_path(fmd_hdl_t * hdl,nvlist_t * detector,char ** hcpath,size_t * lenp)2914df55fdeSJanie Lu fab_hc_path(fmd_hdl_t *hdl, nvlist_t *detector, char **hcpath, size_t *lenp)
2924df55fdeSJanie Lu {
2934df55fdeSJanie Lu char c, *name, *id, *buf;
2944df55fdeSJanie Lu uint_t i, size;
2954df55fdeSJanie Lu nvlist_t **hcl;
2964df55fdeSJanie Lu size_t len = 0, buf_size = 0;
2974df55fdeSJanie Lu
2984df55fdeSJanie Lu if (nvlist_lookup_nvlist_array(detector, FM_FMRI_HC_LIST, &hcl,
2994df55fdeSJanie Lu &size) != 0)
3004df55fdeSJanie Lu return (B_FALSE);
3014df55fdeSJanie Lu
3024df55fdeSJanie Lu for (i = 0; i < size; i++) {
3034df55fdeSJanie Lu if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name) != 0)
3044df55fdeSJanie Lu return (B_FALSE);
3054df55fdeSJanie Lu if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &id) != 0)
3064df55fdeSJanie Lu return (B_FALSE);
3074df55fdeSJanie Lu buf_size += snprintf(&c, 1, "/%s=%s", name, id);
3084df55fdeSJanie Lu }
3094df55fdeSJanie Lu
3104df55fdeSJanie Lu buf_size++;
3114df55fdeSJanie Lu buf = fmd_hdl_alloc(hdl, buf_size, FMD_SLEEP);
3124df55fdeSJanie Lu
3134df55fdeSJanie Lu for (i = 0; i < size; i++) {
3144df55fdeSJanie Lu (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name);
3154df55fdeSJanie Lu (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &id);
3164df55fdeSJanie Lu len += snprintf(buf + len, buf_size - len, "/%s=%s", name, id);
3174df55fdeSJanie Lu }
3184df55fdeSJanie Lu
3194df55fdeSJanie Lu *hcpath = buf;
3204df55fdeSJanie Lu *lenp = buf_size;
3214df55fdeSJanie Lu
3224df55fdeSJanie Lu return (B_TRUE);
3234df55fdeSJanie Lu }
3244df55fdeSJanie Lu
3254df55fdeSJanie Lu boolean_t
fab_hc2dev_nvl(fmd_hdl_t * hdl,nvlist_t * detector,char ** dev_path)3264df55fdeSJanie Lu fab_hc2dev_nvl(fmd_hdl_t *hdl, nvlist_t *detector, char **dev_path)
3274df55fdeSJanie Lu {
3284df55fdeSJanie Lu char *hcl;
3294df55fdeSJanie Lu size_t len;
3304df55fdeSJanie Lu
3314df55fdeSJanie Lu if (! fab_hc_path(hdl, detector, &hcl, &len))
3324df55fdeSJanie Lu return (B_FALSE);
3334df55fdeSJanie Lu
3344df55fdeSJanie Lu (void) fab_hc2dev(hdl, hcl, dev_path);
3354df55fdeSJanie Lu
3364df55fdeSJanie Lu fmd_hdl_free(hdl, hcl, len);
3374df55fdeSJanie Lu
3384df55fdeSJanie Lu return (*dev_path != NULL);
3394df55fdeSJanie Lu }
3404df55fdeSJanie Lu
3414df55fdeSJanie Lu boolean_t
fab_get_hcpath(fmd_hdl_t * hdl,nvlist_t * nvl,char ** hcpath,size_t * len)3424df55fdeSJanie Lu fab_get_hcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char **hcpath, size_t *len)
3434df55fdeSJanie Lu {
3444df55fdeSJanie Lu nvlist_t *detector;
3454df55fdeSJanie Lu char *scheme;
3464df55fdeSJanie Lu
3474df55fdeSJanie Lu if (nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector) != 0 ||
3484df55fdeSJanie Lu nvlist_lookup_string(detector, FM_FMRI_SCHEME, &scheme) != 0 ||
3494df55fdeSJanie Lu ! STRCMP(scheme, FM_FMRI_SCHEME_HC))
3504df55fdeSJanie Lu return (B_FALSE);
3514df55fdeSJanie Lu
3524df55fdeSJanie Lu return (fab_hc_path(hdl, detector, hcpath, len));
3534df55fdeSJanie Lu }
3544df55fdeSJanie Lu
3554df55fdeSJanie Lu char *
fab_find_rppath_by_df(fmd_hdl_t * hdl,nvlist_t * nvl,uint8_t df)3564df55fdeSJanie Lu fab_find_rppath_by_df(fmd_hdl_t *hdl, nvlist_t *nvl, uint8_t df)
3574df55fdeSJanie Lu {
3584df55fdeSJanie Lu char query[500];
3594df55fdeSJanie Lu char str[10];
3604df55fdeSJanie Lu char *hcpath;
3614df55fdeSJanie Lu size_t len;
3624df55fdeSJanie Lu
3634df55fdeSJanie Lu (void) snprintf(str, sizeof (str), "%0hhx", df);
3644df55fdeSJanie Lu
3654df55fdeSJanie Lu /*
3664df55fdeSJanie Lu * get the string form of the hc detector, eg
3674df55fdeSJanie Lu * /chassis=0/motherboard=0/hostbridge=0
3684df55fdeSJanie Lu */
3694df55fdeSJanie Lu if (!fab_get_hcpath(hdl, nvl, &hcpath, &len))
3704df55fdeSJanie Lu return (NULL);
3714df55fdeSJanie Lu
3724df55fdeSJanie Lu /*
3734df55fdeSJanie Lu * Explanation of the XSL XPATH Query
3744df55fdeSJanie Lu * Line 1: Look at all nodes with the node name "propval"
3754df55fdeSJanie Lu * Line 2: See if the "BDF" of the node matches DF
3764df55fdeSJanie Lu * Line 3-4: See if the the node is pciexrc
3774df55fdeSJanie Lu * Line 5-6: See if the "ASRU" contains root complex
3784df55fdeSJanie Lu * Line 7-8: Go up one level and get prop value of io/dev
3794df55fdeSJanie Lu */
3804df55fdeSJanie Lu (void) snprintf(query, sizeof (query), "//propval["
3814df55fdeSJanie Lu "@name='BDF' and contains(substring(@value, "
3824df55fdeSJanie Lu "string-length(@value) - 1), '%s')]"
3834df55fdeSJanie Lu "/parent::*/parent::*/propgroup[@name='pci']/propval"
3844df55fdeSJanie Lu "[@name='extended-capabilities' and @value='%s']"
3854df55fdeSJanie Lu "/parent::*/parent::*/propgroup[@name='protocol']"
3864df55fdeSJanie Lu "/propval[@name='resource' and contains(@value, '%s')]"
3874df55fdeSJanie Lu "/parent::*/parent::*/propgroup[@name='io']"
3884df55fdeSJanie Lu "/propval[@name='dev']/@value", str, PCIEX_ROOT, hcpath);
3894df55fdeSJanie Lu
3904df55fdeSJanie Lu fmd_hdl_free(hdl, hcpath, len);
3914df55fdeSJanie Lu
3924df55fdeSJanie Lu return (fab_xpath_query(hdl, query));
3934df55fdeSJanie Lu }
3944df55fdeSJanie Lu
3954df55fdeSJanie Lu char *
fab_find_rppath_by_devbdf(fmd_hdl_t * hdl,nvlist_t * nvl,pcie_req_id_t bdf)3964df55fdeSJanie Lu fab_find_rppath_by_devbdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf)
3974df55fdeSJanie Lu {
3984df55fdeSJanie Lu xmlXPathObjectPtr xpathObj;
3994df55fdeSJanie Lu xmlNodeSetPtr nodes;
4004df55fdeSJanie Lu xmlNodePtr devNode;
401*ffb64830SJordan Paige Hendricks char *retval, *temp;
4024df55fdeSJanie Lu char query[500];
4034df55fdeSJanie Lu int i, size, bus, dev, fn;
4044df55fdeSJanie Lu char *hcpath;
4054df55fdeSJanie Lu size_t len;
4064df55fdeSJanie Lu
4074df55fdeSJanie Lu if (bdf != (uint16_t)-1) {
4084df55fdeSJanie Lu bus = (bdf & PCIE_REQ_ID_BUS_MASK) >> PCIE_REQ_ID_BUS_SHIFT;
4094df55fdeSJanie Lu dev = (bdf & PCIE_REQ_ID_DEV_MASK) >> PCIE_REQ_ID_DEV_SHIFT;
4104df55fdeSJanie Lu fn = (bdf & PCIE_REQ_ID_FUNC_MASK) >> PCIE_REQ_ID_FUNC_SHIFT;
4114df55fdeSJanie Lu }
4124df55fdeSJanie Lu
4134df55fdeSJanie Lu /*
4144df55fdeSJanie Lu * get the string form of the hc detector, eg
4154df55fdeSJanie Lu * /chassis=0/motherboard=0/hostbridge=0
4164df55fdeSJanie Lu */
4174df55fdeSJanie Lu if (!fab_get_hcpath(hdl, nvl, &hcpath, &len))
4184df55fdeSJanie Lu goto fail;
4194df55fdeSJanie Lu
4204df55fdeSJanie Lu /*
4214df55fdeSJanie Lu * Explanation of the XSL XPATH Query
4224df55fdeSJanie Lu * Line 1: Look at all nodes with the node name "propval"
4234df55fdeSJanie Lu * Line 2-3: See if the "value" of the node ends with correct PCIEx BDF
4244df55fdeSJanie Lu * Line 4-5: See if the "value" of the node ends with correct PCI BDF
4254df55fdeSJanie Lu * Line 6: Go up one level to the parent of the current node
4264df55fdeSJanie Lu * Line 7: See if child node contains "ASRU" with the same PCIe Root
4274df55fdeSJanie Lu * Line 8: Go up see all the ancestors
4284df55fdeSJanie Lu */
4294df55fdeSJanie Lu (void) snprintf(query, sizeof (query), "//propval["
4304df55fdeSJanie Lu "contains(substring(@value, string-length(@value) - 34), "
4314df55fdeSJanie Lu "'pciexbus=%d/pciexdev=%d/pciexfn=%d') or "
4324df55fdeSJanie Lu "contains(substring(@value, string-length(@value) - 28), "
4334df55fdeSJanie Lu "'pcibus=%d/pcidev=%d/pcifn=%d')"
4344df55fdeSJanie Lu "]/parent::"
4354df55fdeSJanie Lu "*/propval[@name='resource' and contains(@value, '%s')]"
4364df55fdeSJanie Lu "/ancestor::*",
4374df55fdeSJanie Lu bus, dev, fn, bus, dev, fn, hcpath);
4384df55fdeSJanie Lu
4394df55fdeSJanie Lu fmd_hdl_free(hdl, hcpath, len);
4404df55fdeSJanie Lu
4414df55fdeSJanie Lu fmd_hdl_debug(hdl, "xpathObj query %s\n", query);
4424df55fdeSJanie Lu
4434df55fdeSJanie Lu xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx);
4444df55fdeSJanie Lu
4454df55fdeSJanie Lu if (xpathObj == NULL)
4464df55fdeSJanie Lu goto fail;
4474df55fdeSJanie Lu
4484df55fdeSJanie Lu nodes = xpathObj->nodesetval;
4494df55fdeSJanie Lu size = (nodes) ? nodes->nodeNr : 0;
4504df55fdeSJanie Lu
4514df55fdeSJanie Lu fmd_hdl_debug(hdl, "xpathObj 0x%p type %d size %d\n",
4524df55fdeSJanie Lu xpathObj, xpathObj->type, size);
4534df55fdeSJanie Lu
4544df55fdeSJanie Lu for (i = 0; i < size; i++) {
4554df55fdeSJanie Lu devNode = nodes->nodeTab[i];
4564df55fdeSJanie Lu if (STRCMP(devNode->name, "range") &&
4574df55fdeSJanie Lu HAS_PROP(devNode, "name")) {
4584df55fdeSJanie Lu char *tprop = GET_PROP(devNode, "name");
4594df55fdeSJanie Lu
4604df55fdeSJanie Lu /* find "range name='pciexrc'" in ancestors */
4614df55fdeSJanie Lu if (STRCMP(tprop, PCIEX_ROOT)) {
4624df55fdeSJanie Lu /* go down to the pciexrc instance node */
4634df55fdeSJanie Lu FREE_PROP(tprop);
4644df55fdeSJanie Lu devNode = nodes->nodeTab[i+1];
4654df55fdeSJanie Lu goto found;
4664df55fdeSJanie Lu }
4674df55fdeSJanie Lu FREE_PROP(tprop);
4684df55fdeSJanie Lu }
4694df55fdeSJanie Lu }
4704df55fdeSJanie Lu goto fail;
4714df55fdeSJanie Lu
4724df55fdeSJanie Lu found:
4734df55fdeSJanie Lu /* Traverse down the xml tree to find the right propgroup */
4744df55fdeSJanie Lu for (devNode = devNode->children; devNode; devNode = devNode->next) {
4754df55fdeSJanie Lu if (STRCMP(devNode->name, "propgroup")) {
4764df55fdeSJanie Lu char *tprop = GET_PROP(devNode, "name");
4774df55fdeSJanie Lu
4784df55fdeSJanie Lu if (STRCMP(tprop, "io")) {
4794df55fdeSJanie Lu FREE_PROP(tprop);
4804df55fdeSJanie Lu goto propgroup;
4814df55fdeSJanie Lu }
4824df55fdeSJanie Lu FREE_PROP(tprop);
4834df55fdeSJanie Lu }
4844df55fdeSJanie Lu }
4854df55fdeSJanie Lu goto fail;
4864df55fdeSJanie Lu
4874df55fdeSJanie Lu propgroup:
4884df55fdeSJanie Lu /* Retrive the "dev" propval and return */
4894df55fdeSJanie Lu for (devNode = devNode->children; devNode; devNode = devNode->next) {
4904df55fdeSJanie Lu if (STRCMP(devNode->name, "propval")) {
4914df55fdeSJanie Lu char *tprop = GET_PROP(devNode, "name");
4924df55fdeSJanie Lu
4934df55fdeSJanie Lu if (STRCMP(tprop, "dev")) {
4944df55fdeSJanie Lu temp = GET_PROP(devNode, "value");
4954df55fdeSJanie Lu retval = fmd_hdl_strdup(hdl, temp, FMD_SLEEP);
4964df55fdeSJanie Lu fmd_hdl_debug(hdl, "RP Path: %s\n", retval);
4974df55fdeSJanie Lu xmlFree(temp);
4984df55fdeSJanie Lu xmlXPathFreeObject(xpathObj);
4994df55fdeSJanie Lu }
5004df55fdeSJanie Lu FREE_PROP(tprop);
5014df55fdeSJanie Lu
5024df55fdeSJanie Lu return (retval);
5034df55fdeSJanie Lu }
5044df55fdeSJanie Lu }
5054df55fdeSJanie Lu fail:
5064df55fdeSJanie Lu if (xpathObj != NULL)
5074df55fdeSJanie Lu xmlXPathFreeObject(xpathObj);
5084df55fdeSJanie Lu return (NULL);
5094df55fdeSJanie Lu }
5104df55fdeSJanie Lu
5114f764f91SCheng Sean Ye char *
fab_find_rppath_by_devpath(fmd_hdl_t * hdl,const char * devpath)5124f764f91SCheng Sean Ye fab_find_rppath_by_devpath(fmd_hdl_t *hdl, const char *devpath)
5134f764f91SCheng Sean Ye {
5144f764f91SCheng Sean Ye char query[500];
5154f764f91SCheng Sean Ye
5164f764f91SCheng Sean Ye /*
5174f764f91SCheng Sean Ye * Explanation of the XSL XPATH Query
5184f764f91SCheng Sean Ye * Line 1: Look at all nodes with the node name "propval"
5194f764f91SCheng Sean Ye * Line 2: See if the node is pciexrc
5204f764f91SCheng Sean Ye * Line 3: Go up to the io pgroup
5214f764f91SCheng Sean Ye * Line 4: See if the "dev" prop is parent of devpath
5224f764f91SCheng Sean Ye * Line 5: Get the 'dev' prop
5234f764f91SCheng Sean Ye */
5244f764f91SCheng Sean Ye (void) snprintf(query, sizeof (query), "//propval"
5254f764f91SCheng Sean Ye "[@name='extended-capabilities' and @value='%s']"
5264f764f91SCheng Sean Ye "/parent::*/parent::*/propgroup[@name='io']"
5274f764f91SCheng Sean Ye "/propval[@name='dev' and starts-with('%s', concat(@value, '/'))]"
5284f764f91SCheng Sean Ye "/@value", PCIEX_ROOT, devpath);
5294f764f91SCheng Sean Ye
5304f764f91SCheng Sean Ye return (fab_xpath_query(hdl, query));
5314f764f91SCheng Sean Ye }
5324f764f91SCheng Sean Ye
5334df55fdeSJanie Lu /* ARGSUSED */
5344df55fdeSJanie Lu boolean_t
fab_get_rcpath(fmd_hdl_t * hdl,nvlist_t * nvl,char * rcpath)5354df55fdeSJanie Lu fab_get_rcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char *rcpath)
5364df55fdeSJanie Lu {
5374df55fdeSJanie Lu nvlist_t *detector;
5384df55fdeSJanie Lu char *path, *scheme;
5394df55fdeSJanie Lu
5404df55fdeSJanie Lu if (nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector) != 0)
5414df55fdeSJanie Lu goto fail;
5424df55fdeSJanie Lu if (nvlist_lookup_string(detector, FM_FMRI_SCHEME, &scheme) != 0)
5434df55fdeSJanie Lu goto fail;
5444df55fdeSJanie Lu
5454df55fdeSJanie Lu if (STRCMP(scheme, FM_FMRI_SCHEME_DEV)) {
5464df55fdeSJanie Lu if (nvlist_lookup_string(detector, FM_FMRI_DEV_PATH,
5474df55fdeSJanie Lu &path) != 0)
5484df55fdeSJanie Lu goto fail;
5494df55fdeSJanie Lu (void) strncpy(rcpath, path, FM_MAX_CLASS);
5504df55fdeSJanie Lu } else if (STRCMP(scheme, FM_FMRI_SCHEME_HC)) {
5514df55fdeSJanie Lu /*
5524df55fdeSJanie Lu * This should only occur for ereports that come from the RC
5534df55fdeSJanie Lu * itself. In this case convert HC scheme to dev path.
5544df55fdeSJanie Lu */
5554df55fdeSJanie Lu if (fab_hc2dev_nvl(hdl, detector, &path)) {
5564df55fdeSJanie Lu (void) strncpy(rcpath, path, FM_MAX_CLASS);
5574df55fdeSJanie Lu fmd_hdl_strfree(hdl, path);
5584df55fdeSJanie Lu } else {
5594df55fdeSJanie Lu goto fail;
5604df55fdeSJanie Lu }
5614df55fdeSJanie Lu } else {
5624df55fdeSJanie Lu return (B_FALSE);
5634df55fdeSJanie Lu }
5644df55fdeSJanie Lu
5654df55fdeSJanie Lu /*
5664df55fdeSJanie Lu * Extract the RC path by taking the first device in the dev path
5674df55fdeSJanie Lu *
5684df55fdeSJanie Lu * /pci@0,0/pci8086,3605@2/pci8086,3500@0/pci8086,3514@1/pci8086,105e@0
5694df55fdeSJanie Lu * - to -
5704df55fdeSJanie Lu * /pci@0,0
5714df55fdeSJanie Lu */
5724df55fdeSJanie Lu path = strchr(rcpath + 1, '/');
5734df55fdeSJanie Lu if (path)
5744df55fdeSJanie Lu path[0] = '\0';
5754df55fdeSJanie Lu
5764df55fdeSJanie Lu return (B_TRUE);
5774df55fdeSJanie Lu fail:
5784df55fdeSJanie Lu return (B_FALSE);
5794df55fdeSJanie Lu }
5804df55fdeSJanie Lu
5814df55fdeSJanie Lu char *
fab_find_bdf(fmd_hdl_t * hdl,nvlist_t * nvl,pcie_req_id_t bdf)5824df55fdeSJanie Lu fab_find_bdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf)
5834df55fdeSJanie Lu {
584*ffb64830SJordan Paige Hendricks char *retval;
5854df55fdeSJanie Lu char query[500];
5864df55fdeSJanie Lu int bus, dev, fn;
5874df55fdeSJanie Lu char rcpath[255];
5884df55fdeSJanie Lu
5894df55fdeSJanie Lu if (bdf != (uint16_t)-1) {
5904df55fdeSJanie Lu bus = (bdf & PCIE_REQ_ID_BUS_MASK) >> PCIE_REQ_ID_BUS_SHIFT;
5914df55fdeSJanie Lu dev = (bdf & PCIE_REQ_ID_DEV_MASK) >> PCIE_REQ_ID_DEV_SHIFT;
5924df55fdeSJanie Lu fn = (bdf & PCIE_REQ_ID_FUNC_MASK) >> PCIE_REQ_ID_FUNC_SHIFT;
5934df55fdeSJanie Lu }
5944df55fdeSJanie Lu
5954df55fdeSJanie Lu if (!fab_get_rcpath(hdl, nvl, rcpath))
5964df55fdeSJanie Lu goto fail;
5974df55fdeSJanie Lu
5984df55fdeSJanie Lu /*
5994df55fdeSJanie Lu * Explanation of the XSL XPATH Query
6004df55fdeSJanie Lu * Line 1: Look at all nodes with the node name "propval"
6014df55fdeSJanie Lu * Line 2-3: See if the "value" of the node ends with correct PCIEx BDF
6024df55fdeSJanie Lu * Line 4-5: See if the "value" of the node ends with correct PCI BDF
6034df55fdeSJanie Lu * Line 6: Go up one level to the parent of the current node
6044df55fdeSJanie Lu * Line 7: See if child node contains "ASRU" with the same PCIe Root
6054df55fdeSJanie Lu * Line 8: Traverse up the parent and the other siblings and look for
6064df55fdeSJanie Lu * the io "propgroup" and get the value of the dev "propval"
6074df55fdeSJanie Lu */
6084df55fdeSJanie Lu (void) snprintf(query, sizeof (query), "//propval["
6094df55fdeSJanie Lu "contains(substring(@value, string-length(@value) - 34), "
6104df55fdeSJanie Lu "'pciexbus=%d/pciexdev=%d/pciexfn=%d') or "
6114df55fdeSJanie Lu "contains(substring(@value, string-length(@value) - 28), "
6124df55fdeSJanie Lu "'pcibus=%d/pcidev=%d/pcifn=%d')"
6134df55fdeSJanie Lu "]/parent::"
6144df55fdeSJanie Lu "*/propval[@name='ASRU' and contains(@value, '%s')]"
6154df55fdeSJanie Lu "/parent::*/following-sibling::*[@name='io']/propval[@name='dev']/"
6164df55fdeSJanie Lu "@value", bus, dev, fn, bus, dev, fn, rcpath);
6174df55fdeSJanie Lu
6184df55fdeSJanie Lu retval = fab_xpath_query(hdl, query);
6194df55fdeSJanie Lu if (retval) {
6204df55fdeSJanie Lu fmd_hdl_debug(hdl, "BDF Dev Path: %s\n", retval);
6214df55fdeSJanie Lu return (retval);
6224df55fdeSJanie Lu }
6234df55fdeSJanie Lu fail:
6244df55fdeSJanie Lu return (NULL);
6254df55fdeSJanie Lu }
6264df55fdeSJanie Lu
6274df55fdeSJanie Lu char *
fab_find_addr(fmd_hdl_t * hdl,nvlist_t * nvl,uint64_t addr)6284df55fdeSJanie Lu fab_find_addr(fmd_hdl_t *hdl, nvlist_t *nvl, uint64_t addr)
6294df55fdeSJanie Lu {
6304df55fdeSJanie Lu xmlXPathObjectPtr xpathObj;
6314df55fdeSJanie Lu xmlNodeSetPtr nodes;
6324df55fdeSJanie Lu xmlNodePtr devNode;
6334df55fdeSJanie Lu char *retval, *temp;
6344df55fdeSJanie Lu char query[500];
6354df55fdeSJanie Lu int size, i, j;
6364df55fdeSJanie Lu uint32_t prop[50];
6374df55fdeSJanie Lu char *token;
6384df55fdeSJanie Lu pci_regspec_t *assign_p;
6394df55fdeSJanie Lu uint64_t low, hi;
6404df55fdeSJanie Lu char rcpath[255];
6414df55fdeSJanie Lu
6424df55fdeSJanie Lu if (!fab_get_rcpath(hdl, nvl, rcpath))
6434df55fdeSJanie Lu goto fail;
6444df55fdeSJanie Lu
6454df55fdeSJanie Lu (void) snprintf(query, sizeof (query), "//propval["
6464df55fdeSJanie Lu "@name='ASRU' and contains(@value, '%s')]/"
6474df55fdeSJanie Lu "parent::*/following-sibling::*[@name='pci']/"
6484df55fdeSJanie Lu "propval[@name='assigned-addresses']", rcpath);
6494df55fdeSJanie Lu
6504df55fdeSJanie Lu fmd_hdl_debug(hdl, "xpathObj query %s\n", query);
6514df55fdeSJanie Lu
6524df55fdeSJanie Lu xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx);
6534df55fdeSJanie Lu
6544df55fdeSJanie Lu if (xpathObj == NULL)
6554df55fdeSJanie Lu goto fail;
6564df55fdeSJanie Lu
6574df55fdeSJanie Lu fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, xpathObj->type);
6584df55fdeSJanie Lu
6594df55fdeSJanie Lu nodes = xpathObj->nodesetval;
6604df55fdeSJanie Lu size = (nodes) ? nodes->nodeNr : 0;
6614df55fdeSJanie Lu
6624df55fdeSJanie Lu /* Decode the list of assigned addresses xml nodes for each device */
6634df55fdeSJanie Lu for (i = 0; i < size; i++) {
6644df55fdeSJanie Lu char *tprop;
6654df55fdeSJanie Lu
6664df55fdeSJanie Lu devNode = nodes->nodeTab[i];
6674df55fdeSJanie Lu if (!HAS_PROP(devNode, "value"))
6684df55fdeSJanie Lu continue;
6694df55fdeSJanie Lu
6704df55fdeSJanie Lu /* Convert "string" assigned-addresses to pci_regspec_t */
6714df55fdeSJanie Lu j = 0;
6724df55fdeSJanie Lu tprop = GET_PROP(devNode, "value");
6734df55fdeSJanie Lu for (token = strtok(tprop, " "); token;
6744df55fdeSJanie Lu token = strtok(NULL, " ")) {
6754df55fdeSJanie Lu prop[j++] = strtoul(token, (char **)NULL, 16);
6764df55fdeSJanie Lu }
6774df55fdeSJanie Lu prop[j] = (uint32_t)-1;
6784df55fdeSJanie Lu FREE_PROP(tprop);
6794df55fdeSJanie Lu
6804df55fdeSJanie Lu /* Check if address belongs to this device */
6814df55fdeSJanie Lu for (assign_p = (pci_regspec_t *)prop;
6824df55fdeSJanie Lu assign_p->pci_phys_hi != (uint_t)-1; assign_p++) {
6834df55fdeSJanie Lu low = assign_p->pci_phys_low;
6844df55fdeSJanie Lu hi = low + assign_p->pci_size_low;
6854df55fdeSJanie Lu if ((addr < hi) && (addr >= low)) {
6864df55fdeSJanie Lu fmd_hdl_debug(hdl, "Found Address\n");
6874df55fdeSJanie Lu goto found;
6884df55fdeSJanie Lu }
6894df55fdeSJanie Lu }
6904df55fdeSJanie Lu }
6914df55fdeSJanie Lu goto fail;
6924df55fdeSJanie Lu
6934df55fdeSJanie Lu found:
6944df55fdeSJanie Lu /* Traverse up the xml tree and back down to find the right propgroup */
6954df55fdeSJanie Lu for (devNode = devNode->parent->parent->children;
6964df55fdeSJanie Lu devNode; devNode = devNode->next) {
6974df55fdeSJanie Lu char *tprop;
6984df55fdeSJanie Lu
6994df55fdeSJanie Lu tprop = GET_PROP(devNode, "name");
7004df55fdeSJanie Lu if (STRCMP(devNode->name, "propgroup") &&
7014df55fdeSJanie Lu STRCMP(tprop, "io")) {
7024df55fdeSJanie Lu FREE_PROP(tprop);
7034df55fdeSJanie Lu goto propgroup;
7044df55fdeSJanie Lu }
7054df55fdeSJanie Lu FREE_PROP(tprop);
7064df55fdeSJanie Lu }
7074df55fdeSJanie Lu goto fail;
7084df55fdeSJanie Lu
7094df55fdeSJanie Lu propgroup:
7104df55fdeSJanie Lu /* Retrive the "dev" propval and return */
7114df55fdeSJanie Lu for (devNode = devNode->children; devNode; devNode = devNode->next) {
712*ffb64830SJordan Paige Hendricks char *tprop;
7134df55fdeSJanie Lu
7144df55fdeSJanie Lu tprop = GET_PROP(devNode, "name");
7154df55fdeSJanie Lu if (STRCMP(devNode->name, "propval") &&
7164df55fdeSJanie Lu STRCMP(tprop, "dev")) {
7174df55fdeSJanie Lu FREE_PROP(tprop);
7184df55fdeSJanie Lu temp = GET_PROP(devNode, "value");
7194df55fdeSJanie Lu retval = fmd_hdl_strdup(hdl, temp, FMD_SLEEP);
7204df55fdeSJanie Lu fmd_hdl_debug(hdl, "Addr Dev Path: %s\n", retval);
7214df55fdeSJanie Lu xmlFree(temp);
7224df55fdeSJanie Lu xmlXPathFreeObject(xpathObj);
7234df55fdeSJanie Lu return (retval);
7244df55fdeSJanie Lu }
7254df55fdeSJanie Lu FREE_PROP(tprop);
7264df55fdeSJanie Lu }
7274df55fdeSJanie Lu fail:
7284df55fdeSJanie Lu if (xpathObj != NULL)
7294df55fdeSJanie Lu xmlXPathFreeObject(xpathObj);
7304df55fdeSJanie Lu return (NULL);
7314df55fdeSJanie Lu }
7324df55fdeSJanie Lu
7334df55fdeSJanie Lu void
fab_pr(fmd_hdl_t * hdl,fmd_event_t * ep,nvlist_t * nvl)7344df55fdeSJanie Lu fab_pr(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl)
7354df55fdeSJanie Lu {
7364df55fdeSJanie Lu nvpair_t *nvp;
7374df55fdeSJanie Lu
7384df55fdeSJanie Lu for (nvp = nvlist_next_nvpair(nvl, NULL);
7394df55fdeSJanie Lu nvp != NULL;
7404df55fdeSJanie Lu nvp = nvlist_next_nvpair(nvl, nvp)) {
7414df55fdeSJanie Lu
7424df55fdeSJanie Lu data_type_t type = nvpair_type(nvp);
7434df55fdeSJanie Lu const char *name = nvpair_name(nvp);
7444df55fdeSJanie Lu
7454df55fdeSJanie Lu boolean_t b;
7464df55fdeSJanie Lu uint8_t i8;
7474df55fdeSJanie Lu uint16_t i16;
7484df55fdeSJanie Lu uint32_t i32;
7494df55fdeSJanie Lu uint64_t i64;
7504df55fdeSJanie Lu char *str;
7514df55fdeSJanie Lu nvlist_t *cnv;
7524df55fdeSJanie Lu
7534df55fdeSJanie Lu nvlist_t **nvlarr;
7544df55fdeSJanie Lu uint_t arrsize;
7554df55fdeSJanie Lu int arri;
7564df55fdeSJanie Lu
7574df55fdeSJanie Lu
7584df55fdeSJanie Lu if (STRCMP(name, FM_CLASS))
7594df55fdeSJanie Lu continue; /* already printed by caller */
7604df55fdeSJanie Lu
7614df55fdeSJanie Lu fmd_hdl_debug(hdl, " %s=", name);
7624df55fdeSJanie Lu
7634df55fdeSJanie Lu switch (type) {
7644df55fdeSJanie Lu case DATA_TYPE_BOOLEAN:
7654df55fdeSJanie Lu fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN 1");
7664df55fdeSJanie Lu break;
7674df55fdeSJanie Lu
7684df55fdeSJanie Lu case DATA_TYPE_BOOLEAN_VALUE:
7694df55fdeSJanie Lu (void) nvpair_value_boolean_value(nvp, &b);
7704df55fdeSJanie Lu fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN_VALUE %d",
7714df55fdeSJanie Lu b ? "1" : "0");
7724df55fdeSJanie Lu break;
7734df55fdeSJanie Lu
7744df55fdeSJanie Lu case DATA_TYPE_BYTE:
7754df55fdeSJanie Lu (void) nvpair_value_byte(nvp, &i8);
7764df55fdeSJanie Lu fmd_hdl_debug(hdl, "DATA_TYPE_BYTE 0x%x", i8);
7774df55fdeSJanie Lu break;
7784df55fdeSJanie Lu
7794df55fdeSJanie Lu case DATA_TYPE_INT8:
7804df55fdeSJanie Lu (void) nvpair_value_int8(nvp, (void *)&i8);
7814df55fdeSJanie Lu fmd_hdl_debug(hdl, "DATA_TYPE_INT8 0x%x", i8);
7824df55fdeSJanie Lu break;
7834df55fdeSJanie Lu
7844df55fdeSJanie Lu case DATA_TYPE_UINT8:
7854df55fdeSJanie Lu (void) nvpair_value_uint8(nvp, &i8);
7864df55fdeSJanie Lu fmd_hdl_debug(hdl, "DATA_TYPE_UINT8 0x%x", i8);
7874df55fdeSJanie Lu break;
7884df55fdeSJanie Lu
7894df55fdeSJanie Lu case DATA_TYPE_INT16:
7904df55fdeSJanie Lu (void) nvpair_value_int16(nvp, (void *)&i16);
7914df55fdeSJanie Lu fmd_hdl_debug(hdl, "DATA_TYPE_INT16 0x%x", i16);
7924df55fdeSJanie Lu break;
7934df55fdeSJanie Lu
7944df55fdeSJanie Lu case DATA_TYPE_UINT16:
7954df55fdeSJanie Lu (void) nvpair_value_uint16(nvp, &i16);
7964df55fdeSJanie Lu fmd_hdl_debug(hdl, "DATA_TYPE_UINT16 0x%x", i16);
7974df55fdeSJanie Lu break;
7984df55fdeSJanie Lu
7994df55fdeSJanie Lu case DATA_TYPE_INT32:
8004df55fdeSJanie Lu (void) nvpair_value_int32(nvp, (void *)&i32);
8014df55fdeSJanie Lu fmd_hdl_debug(hdl, "DATA_TYPE_INT32 0x%x", i32);
8024df55fdeSJanie Lu break;
8034df55fdeSJanie Lu
8044df55fdeSJanie Lu case DATA_TYPE_UINT32:
8054df55fdeSJanie Lu (void) nvpair_value_uint32(nvp, &i32);
8064df55fdeSJanie Lu fmd_hdl_debug(hdl, "DATA_TYPE_UINT32 0x%x", i32);
8074df55fdeSJanie Lu break;
8084df55fdeSJanie Lu
8094df55fdeSJanie Lu case DATA_TYPE_INT64:
8104df55fdeSJanie Lu (void) nvpair_value_int64(nvp, (void *)&i64);
8114df55fdeSJanie Lu fmd_hdl_debug(hdl, "DATA_TYPE_INT64 0x%llx",
8124df55fdeSJanie Lu (u_longlong_t)i64);
8134df55fdeSJanie Lu break;
8144df55fdeSJanie Lu
8154df55fdeSJanie Lu case DATA_TYPE_UINT64:
8164df55fdeSJanie Lu (void) nvpair_value_uint64(nvp, &i64);
8174df55fdeSJanie Lu fmd_hdl_debug(hdl, "DATA_TYPE_UINT64 0x%llx",
8184df55fdeSJanie Lu (u_longlong_t)i64);
8194df55fdeSJanie Lu break;
8204df55fdeSJanie Lu
8214df55fdeSJanie Lu case DATA_TYPE_HRTIME:
8224df55fdeSJanie Lu (void) nvpair_value_hrtime(nvp, (void *)&i64);
8234df55fdeSJanie Lu fmd_hdl_debug(hdl, "DATA_TYPE_HRTIME 0x%llx",
8244df55fdeSJanie Lu (u_longlong_t)i64);
8254df55fdeSJanie Lu break;
8264df55fdeSJanie Lu
8274df55fdeSJanie Lu case DATA_TYPE_STRING:
8284df55fdeSJanie Lu (void) nvpair_value_string(nvp, &str);
8294df55fdeSJanie Lu fmd_hdl_debug(hdl, "DATA_TYPE_STRING \"%s\"",
8304df55fdeSJanie Lu str ? str : "<NULL>");
8314df55fdeSJanie Lu break;
8324df55fdeSJanie Lu
8334df55fdeSJanie Lu case DATA_TYPE_NVLIST:
8344df55fdeSJanie Lu fmd_hdl_debug(hdl, "[");
8354df55fdeSJanie Lu (void) nvpair_value_nvlist(nvp, &cnv);
8364df55fdeSJanie Lu fab_pr(hdl, NULL, cnv);
8374df55fdeSJanie Lu fmd_hdl_debug(hdl, " ]");
8384df55fdeSJanie Lu break;
8394df55fdeSJanie Lu
8404df55fdeSJanie Lu case DATA_TYPE_BOOLEAN_ARRAY:
8414df55fdeSJanie Lu case DATA_TYPE_BYTE_ARRAY:
8424df55fdeSJanie Lu case DATA_TYPE_INT8_ARRAY:
8434df55fdeSJanie Lu case DATA_TYPE_UINT8_ARRAY:
8444df55fdeSJanie Lu case DATA_TYPE_INT16_ARRAY:
8454df55fdeSJanie Lu case DATA_TYPE_UINT16_ARRAY:
8464df55fdeSJanie Lu case DATA_TYPE_INT32_ARRAY:
8474df55fdeSJanie Lu case DATA_TYPE_UINT32_ARRAY:
8484df55fdeSJanie Lu case DATA_TYPE_INT64_ARRAY:
8494df55fdeSJanie Lu case DATA_TYPE_UINT64_ARRAY:
8504df55fdeSJanie Lu case DATA_TYPE_STRING_ARRAY:
8514df55fdeSJanie Lu fmd_hdl_debug(hdl, "[...]");
8524df55fdeSJanie Lu break;
8534df55fdeSJanie Lu case DATA_TYPE_NVLIST_ARRAY:
8544df55fdeSJanie Lu arrsize = 0;
8554df55fdeSJanie Lu (void) nvpair_value_nvlist_array(nvp, &nvlarr,
8564df55fdeSJanie Lu &arrsize);
8574df55fdeSJanie Lu
8584df55fdeSJanie Lu for (arri = 0; arri < arrsize; arri++) {
8594df55fdeSJanie Lu fab_pr(hdl, ep, nvlarr[arri]);
8604df55fdeSJanie Lu }
8614df55fdeSJanie Lu
8624df55fdeSJanie Lu break;
8634df55fdeSJanie Lu case DATA_TYPE_UNKNOWN:
8644df55fdeSJanie Lu fmd_hdl_debug(hdl, "<unknown>");
8654df55fdeSJanie Lu break;
8664df55fdeSJanie Lu }
8674df55fdeSJanie Lu }
8684df55fdeSJanie Lu }
869b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China
870b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China char *
fab_get_rpdev(fmd_hdl_t * hdl)871b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China fab_get_rpdev(fmd_hdl_t *hdl)
872b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China {
873*ffb64830SJordan Paige Hendricks char *retval;
874*ffb64830SJordan Paige Hendricks char query[500];
875b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China
876b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China (void) snprintf(query, sizeof (query), "//propval["
877b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China "@name='extended-capabilities' and contains(@value, '%s')]"
878b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China "/parent::*/parent::*/propgroup[@name='io']"
879b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China "/propval[@name='dev']/@value", PCIEX_ROOT);
880b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China
881b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China retval = fab_xpath_query(hdl, query);
882b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China if (retval) {
883b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China fmd_hdl_debug(hdl, "Root port path is %s\n", retval);
884b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China return (retval);
885b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China }
886b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China
887b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China return (NULL);
888b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China }
889036ec191SCheng Sean Ye
890036ec191SCheng Sean Ye void
fab_send_erpt_all_rps(fmd_hdl_t * hdl,nvlist_t * erpt)891036ec191SCheng Sean Ye fab_send_erpt_all_rps(fmd_hdl_t *hdl, nvlist_t *erpt)
892036ec191SCheng Sean Ye {
893036ec191SCheng Sean Ye xmlXPathObjectPtr xpathObj;
894036ec191SCheng Sean Ye xmlNodeSetPtr nodes;
895*ffb64830SJordan Paige Hendricks char *rppath, *hbpath;
896*ffb64830SJordan Paige Hendricks char query[600];
897036ec191SCheng Sean Ye nvlist_t *detector, *nvl;
898036ec191SCheng Sean Ye uint_t i, size;
899036ec191SCheng Sean Ye size_t len;
900036ec191SCheng Sean Ye
901036ec191SCheng Sean Ye /* get hostbridge's path */
902036ec191SCheng Sean Ye if (!fab_get_hcpath(hdl, erpt, &hbpath, &len)) {
903036ec191SCheng Sean Ye fmd_hdl_debug(hdl,
904036ec191SCheng Sean Ye "fab_send_erpt_on_all_rps: fab_get_hcpath() failed.\n");
905036ec191SCheng Sean Ye return;
906036ec191SCheng Sean Ye }
907036ec191SCheng Sean Ye
908036ec191SCheng Sean Ye (void) snprintf(query, sizeof (query), "//propval["
909036ec191SCheng Sean Ye "@name='extended-capabilities' and contains(@value, '%s')]"
910036ec191SCheng Sean Ye "/parent::*/parent::*/propgroup[@name='protocol']"
911036ec191SCheng Sean Ye "/propval[@name='resource' and contains(@value, '%s/')"
912036ec191SCheng Sean Ye "]/parent::*/parent::*/propgroup[@name='io']"
913036ec191SCheng Sean Ye "/propval[@name='dev']/@value", PCIEX_ROOT, hbpath);
914036ec191SCheng Sean Ye
915036ec191SCheng Sean Ye fmd_hdl_free(hdl, hbpath, len);
916036ec191SCheng Sean Ye
917036ec191SCheng Sean Ye fmd_hdl_debug(hdl, "xpathObj query %s\n", query);
918036ec191SCheng Sean Ye
919036ec191SCheng Sean Ye xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx);
920036ec191SCheng Sean Ye
921036ec191SCheng Sean Ye if (xpathObj == NULL)
922036ec191SCheng Sean Ye return;
923036ec191SCheng Sean Ye
924036ec191SCheng Sean Ye nodes = xpathObj->nodesetval;
925036ec191SCheng Sean Ye size = (nodes) ? nodes->nodeNr : 0;
926036ec191SCheng Sean Ye
927036ec191SCheng Sean Ye fmd_hdl_debug(hdl, "xpathObj 0x%p type %d size %d\n",
928036ec191SCheng Sean Ye xpathObj, xpathObj->type, size);
929036ec191SCheng Sean Ye
930036ec191SCheng Sean Ye for (i = 0; i < size; i++) {
931036ec191SCheng Sean Ye rppath = (char *)xmlNodeGetContent(nodes->nodeTab[i]);
932036ec191SCheng Sean Ye fmd_hdl_debug(hdl, "query result: %s\n", rppath);
933036ec191SCheng Sean Ye
934036ec191SCheng Sean Ye nvl = detector = NULL;
935036ec191SCheng Sean Ye if (nvlist_dup(erpt, &nvl, NV_UNIQUE_NAME) != 0 ||
936036ec191SCheng Sean Ye nvlist_alloc(&detector, NV_UNIQUE_NAME, 0) != 0) {
937036ec191SCheng Sean Ye xmlFree(rppath);
938036ec191SCheng Sean Ye nvlist_free(nvl);
939036ec191SCheng Sean Ye continue;
940036ec191SCheng Sean Ye }
941036ec191SCheng Sean Ye
942036ec191SCheng Sean Ye /*
943036ec191SCheng Sean Ye * set the detector in the original ereport to the root port
944036ec191SCheng Sean Ye */
945036ec191SCheng Sean Ye (void) nvlist_add_string(detector, FM_VERSION,
946036ec191SCheng Sean Ye FM_DEV_SCHEME_VERSION);
947036ec191SCheng Sean Ye (void) nvlist_add_string(detector, FM_FMRI_SCHEME,
948036ec191SCheng Sean Ye FM_FMRI_SCHEME_DEV);
949036ec191SCheng Sean Ye (void) nvlist_add_string(detector, FM_FMRI_DEV_PATH,
950036ec191SCheng Sean Ye rppath);
951036ec191SCheng Sean Ye (void) nvlist_remove_all(nvl, FM_EREPORT_DETECTOR);
952036ec191SCheng Sean Ye (void) nvlist_add_nvlist(nvl, FM_EREPORT_DETECTOR,
953036ec191SCheng Sean Ye detector);
954036ec191SCheng Sean Ye nvlist_free(detector);
955036ec191SCheng Sean Ye xmlFree(rppath);
956036ec191SCheng Sean Ye
957036ec191SCheng Sean Ye fmd_hdl_debug(hdl, "Sending ereport: %s\n", fab_buf);
958036ec191SCheng Sean Ye fmd_xprt_post(hdl, fab_fmd_xprt, nvl, 0);
959036ec191SCheng Sean Ye if (fmd_xprt_error(hdl, fab_fmd_xprt))
960036ec191SCheng Sean Ye fmd_hdl_debug(hdl,
961036ec191SCheng Sean Ye "Failed to send PCI ereport\n");
962036ec191SCheng Sean Ye }
963036ec191SCheng Sean Ye
964036ec191SCheng Sean Ye xmlXPathFreeObject(xpathObj);
965036ec191SCheng Sean Ye }
966