17aec1d6eScindi /*
27aec1d6eScindi * CDDL HEADER START
37aec1d6eScindi *
47aec1d6eScindi * The contents of this file are subject to the terms of the
57aec1d6eScindi * Common Development and Distribution License (the "License").
67aec1d6eScindi * You may not use this file except in compliance with the License.
77aec1d6eScindi *
87aec1d6eScindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97aec1d6eScindi * or http://www.opensolaris.org/os/licensing.
107aec1d6eScindi * See the License for the specific language governing permissions
117aec1d6eScindi * and limitations under the License.
127aec1d6eScindi *
137aec1d6eScindi * When distributing Covered Code, include this CDDL HEADER in each
147aec1d6eScindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157aec1d6eScindi * If applicable, add the following below this CDDL HEADER, with the
167aec1d6eScindi * fields enclosed by brackets "[]" replaced with your own identifying
177aec1d6eScindi * information: Portions Copyright [yyyy] [name of copyright owner]
187aec1d6eScindi *
197aec1d6eScindi * CDDL HEADER END
207aec1d6eScindi */
217aec1d6eScindi
227aec1d6eScindi /*
230db3240dSStephen Hanson * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24106e8bd4SRob Johnston * Copyright 2019 Joyent, Inc.
257aec1d6eScindi */
267aec1d6eScindi
2760348818STarik Soydan #include <alloca.h>
287aec1d6eScindi #include <assert.h>
2960348818STarik Soydan #include <fm/topo_mod.h>
3060348818STarik Soydan #include <libnvpair.h>
317aec1d6eScindi #include <string.h>
320eb822a1Scindi #include <sys/fm/protocol.h>
337aec1d6eScindi
340eb822a1Scindi #include <did.h>
350eb822a1Scindi #include <pcibus.h>
360eb822a1Scindi #include <pcibus_labels.h>
377aec1d6eScindi
387aec1d6eScindi extern slotnm_rewrite_t *Slot_Rewrites;
397aec1d6eScindi extern physlot_names_t *Physlot_Names;
407aec1d6eScindi extern missing_names_t *Missing_Names;
417aec1d6eScindi
4260348818STarik Soydan /*
4360348818STarik Soydan * Do a platform specific label lookup based on physical slot number.
4460348818STarik Soydan */
457aec1d6eScindi static const char *
pci_label_physlot_lookup(topo_mod_t * mod,char * platform,did_t * dp)4660348818STarik Soydan pci_label_physlot_lookup(topo_mod_t *mod, char *platform, did_t *dp)
477aec1d6eScindi {
487aec1d6eScindi const char *rlabel = NULL;
497aec1d6eScindi int n, p, i;
507aec1d6eScindi
51a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: doing a lookup for platform=%s\n",
52a4aef2baSTarik Soydan __func__, platform);
53a4aef2baSTarik Soydan
5460348818STarik Soydan if ((n = did_physlot(dp)) < 0 || Physlot_Names == NULL ||
5594ed70baSzx platform == NULL)
567aec1d6eScindi return (NULL);
577aec1d6eScindi
58a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: doing a lookup for physlot=%d\n",
59a4aef2baSTarik Soydan __func__, n);
60a4aef2baSTarik Soydan
617aec1d6eScindi for (p = 0; p < Physlot_Names->psn_nplats; p++) {
62a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: comparing against platform=%s\n",
63a4aef2baSTarik Soydan __func__, Physlot_Names->psn_names[p].pnm_platform);
640db3240dSStephen Hanson if (strcasecmp(Physlot_Names->psn_names[p].pnm_platform,
657aec1d6eScindi platform) != 0)
667aec1d6eScindi continue;
67a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: found lookup table for this "
68a4aef2baSTarik Soydan "platform\n", __func__);
697aec1d6eScindi for (i = 0; i < Physlot_Names->psn_names[p].pnm_nnames; i++) {
707aec1d6eScindi physnm_t ps;
717aec1d6eScindi ps = Physlot_Names->psn_names[p].pnm_names[i];
727aec1d6eScindi if (ps.ps_num == n) {
73a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: matched entry=%d, "
74a4aef2baSTarik Soydan "label=%s\n", __func__, i, ps.ps_label);
757aec1d6eScindi rlabel = ps.ps_label;
767aec1d6eScindi break;
777aec1d6eScindi }
787aec1d6eScindi }
797aec1d6eScindi break;
807aec1d6eScindi }
8160348818STarik Soydan if (rlabel != NULL) {
82a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: returning label=%s\n",
83a4aef2baSTarik Soydan __func__, rlabel);
8460348818STarik Soydan }
857aec1d6eScindi return (rlabel);
867aec1d6eScindi }
877aec1d6eScindi
8860348818STarik Soydan /*
8960348818STarik Soydan * Do a platform specific label lookup based on slot name.
9060348818STarik Soydan */
917aec1d6eScindi static const char *
pci_label_slotname_lookup(topo_mod_t * mod,char * platform,const char * label,did_t * dp)92a4aef2baSTarik Soydan pci_label_slotname_lookup(topo_mod_t *mod, char *platform,
93a4aef2baSTarik Soydan const char *label, did_t *dp)
947aec1d6eScindi {
957aec1d6eScindi const char *rlabel = label;
96a4aef2baSTarik Soydan int s, i, ret;
977aec1d6eScindi
98a4aef2baSTarik Soydan if (Slot_Rewrites == NULL || platform == NULL)
997aec1d6eScindi return (rlabel);
1007aec1d6eScindi
101a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: doing a lookup for platform=%s\n",
102a4aef2baSTarik Soydan __func__, platform);
103a4aef2baSTarik Soydan
1047aec1d6eScindi for (s = 0; s < Slot_Rewrites->srw_nplats; s++) {
105a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: comparing against platform=%s\n",
106a4aef2baSTarik Soydan __func__, Slot_Rewrites->srw_platrewrites[s].prw_platform);
1070db3240dSStephen Hanson if (strcasecmp(Slot_Rewrites->srw_platrewrites[s].prw_platform,
1087aec1d6eScindi platform) != 0)
1097aec1d6eScindi continue;
110a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: found lookup table for this "
111a4aef2baSTarik Soydan "platform\n", __func__);
1127aec1d6eScindi for (i = 0;
1137aec1d6eScindi i < Slot_Rewrites->srw_platrewrites[s].prw_nrewrites;
1147aec1d6eScindi i++) {
1157aec1d6eScindi slot_rwd_t rw;
1167aec1d6eScindi rw = Slot_Rewrites->srw_platrewrites[s].prw_rewrites[i];
1177aec1d6eScindi if (strcmp(rw.srw_obp, label) == 0) {
118a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: matched entry=%d, "
119a4aef2baSTarik Soydan "old_label=%s, new_label=%s\n",
1200db3240dSStephen Hanson __func__, i, rw.srw_obp,
1210db3240dSStephen Hanson rw.srw_new ? rw.srw_new : NULL);
122a4aef2baSTarik Soydan /*
123a4aef2baSTarik Soydan * If a test function is specified then call
124a4aef2baSTarik Soydan * it to do an additional check.
125a4aef2baSTarik Soydan */
126a4aef2baSTarik Soydan if (rw.srw_test != NULL) {
127a4aef2baSTarik Soydan topo_mod_dprintf(mod,
128a4aef2baSTarik Soydan "%s: calling test function=%p\n",
129a4aef2baSTarik Soydan __func__, rw.srw_test);
13058d4b16fSRobert Mustacchi if ((ret = rw.srw_test(mod, dp)) != 0)
131a4aef2baSTarik Soydan rlabel = rw.srw_new;
132a4aef2baSTarik Soydan topo_mod_dprintf(mod,
133a4aef2baSTarik Soydan "%s: test function return=%d\n",
134a4aef2baSTarik Soydan __func__, ret);
135a4aef2baSTarik Soydan } else {
136a4aef2baSTarik Soydan rlabel = rw.srw_new;
137a4aef2baSTarik Soydan }
1387aec1d6eScindi break;
1397aec1d6eScindi }
1407aec1d6eScindi }
1417aec1d6eScindi break;
1427aec1d6eScindi }
1430db3240dSStephen Hanson topo_mod_dprintf(mod, "%s: returning label=%s\n", __func__,
1440db3240dSStephen Hanson rlabel ? rlabel : "NULL");
1457aec1d6eScindi return (rlabel);
1467aec1d6eScindi }
1477aec1d6eScindi
14860348818STarik Soydan /*
14960348818STarik Soydan * Do a platform specific label lookup based on bus, dev, etc.
15060348818STarik Soydan */
1517aec1d6eScindi static const char *
pci_label_missing_lookup(topo_mod_t * mod,char * platform,did_t * dp)15260348818STarik Soydan pci_label_missing_lookup(topo_mod_t *mod, char *platform, did_t *dp)
1537aec1d6eScindi {
1547aec1d6eScindi const char *rlabel = NULL;
1557aec1d6eScindi int board, bridge, rc, bus, dev;
156a4aef2baSTarik Soydan int p, i, ret;
1577aec1d6eScindi
158a4aef2baSTarik Soydan if (Missing_Names == NULL || platform == NULL)
1597aec1d6eScindi return (NULL);
160a4aef2baSTarik Soydan
1617aec1d6eScindi bridge = did_bridge(dp);
1627aec1d6eScindi board = did_board(dp);
1637aec1d6eScindi rc = did_rc(dp);
1647aec1d6eScindi did_BDF(dp, &bus, &dev, NULL);
1657aec1d6eScindi
166a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: doing a lookup for platform=%s, "
167a4aef2baSTarik Soydan "board=%d, bridge=%d, rc=%d, bus=%d, dev=%d\n",
168a4aef2baSTarik Soydan __func__, platform, board, bridge, rc, bus, dev);
1697aec1d6eScindi
1707aec1d6eScindi for (p = 0; p < Missing_Names->mn_nplats; p++) {
171a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: comparing against platform=%s\n",
172a4aef2baSTarik Soydan __func__, Missing_Names->mn_names[p].pdl_platform);
1730db3240dSStephen Hanson if (strcasecmp(Missing_Names->mn_names[p].pdl_platform,
1747aec1d6eScindi platform) != 0)
1757aec1d6eScindi continue;
176a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: found lookup table for this "
177a4aef2baSTarik Soydan "platform\n", __func__);
1787aec1d6eScindi for (i = 0; i < Missing_Names->mn_names[p].pdl_nnames; i++) {
1797aec1d6eScindi devlab_t m;
1807aec1d6eScindi m = Missing_Names->mn_names[p].pdl_names[i];
1817aec1d6eScindi if (m.dl_board == board && m.dl_bridge == bridge &&
1820db3240dSStephen Hanson m.dl_rc == rc &&
1830db3240dSStephen Hanson (m.dl_bus == -1 || m.dl_bus == bus) &&
1840db3240dSStephen Hanson (m.dl_dev == -1 || m.dl_dev == dev)) {
185a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: matched entry=%d, "
186a4aef2baSTarik Soydan "label=%s\n", __func__, i, m.dl_label);
187a4aef2baSTarik Soydan /*
188a4aef2baSTarik Soydan * If a test function is specified then call
189a4aef2baSTarik Soydan * it to do an additional test.
190a4aef2baSTarik Soydan */
191a4aef2baSTarik Soydan if (m.dl_test != NULL) {
192a4aef2baSTarik Soydan topo_mod_dprintf(mod,
193a4aef2baSTarik Soydan "%s: calling test function=%p\n",
194a4aef2baSTarik Soydan __func__, m.dl_test);
19558d4b16fSRobert Mustacchi if ((ret = m.dl_test(mod, dp)) != 0)
196a4aef2baSTarik Soydan rlabel = m.dl_label;
197a4aef2baSTarik Soydan topo_mod_dprintf(mod,
198a4aef2baSTarik Soydan "%s: test function return=%d\n",
199a4aef2baSTarik Soydan __func__, ret);
2000db3240dSStephen Hanson if (ret)
2010db3240dSStephen Hanson break;
202a4aef2baSTarik Soydan } else {
203a4aef2baSTarik Soydan rlabel = m.dl_label;
2040db3240dSStephen Hanson break;
205a4aef2baSTarik Soydan }
2067aec1d6eScindi }
2077aec1d6eScindi }
2087aec1d6eScindi break;
2097aec1d6eScindi }
21060348818STarik Soydan if (rlabel != NULL) {
211a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: match found, label=%s\n",
212a4aef2baSTarik Soydan __func__, rlabel);
21360348818STarik Soydan }
2147aec1d6eScindi return (rlabel);
2157aec1d6eScindi }
2167aec1d6eScindi
21760348818STarik Soydan /*
21860348818STarik Soydan * Do an overall slot label lookup for the device node.
21960348818STarik Soydan */
22060348818STarik Soydan char *
pci_slot_label_lookup(topo_mod_t * mod,tnode_t * node,did_t * dp,did_t * pdp)22160348818STarik Soydan pci_slot_label_lookup(topo_mod_t *mod, tnode_t *node, did_t *dp, did_t *pdp)
2227aec1d6eScindi {
22360348818STarik Soydan tnode_t *anode, *apnode;
22460348818STarik Soydan did_t *adp, *apdp;
22558d4b16fSRobert Mustacchi char *plat, *pp, *l = NULL, *ancestor_l = NULL, *new_l = NULL;
22660348818STarik Soydan int err, b, d, f, done = 0;
22760348818STarik Soydan size_t len;
2287aec1d6eScindi
22960348818STarik Soydan did_BDF(dp, &b, &d, &f);
230a4aef2baSTarik Soydan
231a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: entry: node=%p, node_name=%s, "
232*6597d6fcSRobert Mustacchi "node_inst=%" PRIu64 ", dp=%p, dp_bdf=%d/%d/%d, pdp=%p\n",
233a4aef2baSTarik Soydan __func__, node, topo_node_name(node), topo_node_instance(node),
234a4aef2baSTarik Soydan dp, b, d, f, pdp);
23560348818STarik Soydan
23660348818STarik Soydan /*
23760348818STarik Soydan * If this device has a physical slot number then check if
23860348818STarik Soydan * an ancestor also has a slot label.
23960348818STarik Soydan *
24060348818STarik Soydan * If an ancestor has a slot label, then this node's label
24160348818STarik Soydan * is generated by concatenating a default label onto the
24260348818STarik Soydan * ancestor's label.
24360348818STarik Soydan *
24460348818STarik Soydan * We grab pairs of ancestors (parent and child) as we go up
24560348818STarik Soydan * the tree because the parent is checked for the presence
24660348818STarik Soydan * of a slot while the child contains the label.
24760348818STarik Soydan *
24860348818STarik Soydan * Note that this algorithm only applies to nodes which have
249106e8bd4SRob Johnston * a physical slot number. (i.e. PCIE devices or PCI/PCIX
25060348818STarik Soydan * devices off of a PCIE to PCIX switch)
25160348818STarik Soydan */
25260348818STarik Soydan if (did_physlot(pdp) >= 0) {
25360348818STarik Soydan
254a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: node=%p: node has a physical "
255a4aef2baSTarik Soydan "slot=%d, checking ancestors for slots\n",
256a4aef2baSTarik Soydan __func__, node, did_physlot(pdp));
25760348818STarik Soydan
25860348818STarik Soydan /*
25960348818STarik Soydan * Get this device's physical slot name.
26060348818STarik Soydan */
26160348818STarik Soydan l = (char *)did_physlot_name(pdp, d);
26260348818STarik Soydan anode = topo_node_parent(node);
26360348818STarik Soydan
26460348818STarik Soydan /*
26560348818STarik Soydan * Check ancestors for a slot label until we
26660348818STarik Soydan * either find one or hit a non-pci device.
26760348818STarik Soydan */
26860348818STarik Soydan while (!done) {
26960348818STarik Soydan
27060348818STarik Soydan /*
27160348818STarik Soydan * Get next ancestor node and data pointers.
27260348818STarik Soydan */
27360348818STarik Soydan anode = topo_node_parent(anode);
27460348818STarik Soydan if (anode != NULL) {
27560348818STarik Soydan adp = did_find(mod,
27660348818STarik Soydan topo_node_getspecific(anode));
27760348818STarik Soydan apnode = topo_node_parent(anode);
27860348818STarik Soydan if (apnode != NULL)
27960348818STarik Soydan apdp = did_find(mod,
28060348818STarik Soydan topo_node_getspecific(apnode));
28160348818STarik Soydan else
28260348818STarik Soydan apdp = NULL;
28360348818STarik Soydan } else {
28460348818STarik Soydan apnode = NULL;
28560348818STarik Soydan apdp = adp = NULL;
28660348818STarik Soydan }
28760348818STarik Soydan
288a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: node=%p: checking next "
289a4aef2baSTarik Soydan "two ancestors: anode=%p, adp=%p "
290a4aef2baSTarik Soydan "apnode=%p, apdp=%p\n",
291a4aef2baSTarik Soydan __func__, node, anode, adp, apnode, apdp);
29260348818STarik Soydan if ((anode != NULL) && (adp != NULL)) {
29360348818STarik Soydan did_BDF(adp, &b, &d, &f);
294a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: node=%p: "
295*6597d6fcSRobert Mustacchi "anode_name=%s[%" PRIu64 "], "
296*6597d6fcSRobert Mustacchi "anode_bdf=%d/%d/%d\n", __func__, node,
297*6597d6fcSRobert Mustacchi topo_node_name(anode),
29860348818STarik Soydan topo_node_instance(anode), b, d, f);
29960348818STarik Soydan }
30060348818STarik Soydan if ((apnode != NULL) && (apdp != NULL)) {
30160348818STarik Soydan did_BDF(apdp, &b, &d, &f);
302a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: node=%p: "
303*6597d6fcSRobert Mustacchi "apnode_name=%s[%" PRIu64 "], "
30460348818STarik Soydan "apnode_bdf=%d/%d/%d\n",
305a4aef2baSTarik Soydan __func__, node, topo_node_name(apnode),
30660348818STarik Soydan topo_node_instance(apnode), b, d, f);
30760348818STarik Soydan }
30860348818STarik Soydan
30960348818STarik Soydan /*
31060348818STarik Soydan * If the ancestors do not exist or are not pci
31160348818STarik Soydan * devices then we're done searching.
31260348818STarik Soydan *
31360348818STarik Soydan * Otherwise, if the ancestor has a physical slot,
31460348818STarik Soydan * and it is a different slot than the one we
31560348818STarik Soydan * started with then lookup the ancestor label,
31660348818STarik Soydan * and we're done.
31760348818STarik Soydan */
31860348818STarik Soydan if ((anode == NULL) || (adp == NULL) ||
31960348818STarik Soydan (apnode == NULL) || (apdp == NULL)) {
32060348818STarik Soydan done++;
32160348818STarik Soydan } else if (did_physlot_exists(apdp) &&
32260348818STarik Soydan (apdp != pdp)) {
32360348818STarik Soydan if (topo_node_label(anode, &ancestor_l,
32460348818STarik Soydan &err) != 0) {
32560348818STarik Soydan topo_mod_dprintf(mod,
326a4aef2baSTarik Soydan "%s: node=%p: topo_node_label() "
327a4aef2baSTarik Soydan "FAILED!", __func__, node);
32860348818STarik Soydan (void) topo_mod_seterrno(mod, err);
32960348818STarik Soydan return (NULL);
33060348818STarik Soydan }
33160348818STarik Soydan done++;
332a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: node=%p: found "
333a4aef2baSTarik Soydan "ancestor with a slot, label=%s ",
334a4aef2baSTarik Soydan __func__, node, ancestor_l);
33560348818STarik Soydan }
33660348818STarik Soydan }
33760348818STarik Soydan if (ancestor_l == NULL) {
338a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: node=%p: no ancestor "
339a4aef2baSTarik Soydan "slot found\n", __func__, node);
34060348818STarik Soydan }
3417aec1d6eScindi }
3420eb822a1Scindi
3430eb822a1Scindi /*
34460348818STarik Soydan * If we found an ancestor with a slot label, and this node has
34560348818STarik Soydan * a physical slot number label then concatenate the two to form
34660348818STarik Soydan * this node's label. Otherwise, do a full slot label lookup.
3470eb822a1Scindi */
34860348818STarik Soydan if (ancestor_l && l) {
349a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: node=%p: concatenating "
350a4aef2baSTarik Soydan "ancestor_l=%s and l=%s\n",
351a4aef2baSTarik Soydan __func__, node, ancestor_l, l);
35260348818STarik Soydan len = strlen(ancestor_l) + strlen(l) + 2;
35360348818STarik Soydan new_l = alloca(len);
35460348818STarik Soydan (void) snprintf(new_l, len, "%s/%s", ancestor_l, l);
35560348818STarik Soydan l = new_l;
35660348818STarik Soydan } else {
35760348818STarik Soydan /*
35860348818STarik Soydan * Get platform name used for lookups.
35960348818STarik Soydan */
36060348818STarik Soydan if (topo_prop_get_string(node, FM_FMRI_AUTHORITY,
36160348818STarik Soydan FM_FMRI_AUTH_PRODUCT, &plat, &err) < 0) {
36260348818STarik Soydan (void) topo_mod_seterrno(mod, err);
36360348818STarik Soydan return (NULL);
36460348818STarik Soydan }
36560348818STarik Soydan /*
36660348818STarik Soydan * Trim SUNW, from the platform name
36760348818STarik Soydan */
36860348818STarik Soydan pp = strchr(plat, ',');
36960348818STarik Soydan if (pp == NULL)
37060348818STarik Soydan pp = plat;
37160348818STarik Soydan else
37260348818STarik Soydan ++pp;
37360348818STarik Soydan /*
37460348818STarik Soydan * Get device number used for lookup.
37560348818STarik Soydan */
37660348818STarik Soydan did_BDF(dp, NULL, &d, NULL);
37760348818STarik Soydan
37860348818STarik Soydan /*
37960348818STarik Soydan * The slot label is determined in the following order:
38060348818STarik Soydan * - Platform specific lookup based on physical slot #.
38160348818STarik Soydan * - Platform specific lookup based on default label string.
38260348818STarik Soydan * - Platform specific lookup based on device number.
38360348818STarik Soydan * - Default label.
38460348818STarik Soydan * The default label is based on the slot names property
38560348818STarik Soydan * if it exists, else it is a generic name derived from
38660348818STarik Soydan * the slot #.
38760348818STarik Soydan */
38860348818STarik Soydan if ((l = (char *)pci_label_physlot_lookup(mod, pp, pdp))
38960348818STarik Soydan == NULL) {
390106e8bd4SRob Johnston if ((l = (char *)did_physlot_name(dp, d)) != NULL) {
39160348818STarik Soydan l = (char *)
392a4aef2baSTarik Soydan pci_label_slotname_lookup(mod, pp, l, dp);
3930db3240dSStephen Hanson }
3940db3240dSStephen Hanson if (l == NULL) {
39560348818STarik Soydan l = (char *)
39660348818STarik Soydan pci_label_missing_lookup(mod, pp, dp);
39760348818STarik Soydan }
3987aec1d6eScindi }
39960348818STarik Soydan topo_mod_strfree(mod, plat);
40060348818STarik Soydan }
40160348818STarik Soydan
40260348818STarik Soydan /*
40360348818STarik Soydan * If we calculated a slot label, then save it in the
40460348818STarik Soydan * node's data structure so we can free it later.
40560348818STarik Soydan */
40660348818STarik Soydan if (l) {
40760348818STarik Soydan if (did_slot_label_get(dp) != NULL)
40860348818STarik Soydan topo_mod_strfree(mod, did_slot_label_get(dp));
40960348818STarik Soydan l = topo_mod_strdup(mod, l);
41060348818STarik Soydan did_slot_label_set(dp, l);
41160348818STarik Soydan }
41260348818STarik Soydan
413a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: exit: node=%p: label=%s\n",
414a4aef2baSTarik Soydan __func__, node, (l ? l : "NULL"));
41560348818STarik Soydan
4167aec1d6eScindi return (l);
4177aec1d6eScindi }
4187aec1d6eScindi
4197aec1d6eScindi int
pci_label_cmn(topo_mod_t * mod,tnode_t * node,nvlist_t * in,nvlist_t ** out)4200eb822a1Scindi pci_label_cmn(topo_mod_t *mod, tnode_t *node, nvlist_t *in, nvlist_t **out)
4217aec1d6eScindi {
4227aec1d6eScindi uint64_t ptr;
42360348818STarik Soydan char *l;
424e5ba14ffSstephh did_t *dp, *pdp;
425e5ba14ffSstephh tnode_t *pnode;
4267aec1d6eScindi char *nm;
4277aec1d6eScindi int err;
4287aec1d6eScindi
4297aec1d6eScindi /*
43000d0963fSdilpreet * If it's not a device or a PCI-express bus (which could potentially
43100d0963fSdilpreet * represent a slot, and therefore we might need to capture its slot
43200d0963fSdilpreet * name information), just inherit any label from our parent
4337aec1d6eScindi */
4347aec1d6eScindi *out = NULL;
4357aec1d6eScindi nm = topo_node_name(node);
43600d0963fSdilpreet if (strcmp(nm, PCI_DEVICE) != 0 && strcmp(nm, PCIEX_DEVICE) != 0 &&
43700d0963fSdilpreet strcmp(nm, PCIEX_BUS) != 0) {
4387aec1d6eScindi if (topo_node_label_set(node, NULL, &err) < 0)
4397aec1d6eScindi if (err != ETOPO_PROP_NOENT)
440724365f7Ssethg return (topo_mod_seterrno(mod, err));
4417aec1d6eScindi return (0);
4427aec1d6eScindi }
4437aec1d6eScindi
4447aec1d6eScindi if (nvlist_lookup_uint64(in, TOPO_METH_LABEL_ARG_NVL, &ptr) != 0) {
445724365f7Ssethg topo_mod_dprintf(mod,
446a4aef2baSTarik Soydan "%s: label method argument not found.\n", __func__);
4477aec1d6eScindi return (-1);
4487aec1d6eScindi }
44980ab886dSwesolows dp = (did_t *)(uintptr_t)ptr;
450e5ba14ffSstephh pnode = did_gettnode(dp);
451e5ba14ffSstephh pdp = did_find(mod, topo_node_getspecific(pnode));
4527aec1d6eScindi
4537aec1d6eScindi /*
45460348818STarik Soydan * Is there a slot label associated with the device?
4557aec1d6eScindi */
45660348818STarik Soydan if ((l = pci_slot_label_lookup(mod, node, dp, pdp)) != NULL) {
4577aec1d6eScindi nvlist_t *rnvl;
4587aec1d6eScindi
459724365f7Ssethg if (topo_mod_nvalloc(mod, &rnvl, NV_UNIQUE_NAME) != 0 ||
4607aec1d6eScindi nvlist_add_string(rnvl, TOPO_METH_LABEL_RET_STR, l) != 0)
461724365f7Ssethg return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
4627aec1d6eScindi *out = rnvl;
4637aec1d6eScindi return (0);
4647aec1d6eScindi } else {
4657aec1d6eScindi if (topo_node_label_set(node, NULL, &err) < 0)
4667aec1d6eScindi if (err != ETOPO_PROP_NOENT)
467724365f7Ssethg return (topo_mod_seterrno(mod, err));
4687aec1d6eScindi return (0);
4697aec1d6eScindi }
4707aec1d6eScindi }
471e5ba14ffSstephh
472e5ba14ffSstephh int
pci_fru_cmn(topo_mod_t * mod,tnode_t * node,nvlist_t * in,nvlist_t ** out)473e5ba14ffSstephh pci_fru_cmn(topo_mod_t *mod, tnode_t *node, nvlist_t *in, nvlist_t **out)
474e5ba14ffSstephh {
475e5ba14ffSstephh int err = 0;
476e5ba14ffSstephh uint64_t ptr;
477e5ba14ffSstephh did_t *dp, *pdp;
478e5ba14ffSstephh tnode_t *pnode;
479e5ba14ffSstephh char *nm;
480e5ba14ffSstephh
481e5ba14ffSstephh *out = NULL;
482e5ba14ffSstephh nm = topo_node_name(node);
483d4c0a8c5Sstephh if (strcmp(nm, PCI_DEVICE) != 0 && strcmp(nm, PCIEX_DEVICE) != 0 &&
484d4c0a8c5Sstephh strcmp(nm, PCIEX_BUS) != 0)
485e5ba14ffSstephh return (0);
486e5ba14ffSstephh
487e5ba14ffSstephh if (nvlist_lookup_uint64(in, "nv1", &ptr) != 0) {
488e5ba14ffSstephh topo_mod_dprintf(mod,
489a4aef2baSTarik Soydan "%s: label method argument not found.\n", __func__);
490e5ba14ffSstephh return (-1);
491e5ba14ffSstephh }
492e5ba14ffSstephh dp = (did_t *)(uintptr_t)ptr;
493e5ba14ffSstephh pnode = did_gettnode(dp);
494e5ba14ffSstephh pdp = did_find(mod, topo_node_getspecific(pnode));
495e5ba14ffSstephh
496e5ba14ffSstephh /*
49760348818STarik Soydan * Is there a slot label associated with the device?
498e5ba14ffSstephh */
49960348818STarik Soydan if (pci_slot_label_lookup(mod, pnode, dp, pdp) != NULL) {
500e5ba14ffSstephh nvlist_t *rnvl;
501e5ba14ffSstephh
502e5ba14ffSstephh if (topo_node_resource(node, &rnvl, &err) < 0 || rnvl == NULL) {
503a4aef2baSTarik Soydan topo_mod_dprintf(mod, "%s: error: %s\n",
504a4aef2baSTarik Soydan __func__, topo_strerror(topo_mod_errno(mod)));
505e5ba14ffSstephh return (topo_mod_seterrno(mod, err));
506e5ba14ffSstephh }
507e5ba14ffSstephh *out = rnvl;
508e5ba14ffSstephh }
509e5ba14ffSstephh return (0);
510e5ba14ffSstephh }
511