xref: /illumos-gate/usr/src/lib/fm/topo/modules/common/pcibus/pcibus_labels.c (revision 437220cd296f6d8b6654d6d52508b40b1e2d1ac7)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <libnvpair.h>
30 #include <fm/topo_mod.h>
31 #include <assert.h>
32 #include <string.h>
33 #include <sys/fm/protocol.h>
34 
35 #include <did.h>
36 #include <pcibus.h>
37 #include <pcibus_labels.h>
38 
39 extern slotnm_rewrite_t *Slot_Rewrites;
40 extern physlot_names_t *Physlot_Names;
41 extern missing_names_t *Missing_Names;
42 
43 static const char *
44 pci_physslot_name_lookup(char *platform, did_t *dp)
45 {
46 	const char *rlabel = NULL;
47 	int n, p, i;
48 
49 	if ((n = did_physslot(dp)) < 0 || Physlot_Names == NULL ||
50 	    platform == NULL)
51 		return (NULL);
52 
53 	for (p = 0; p < Physlot_Names->psn_nplats; p++) {
54 		if (strcmp(Physlot_Names->psn_names[p].pnm_platform,
55 		    platform) != 0)
56 			continue;
57 		for (i = 0; i < Physlot_Names->psn_names[p].pnm_nnames; i++) {
58 			physnm_t ps;
59 			ps = Physlot_Names->psn_names[p].pnm_names[i];
60 			if (ps.ps_num == n) {
61 				rlabel = ps.ps_label;
62 				break;
63 			}
64 		}
65 		break;
66 	}
67 	return (rlabel);
68 }
69 
70 static const char *
71 pci_slotname_rewrite(char *platform, const char *label)
72 {
73 	const char *rlabel = label;
74 	int s, i;
75 
76 	if (Slot_Rewrites == NULL)
77 		return (rlabel);
78 
79 	for (s = 0; s < Slot_Rewrites->srw_nplats; s++) {
80 		if (strcmp(Slot_Rewrites->srw_platrewrites[s].prw_platform,
81 		    platform) != 0)
82 			continue;
83 		for (i = 0;
84 		    i < Slot_Rewrites->srw_platrewrites[s].prw_nrewrites;
85 		    i++) {
86 			slot_rwd_t rw;
87 			rw = Slot_Rewrites->srw_platrewrites[s].prw_rewrites[i];
88 			if (strcmp(rw.srw_obp, label) == 0) {
89 				rlabel = rw.srw_new;
90 				break;
91 			}
92 		}
93 		break;
94 	}
95 	assert(rlabel != NULL);
96 	return (rlabel);
97 }
98 
99 static const char *
100 pci_missing_match(topo_mod_t *mod, char *platform, did_t *dp)
101 {
102 	const char *rlabel = NULL;
103 	int board, bridge, rc, bus, dev;
104 	int p, i;
105 
106 	if (Missing_Names == NULL)
107 		return (NULL);
108 	bridge = did_bridge(dp);
109 	board = did_board(dp);
110 	rc = did_rc(dp);
111 	did_BDF(dp, &bus, &dev, NULL);
112 
113 	topo_mod_dprintf(mod, "Missing a name for %d, %d, %d, %d, %d ?\n",
114 	    board, bridge, rc, bus, dev);
115 
116 	for (p = 0; p < Missing_Names->mn_nplats; p++) {
117 		if (strcmp(Missing_Names->mn_names[p].pdl_platform,
118 		    platform) != 0)
119 			continue;
120 		for (i = 0; i < Missing_Names->mn_names[p].pdl_nnames; i++) {
121 			devlab_t m;
122 			m = Missing_Names->mn_names[p].pdl_names[i];
123 			if (m.dl_board == board && m.dl_bridge == bridge &&
124 			    m.dl_rc == rc && m.dl_bus == bus &&
125 			    m.dl_dev == dev) {
126 				rlabel = m.dl_label;
127 				break;
128 			}
129 		}
130 		break;
131 	}
132 	return (rlabel);
133 }
134 
135 const char *
136 pci_slotname_lookup(topo_mod_t *mod, tnode_t *node, did_t *dp)
137 {
138 	const char *l;
139 	char *plat, *pp;
140 	int err;
141 	int d;
142 
143 	if (topo_prop_get_string(node,
144 	    FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT, &plat, &err) < 0) {
145 		(void) topo_mod_seterrno(mod, err);
146 		return (NULL);
147 	}
148 
149 	/*
150 	 * Trim SUNW, from the platform name
151 	 */
152 	pp = strchr(plat, ',');
153 	if (pp == NULL)
154 		pp = plat;
155 	else
156 		++pp;
157 
158 	did_BDF(dp, NULL, &d, NULL);
159 	if ((l = pci_physslot_name_lookup(pp, dp)) == NULL)
160 		if ((l = did_label(dp, d)) != NULL) {
161 			l = pci_slotname_rewrite(pp, l);
162 		} else {
163 			l = pci_missing_match(mod, pp, dp);
164 		}
165 	topo_mod_strfree(mod, plat);
166 	return (l);
167 }
168 
169 int
170 pci_label_cmn(topo_mod_t *mod, tnode_t *node, nvlist_t *in, nvlist_t **out)
171 {
172 	uint64_t ptr;
173 	const char *l;
174 	did_t *dp;
175 	char *nm;
176 	int err;
177 
178 	/*
179 	 * If it's not a device or a PCI-express bus (which could potentially
180 	 * represent a slot, and therefore we might need to capture its slot
181 	 * name information), just inherit any label from our parent
182 	 */
183 	*out = NULL;
184 	nm = topo_node_name(node);
185 	if (strcmp(nm, PCI_DEVICE) != 0 && strcmp(nm, PCIEX_DEVICE) != 0 &&
186 	    strcmp(nm, PCIEX_BUS) != 0) {
187 		if (topo_node_label_set(node, NULL, &err) < 0)
188 			if (err != ETOPO_PROP_NOENT)
189 				return (topo_mod_seterrno(mod, err));
190 		return (0);
191 	}
192 
193 	if (nvlist_lookup_uint64(in, TOPO_METH_LABEL_ARG_NVL, &ptr) != 0) {
194 		topo_mod_dprintf(mod,
195 		    "label method argument not found.\n");
196 		return (-1);
197 	}
198 	dp = (did_t *)(uintptr_t)ptr;
199 
200 	/*
201 	 * Is there a slotname associated with the device?
202 	 */
203 	if ((l = pci_slotname_lookup(mod, node, dp)) != NULL) {
204 		nvlist_t *rnvl;
205 
206 		if (topo_mod_nvalloc(mod, &rnvl, NV_UNIQUE_NAME) != 0 ||
207 		    nvlist_add_string(rnvl, TOPO_METH_LABEL_RET_STR, l) != 0)
208 			return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
209 		*out = rnvl;
210 		return (0);
211 	} else {
212 		if (topo_node_label_set(node, NULL, &err) < 0)
213 			if (err != ETOPO_PROP_NOENT)
214 				return (topo_mod_seterrno(mod, err));
215 		return (0);
216 	}
217 }
218