Print this page
patch tsoome-feedback
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/fm/topo/modules/common/pcibus/did_props.c
+++ new/usr/src/lib/fm/topo/modules/common/pcibus/did_props.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 #include <assert.h>
28 28 #include <alloca.h>
29 29 #include <string.h>
30 30 #include <strings.h>
31 31 #include <limits.h>
32 32 #include <sys/types.h>
33 33 #include <sys/pci.h>
34 34 #include <sys/pcie.h>
35 35 #include <sys/fm/protocol.h>
36 36 #include <fm/topo_mod.h>
37 37 #include <fm/topo_hc.h>
38 38 #include <libdevinfo.h>
39 39 #include <hostbridge.h>
40 40 #include <pcibus.h>
41 41 #include <did.h>
42 42 #include <did_props.h>
43 43 #include <fm/libtopo.h>
44 44
45 45 static int ASRU_set(tnode_t *, did_t *,
46 46 const char *, const char *, const char *);
47 47 static int FRU_set(tnode_t *, did_t *,
48 48 const char *, const char *, const char *);
49 49 static int DEVprop_set(tnode_t *, did_t *,
50 50 const char *, const char *, const char *);
51 51 static int DRIVERprop_set(tnode_t *, did_t *,
52 52 const char *, const char *, const char *);
53 53 static int MODULEprop_set(tnode_t *, did_t *,
54 54 const char *, const char *, const char *);
55 55 static int EXCAP_set(tnode_t *, did_t *,
56 56 const char *, const char *, const char *);
57 57 static int BDF_set(tnode_t *, did_t *,
58 58 const char *, const char *, const char *);
59 59 static int label_set(tnode_t *, did_t *,
60 60 const char *, const char *, const char *);
61 61 static int maybe_di_chars_copy(tnode_t *, did_t *,
62 62 const char *, const char *, const char *);
63 63 static int maybe_di_uint_to_str(tnode_t *, did_t *,
64 64 const char *, const char *, const char *);
65 65 static int maybe_di_uint_to_dec_str(tnode_t *, did_t *,
66 66 const char *, const char *, const char *);
67 67 static int AADDR_set(tnode_t *, did_t *,
68 68 const char *, const char *, const char *);
69 69
70 70 /*
71 71 * Arrays of "property translation routines" to set the properties a
72 72 * given type of topology node should have.
73 73 *
74 74 * Note that the label_set translation *MUST COME BEFORE* the FRU
75 75 * translation. For the near term we're setting the FRU fmri to
76 76 * be a legacy-hc style FMRI based on the label, so the label needs
77 77 * to have been set before we do the FRU translation.
78 78 *
79 79 */
80 80
81 81 static const topo_pgroup_info_t io_pgroup =
82 82 { TOPO_PGROUP_IO, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
83 83 static const topo_pgroup_info_t pci_pgroup =
84 84 { TOPO_PGROUP_PCI, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
85 85
86 86 static const topo_pgroup_info_t protocol_pgroup = {
87 87 TOPO_PGROUP_PROTOCOL,
88 88 TOPO_STABILITY_PRIVATE,
89 89 TOPO_STABILITY_PRIVATE,
90 90 1
91 91 }; /* Request to create protocol will be ignored by libtopo */
92 92
93 93 txprop_t Fn_common_props[] = {
94 94 { NULL, &io_pgroup, TOPO_IO_DEV, DEVprop_set },
95 95 { DI_DEVTYPPROP, &io_pgroup, TOPO_IO_DEVTYPE, maybe_di_chars_copy },
96 96 { DI_DEVIDPROP, &pci_pgroup, TOPO_PCI_DEVID, maybe_di_uint_to_str },
97 97 { NULL, &io_pgroup, TOPO_IO_DRIVER, DRIVERprop_set },
98 98 { NULL, &io_pgroup, TOPO_IO_MODULE, MODULEprop_set },
99 99 { "serd_io_device_nonfatal_n", &io_pgroup, "serd_io_device_nonfatal_n",
100 100 maybe_di_uint_to_dec_str },
101 101 { "serd_io_device_nonfatal_t", &io_pgroup, "serd_io_device_nonfatal_t",
102 102 maybe_di_chars_copy },
103 103 { "serd_io_device_nonfatal_btlp_n", &io_pgroup,
104 104 "serd_io_device_nonfatal_btlp_n", maybe_di_uint_to_dec_str },
105 105 { "serd_io_device_nonfatal_btlp_t", &io_pgroup,
106 106 "serd_io_device_nonfatal_btlp_t", maybe_di_chars_copy },
107 107 { "serd_io_device_nonfatal_bdllp_n", &io_pgroup,
108 108 "serd_io_device_nonfatal_bdllp_n", maybe_di_uint_to_dec_str },
109 109 { "serd_io_device_nonfatal_bdllp_t", &io_pgroup,
110 110 "serd_io_device_nonfatal_bdllp_t", maybe_di_chars_copy },
111 111 { "serd_io_device_nonfatal_re_n", &io_pgroup,
112 112 "serd_io_device_nonfatal_re_n", maybe_di_uint_to_dec_str },
113 113 { "serd_io_device_nonfatal_re_t", &io_pgroup,
114 114 "serd_io_device_nonfatal_re_t", maybe_di_chars_copy },
115 115 { "serd_io_device_nonfatal_rto_n", &io_pgroup,
116 116 "serd_io_device_nonfatal_rto_n", maybe_di_uint_to_dec_str },
117 117 { "serd_io_device_nonfatal_rto_t", &io_pgroup,
118 118 "serd_io_device_nonfatal_rto_t", maybe_di_chars_copy },
119 119 { "serd_io_device_nonfatal_rnr_n", &io_pgroup,
120 120 "serd_io_device_nonfatal_rnr_n", maybe_di_uint_to_dec_str },
121 121 { "serd_io_device_nonfatal_rnr_t", &io_pgroup,
122 122 "serd_io_pciex_corrlink-bus_rnr_t", maybe_di_chars_copy },
123 123 { "serd_io_pciex_corrlink-bus_btlp_n", &io_pgroup,
124 124 "serd_io_pciex_corrlink-bus_btlp_n", maybe_di_uint_to_dec_str },
125 125 { "serd_io_pciex_corrlink-bus_btlp_t", &io_pgroup,
126 126 "serd_io_pciex_corrlink-bus_btlp_t", maybe_di_chars_copy },
127 127 { "serd_io_pciex_corrlink-bus_bdllp_n", &io_pgroup,
128 128 "serd_io_pciex_corrlink-bus_bdllp_n", maybe_di_uint_to_dec_str },
129 129 { "serd_io_pciex_corrlink-bus_bdllp_t", &io_pgroup,
130 130 "serd_io_pciex_corrlink-bus_bdllp_t", maybe_di_chars_copy },
131 131 { "serd_io_pciex_corrlink-bus_re_n", &io_pgroup,
132 132 "serd_io_pciex_corrlink-bus_re_n", maybe_di_uint_to_dec_str },
133 133 { "serd_io_pciex_corrlink-bus_re_t", &io_pgroup,
134 134 "serd_io_pciex_corrlink-bus_re_t", maybe_di_chars_copy },
135 135 { "serd_io_pciex_corrlink-bus_rto_n", &io_pgroup,
136 136 "serd_io_pciex_corrlink-bus_rto_n", maybe_di_uint_to_dec_str },
137 137 { "serd_io_pciex_corrlink-bus_rto_t", &io_pgroup,
138 138 "serd_io_pciex_corrlink-bus_rto_t", maybe_di_chars_copy },
139 139 { "serd_io_pciex_corrlink-bus_rnr_n", &io_pgroup,
140 140 "serd_io_pciex_corrlink-bus_rnr_n", maybe_di_uint_to_dec_str },
141 141 { "serd_io_pciex_corrlink-bus_rnr_t", &io_pgroup,
142 142 "serd_io_pciex_corrlink-bus_rnr_t", maybe_di_chars_copy },
143 143 { NULL, &pci_pgroup, TOPO_PCI_EXCAP, EXCAP_set },
144 144 { DI_CLASSPROP, &pci_pgroup, TOPO_PCI_CLASS, maybe_di_uint_to_str },
145 145 { DI_VENDIDPROP, &pci_pgroup, TOPO_PCI_VENDID, maybe_di_uint_to_str },
146 146 { DI_AADDRPROP, &pci_pgroup, TOPO_PCI_AADDR, AADDR_set },
147 147 { NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
148 148 { NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set },
149 149 { NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set }
150 150 };
151 151
152 152 txprop_t Dev_common_props[] = {
153 153 { NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
154 154 { NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set },
155 155 { NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set }
156 156 };
157 157
158 158 txprop_t Bus_common_props[] = {
159 159 { DI_DEVTYPPROP, &io_pgroup, TOPO_IO_DEVTYPE, maybe_di_chars_copy },
160 160 { NULL, &io_pgroup, TOPO_IO_DRIVER, DRIVERprop_set },
161 161 { NULL, &io_pgroup, TOPO_IO_MODULE, MODULEprop_set },
162 162 { NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
163 163 { NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set },
164 164 { NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set }
165 165 };
166 166
167 167 txprop_t RC_common_props[] = {
168 168 { NULL, &io_pgroup, TOPO_IO_DEV, DEVprop_set },
169 169 { DI_DEVTYPPROP, &io_pgroup, TOPO_IO_DEVTYPE, maybe_di_chars_copy },
170 170 { NULL, &io_pgroup, TOPO_IO_DRIVER, DRIVERprop_set },
171 171 { NULL, &io_pgroup, TOPO_IO_MODULE, MODULEprop_set },
172 172 { NULL, &pci_pgroup, TOPO_PCI_EXCAP, EXCAP_set },
173 173 { NULL, &pci_pgroup, TOPO_PCI_BDF, BDF_set },
174 174 { NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set },
175 175 /*
176 176 * These props need to be put at the end of table. x86pi has its
177 177 * own way to set them.
178 178 */
179 179 { NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
180 180 { NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set }
181 181 };
182 182
183 183 txprop_t ExHB_common_props[] = {
184 184 { NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set },
185 185 /*
186 186 * These props need to be put at the end of table. x86pi has its
187 187 * own way to set them.
188 188 */
189 189 { NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
190 190 { NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set }
191 191 };
192 192
193 193 txprop_t IOB_common_props[] = {
194 194 { NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
195 195 { NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set },
196 196 { NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set }
197 197 };
198 198
199 199 txprop_t HB_common_props[] = {
200 200 { NULL, &io_pgroup, TOPO_IO_DEV, DEVprop_set },
201 201 { NULL, &io_pgroup, TOPO_IO_DRIVER, DRIVERprop_set },
202 202 { NULL, &io_pgroup, TOPO_IO_MODULE, MODULEprop_set },
203 203 { NULL, &protocol_pgroup, TOPO_PROP_ASRU, ASRU_set },
204 204 /*
205 205 * These props need to be put at the end of table. x86pi has its
206 206 * own way to set them.
207 207 */
208 208 { NULL, &protocol_pgroup, TOPO_PROP_LABEL, label_set },
209 209 { NULL, &protocol_pgroup, TOPO_PROP_FRU, FRU_set }
210 210 };
211 211
212 212 int Bus_propcnt = sizeof (Bus_common_props) / sizeof (txprop_t);
213 213 int Dev_propcnt = sizeof (Dev_common_props) / sizeof (txprop_t);
214 214 int ExHB_propcnt = sizeof (ExHB_common_props) / sizeof (txprop_t);
215 215 int HB_propcnt = sizeof (HB_common_props) / sizeof (txprop_t);
216 216 int IOB_propcnt = sizeof (IOB_common_props) / sizeof (txprop_t);
217 217 int RC_propcnt = sizeof (RC_common_props) / sizeof (txprop_t);
218 218 int Fn_propcnt = sizeof (Fn_common_props) / sizeof (txprop_t);
219 219
220 220 /*
221 221 * If this devinfo node came originally from OBP data, we'll have prom
222 222 * properties associated with the node where we can find properties of
223 223 * interest. We ignore anything after the the first four bytes of the
224 224 * property, and interpet those first four bytes as our unsigned
225 225 * integer. If we don't find the property or it's not large enough,
226 226 * 'val' will remained unchanged and we'll return -1. Otherwise 'val'
227 227 * gets updated with the property value and we return 0.
228 228 */
229 229 static int
230 230 promprop2uint(topo_mod_t *mod, di_node_t n, const char *propnm, uint_t *val)
231 231 {
232 232 di_prom_handle_t ptp = DI_PROM_HANDLE_NIL;
233 233 di_prom_prop_t pp = DI_PROM_PROP_NIL;
234 234 uchar_t *buf;
235 235
236 236 if ((ptp = topo_mod_prominfo(mod)) == DI_PROM_HANDLE_NIL)
237 237 return (-1);
238 238
239 239 while ((pp = di_prom_prop_next(ptp, n, pp)) != DI_PROM_PROP_NIL) {
240 240 if (strcmp(di_prom_prop_name(pp), propnm) == 0) {
241 241 if (di_prom_prop_data(pp, &buf) < sizeof (uint_t))
242 242 continue;
243 243 bcopy(buf, val, sizeof (uint_t));
244 244 return (0);
245 245 }
246 246 }
247 247 return (-1);
248 248 }
249 249
250 250 /*
251 251 * If this devinfo node was added by the PCI hotplug framework it
252 252 * doesn't have the PROM properties, but hopefully has the properties
253 253 * we're looking for attached directly to the devinfo node. We only
254 254 * care about the first four bytes of the property, which we read as
255 255 * our unsigned integer. The remaining bytes are ignored. If we
256 256 * don't find the property we're looking for, or can't get its value,
257 257 * 'val' remains unchanged and we return -1. Otherwise 'val' gets the
258 258 * property value and we return 0.
259 259 */
260 260 static int
261 261 hwprop2uint(di_node_t n, const char *propnm, uint_t *val)
262 262 {
263 263 di_prop_t hp = DI_PROP_NIL;
264 264 uchar_t *buf;
265 265
266 266 while ((hp = di_prop_next(n, hp)) != DI_PROP_NIL) {
267 267 if (strcmp(di_prop_name(hp), propnm) == 0) {
268 268 if (di_prop_bytes(hp, &buf) < sizeof (uint_t))
269 269 continue;
270 270 bcopy(buf, val, sizeof (uint_t));
271 271 return (0);
272 272 }
273 273 }
274 274 return (-1);
275 275 }
276 276
277 277 int
278 278 di_uintprop_get(topo_mod_t *mod, di_node_t n, const char *pnm, uint_t *pv)
279 279 {
280 280 if (hwprop2uint(n, pnm, pv) < 0)
281 281 if (promprop2uint(mod, n, pnm, pv) < 0)
282 282 return (-1);
283 283 return (0);
284 284 }
285 285
286 286 int
287 287 di_bytes_get(topo_mod_t *mod, di_node_t n, const char *pnm, int *sz,
288 288 uchar_t **db)
289 289 {
290 290 di_prom_handle_t ptp = DI_PROM_HANDLE_NIL;
291 291 di_prom_prop_t pp = DI_PROM_PROP_NIL;
292 292 di_prop_t hp = DI_PROP_NIL;
293 293
294 294 if ((ptp = topo_mod_prominfo(mod)) == DI_PROM_HANDLE_NIL)
295 295 return (-1);
296 296
297 297 *sz = -1;
298 298 while ((hp = di_prop_next(n, hp)) != DI_PROP_NIL) {
299 299 if (strcmp(di_prop_name(hp), pnm) == 0) {
300 300 if ((*sz = di_prop_bytes(hp, db)) < 0)
301 301 continue;
302 302 break;
303 303 }
304 304 }
305 305 if (*sz < 0) {
306 306 while ((pp = di_prom_prop_next(ptp, n, pp)) !=
307 307 DI_PROM_PROP_NIL) {
308 308 if (strcmp(di_prom_prop_name(pp), pnm) == 0) {
309 309 *sz = di_prom_prop_data(pp, db);
310 310 if (*sz < 0)
311 311 continue;
312 312 break;
313 313 }
314 314 }
315 315 }
316 316
317 317 if (*sz < 0)
318 318 return (-1);
319 319 return (0);
320 320 }
321 321
322 322 /*
323 323 * fix_dev_prop -- sometimes di_devfs_path() doesn't tell the whole
324 324 * story, leaving off the device and function number. Chances are if
325 325 * devfs doesn't put these on then we'll never see this device as an
326 326 * error detector called out in an ereport. Unfortunately, there are
327 327 * races and we sometimes do get ereports from devices that devfs
328 328 * decides aren't there. For example, the error injector card seems
329 329 * to bounce in and out of existence according to devfs. We tack on
330 330 * the missing dev and fn here so that the DEV property used to look
331 331 * up the topology node is correct.
332 332 */
333 333 static char *
334 334 dev_path_fix(topo_mod_t *mp, char *path, int devno, int fnno)
335 335 {
336 336 char *lastslash;
337 337 char *newpath;
338 338 int need;
339 339
340 340 /*
341 341 * We only care about the last component of the dev path. If
342 342 * we don't find a slash, something is weird.
343 343 */
344 344 lastslash = strrchr(path, '/');
345 345 assert(lastslash != NULL);
346 346
347 347 /*
348 348 * If an @ sign is present in the last component, the
349 349 * di_devfs_path() result had the device,fn unit-address.
350 350 * In that case there's nothing we need do.
351 351 */
352 352 if (strchr(lastslash, '@') != NULL)
353 353 return (path);
354 354
355 355 if (fnno == 0)
356 356 need = snprintf(NULL, 0, "%s@%x", path, devno);
357 357 else
358 358 need = snprintf(NULL, 0, "%s@%x,%x", path, devno, fnno);
359 359 need++;
360 360
361 361 if ((newpath = topo_mod_alloc(mp, need)) == NULL) {
362 362 topo_mod_strfree(mp, path);
363 363 return (NULL);
364 364 }
365 365
366 366 if (fnno == 0)
367 367 (void) snprintf(newpath, need, "%s@%x", path, devno);
368 368 else
369 369 (void) snprintf(newpath, need, "%s@%x,%x", path, devno, fnno);
370 370
371 371 topo_mod_strfree(mp, path);
372 372 return (newpath);
373 373 }
374 374
375 375 /*
376 376 * dev_for_hostbridge() -- For hostbridges we truncate the devfs path
377 377 * after the first element in the bus address.
378 378 */
379 379 static char *
380 380 dev_for_hostbridge(topo_mod_t *mp, char *path)
381 381 {
382 382 char *lastslash;
383 383 char *newpath;
384 384 char *comma;
385 385 int plen;
386 386
387 387 plen = strlen(path) + 1;
388 388
389 389 /*
390 390 * We only care about the last component of the dev path. If
391 391 * we don't find a slash, something is weird.
392 392 */
393 393 lastslash = strrchr(path, '/');
394 394 assert(lastslash != NULL);
395 395
396 396 /*
397 397 * Find the comma in the last component component@x,y, and
398 398 * truncate the comma and any following number.
399 399 */
400 400 comma = strchr(lastslash, ',');
401 401 assert(comma != NULL);
402 402
403 403 *comma = '\0';
404 404 if ((newpath = topo_mod_strdup(mp, path)) == NULL) {
405 405 topo_mod_free(mp, path, plen);
406 406 return (NULL);
407 407 }
408 408
409 409 *comma = ',';
410 410 topo_mod_free(mp, path, plen);
411 411 return (newpath);
412 412 }
413 413
414 414 /*ARGSUSED*/
415 415 static int
416 416 ASRU_set(tnode_t *tn, did_t *pd,
417 417 const char *dpnm, const char *tpgrp, const char *tpnm)
418 418 {
419 419 topo_mod_t *mp;
420 420 nvlist_t *fmri;
421 421 char *dnpath, *path, *fpath, *nm;
422 422 int d, e, f;
423 423
424 424 /*
425 425 * If this topology node represents a function of device,
426 426 * set the ASRU to a dev scheme FMRI based on the value of
427 427 * di_devfs_path(). If that path is NULL, set the ASRU to
428 428 * be the resource describing this topology node. If this
429 429 * isn't a function, inherit any ASRU from the parent.
430 430 */
431 431 mp = did_mod(pd);
432 432 nm = topo_node_name(tn);
433 433 if ((strcmp(nm, PCI_BUS) == 0 && did_gettnode(pd) &&
434 434 strcmp(topo_node_name(did_gettnode(pd)), HOSTBRIDGE) == 0) ||
435 435 strcmp(nm, PCI_FUNCTION) == 0 || strcmp(nm, PCIEX_FUNCTION) == 0 ||
436 436 strcmp(nm, PCIEX_ROOT) == 0) {
437 437 if ((dnpath = di_devfs_path(did_dinode(pd))) != NULL) {
438 438 /*
439 439 * Dup the path, dev_path_fix() may replace it and
440 440 * dev_path_fix() wouldn't know to use
441 441 * di_devfs_path_free()
442 442 */
443 443 if ((path = topo_mod_strdup(mp, dnpath)) == NULL) {
444 444 di_devfs_path_free(dnpath);
445 445 return (topo_mod_seterrno(mp, EMOD_NOMEM));
446 446 }
447 447 di_devfs_path_free(dnpath);
448 448 did_BDF(pd, NULL, &d, &f);
449 449 if ((fpath = dev_path_fix(mp, path, d, f)) == NULL)
450 450 return (topo_mod_seterrno(mp, EMOD_NOMEM));
451 451
452 452 fmri = topo_mod_devfmri(mp, FM_DEV_SCHEME_VERSION,
453 453 fpath, NULL);
454 454 if (fmri == NULL) {
455 455 topo_mod_dprintf(mp,
456 456 "dev:///%s fmri creation failed.\n", fpath);
457 457 topo_mod_strfree(mp, fpath);
458 458 return (-1);
459 459 }
460 460 topo_mod_strfree(mp, fpath);
461 461 } else {
462 462 topo_mod_dprintf(mp, "NULL di_devfs_path.\n");
463 463 if (topo_prop_get_fmri(tn, TOPO_PGROUP_PROTOCOL,
464 464 TOPO_PROP_RESOURCE, &fmri, &e) < 0)
465 465 return (topo_mod_seterrno(mp, e));
466 466 }
467 467 if (topo_node_asru_set(tn, fmri, 0, &e) < 0) {
468 468 nvlist_free(fmri);
469 469 return (topo_mod_seterrno(mp, e));
470 470 }
471 471 nvlist_free(fmri);
472 472 return (0);
473 473 }
474 474 (void) topo_node_asru_set(tn, NULL, 0, &e);
475 475
476 476 return (0);
477 477 }
478 478
479 479 /*
480 480 * Set the FRU property to the hc fmri of this tnode
481 481 */
482 482 int
483 483 FRU_fmri_set(topo_mod_t *mp, tnode_t *tn)
484 484 {
485 485 nvlist_t *fmri;
486 486 int err, e;
487 487
488 488 if (topo_node_resource(tn, &fmri, &err) < 0 ||
489 489 fmri == NULL) {
490 490 topo_mod_dprintf(mp, "FRU_fmri_set error: %s\n",
491 491 topo_strerror(topo_mod_errno(mp)));
492 492 return (topo_mod_seterrno(mp, err));
493 493 }
494 494 e = topo_node_fru_set(tn, fmri, 0, &err);
495 495 nvlist_free(fmri);
496 496 if (e < 0)
497 497 return (topo_mod_seterrno(mp, err));
498 498 return (0);
499 499 }
500 500
501 501 tnode_t *
502 502 find_predecessor(tnode_t *tn, char *mod_name)
503 503 {
504 504 tnode_t *pnode = topo_node_parent(tn);
505 505
506 506 while (pnode && (strcmp(topo_node_name(pnode), mod_name) != 0)) {
507 507 pnode = topo_node_parent(pnode);
508 508 }
509 509 return (pnode);
510 510 }
511 511
512 512 static int
513 513 use_predecessor_fru(tnode_t *tn, char *mod_name)
514 514 {
515 515 tnode_t *pnode = NULL;
516 516 nvlist_t *fru = NULL;
517 517 int err = 0;
518 518
519 519 if ((pnode = find_predecessor(tn, mod_name)) == NULL)
520 520 return (-1);
521 521 if ((pnode = topo_node_parent(pnode)) == NULL)
522 522 return (-1);
523 523 if (topo_node_fru(pnode, &fru, NULL, &err) != 0)
524 524 return (-1);
525 525
526 526 (void) topo_node_fru_set(tn, fru, 0, &err);
527 527 nvlist_free(fru);
528 528
529 529 return (0);
530 530 }
531 531
532 532 static int
533 533 use_predecessor_label(topo_mod_t *mod, tnode_t *tn, char *mod_name)
534 534 {
535 535 tnode_t *pnode = NULL;
536 536 int err = 0;
537 537 char *plabel = NULL;
538 538
539 539 if ((pnode = find_predecessor(tn, mod_name)) == NULL)
540 540 return (-1);
541 541 if ((pnode = topo_node_parent(pnode)) == NULL)
542 542 return (-1);
543 543 if (topo_node_label(pnode, &plabel, &err) != 0 || plabel == NULL)
544 544 return (-1);
545 545
546 546 (void) topo_node_label_set(tn, plabel, &err);
547 547
548 548 topo_mod_strfree(mod, plabel);
549 549
550 550 return (0);
551 551 }
552 552
553 553
554 554 /*ARGSUSED*/
555 555 static int
556 556 FRU_set(tnode_t *tn, did_t *pd,
557 557 const char *dpnm, const char *tpgrp, const char *tpnm)
558 558 {
559 559 topo_mod_t *mp;
560 560 char *nm;
561 561 int e = 0, err = 0;
562 562
563 563 nm = topo_node_name(tn);
564 564 mp = did_mod(pd);
565 565
566 566 /*
567 567 * If this is a PCIEX_BUS and its parent is a PCIEX_ROOT,
568 568 * check for a CPUBOARD predecessor. If found, inherit its
569 569 * parent's FRU. Otherwise, continue with FRU set.
570 570 */
571 571 if ((strcmp(nm, PCIEX_BUS) == 0) &&
572 572 (strcmp(topo_node_name(topo_node_parent(tn)), PCIEX_ROOT) == 0)) {
573 573
574 574 if (use_predecessor_fru(tn, CPUBOARD) == 0)
575 575 return (0);
576 576 }
577 577 /*
578 578 * If this topology node represents something other than an
579 579 * ioboard or a device that implements a slot, inherit the
580 580 * parent's FRU value. If there is no label, inherit our
581 581 * parent's FRU value. Otherwise, munge up an fmri based on
582 582 * the label.
583 583 */
584 584 if (strcmp(nm, IOBOARD) != 0 && strcmp(nm, PCI_DEVICE) != 0 &&
585 585 strcmp(nm, PCIEX_DEVICE) != 0 && strcmp(nm, PCIEX_BUS) != 0) {
586 586 (void) topo_node_fru_set(tn, NULL, 0, &e);
587 587 return (0);
588 588 }
589 589
590 590 /*
591 591 * If ioboard, set fru fmri to hc fmri
592 592 */
593 593 if (strcmp(nm, IOBOARD) == 0) {
594 594 e = FRU_fmri_set(mp, tn);
595 595 return (e);
596 596 } else if (strcmp(nm, PCI_DEVICE) == 0 ||
597 597 strcmp(nm, PCIEX_DEVICE) == 0 || strcmp(nm, PCIEX_BUS) == 0) {
598 598 nvlist_t *in, *out;
599 599
600 600 mp = did_mod(pd);
601 601 if (topo_mod_nvalloc(mp, &in, NV_UNIQUE_NAME) != 0)
602 602 return (topo_mod_seterrno(mp, EMOD_FMRI_NVL));
603 603 if (nvlist_add_uint64(in, "nv1", (uintptr_t)pd) != 0) {
604 604 nvlist_free(in);
↓ open down ↓ |
604 lines elided |
↑ open up ↑ |
605 605 return (topo_mod_seterrno(mp, EMOD_NOMEM));
606 606 }
607 607 if (topo_method_invoke(tn,
608 608 TOPO_METH_FRU_COMPUTE, TOPO_METH_FRU_COMPUTE_VERSION,
609 609 in, &out, &err) != 0) {
610 610 nvlist_free(in);
611 611 return (topo_mod_seterrno(mp, err));
612 612 }
613 613 nvlist_free(in);
614 614 (void) topo_node_fru_set(tn, out, 0, &err);
615 - if (out != NULL)
616 - nvlist_free(out);
615 + nvlist_free(out);
617 616 } else
618 617 (void) topo_node_fru_set(tn, NULL, 0, &err);
619 618
620 619 return (0);
621 620 }
622 621
623 622 /*ARGSUSED*/
624 623 static int
625 624 label_set(tnode_t *tn, did_t *pd,
626 625 const char *dpnm, const char *tpgrp, const char *tpnm)
627 626 {
628 627 topo_mod_t *mp;
629 628 nvlist_t *in, *out;
630 629 char *label;
631 630 int err;
632 631
633 632 mp = did_mod(pd);
634 633 /*
635 634 * If this is a PCIEX_BUS and its parent is a PCIEX_ROOT,
636 635 * check for a CPUBOARD predecessor. If found, inherit its
637 636 * parent's Label. Otherwise, continue with label set.
638 637 */
639 638 if ((strcmp(topo_node_name(tn), PCIEX_BUS) == 0) &&
640 639 (strcmp(topo_node_name(topo_node_parent(tn)), PCIEX_ROOT) == 0)) {
641 640
642 641 if (use_predecessor_label(mp, tn, CPUBOARD) == 0)
643 642 return (0);
644 643 }
645 644 if (topo_mod_nvalloc(mp, &in, NV_UNIQUE_NAME) != 0)
646 645 return (topo_mod_seterrno(mp, EMOD_FMRI_NVL));
647 646 if (nvlist_add_uint64(in, TOPO_METH_LABEL_ARG_NVL, (uintptr_t)pd) !=
648 647 0) {
649 648 nvlist_free(in);
650 649 return (topo_mod_seterrno(mp, EMOD_NOMEM));
651 650 }
652 651 if (topo_method_invoke(tn,
653 652 TOPO_METH_LABEL, TOPO_METH_LABEL_VERSION, in, &out, &err) != 0) {
654 653 nvlist_free(in);
655 654 return (topo_mod_seterrno(mp, err));
656 655 }
657 656 nvlist_free(in);
658 657 if (out != NULL &&
659 658 nvlist_lookup_string(out, TOPO_METH_LABEL_RET_STR, &label) == 0) {
660 659 if (topo_prop_set_string(tn, TOPO_PGROUP_PROTOCOL,
661 660 TOPO_PROP_LABEL, TOPO_PROP_IMMUTABLE, label, &err) != 0) {
662 661 nvlist_free(out);
663 662 return (topo_mod_seterrno(mp, err));
664 663 }
665 664 nvlist_free(out);
666 665 }
667 666 return (0);
668 667 }
669 668
670 669 /*ARGSUSED*/
671 670 static int
672 671 EXCAP_set(tnode_t *tn, did_t *pd,
673 672 const char *dpnm, const char *tpgrp, const char *tpnm)
674 673 {
675 674 int excap = did_excap(pd);
676 675 int err;
677 676 int e = 0;
678 677
679 678 switch (excap & PCIE_PCIECAP_DEV_TYPE_MASK) {
680 679 case PCIE_PCIECAP_DEV_TYPE_ROOT:
681 680 e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
682 681 TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCIEX_ROOT, &err);
683 682 break;
684 683 case PCIE_PCIECAP_DEV_TYPE_UP:
685 684 e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
686 685 TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCIEX_SWUP, &err);
687 686 break;
688 687 case PCIE_PCIECAP_DEV_TYPE_DOWN:
689 688 e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
690 689 TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCIEX_SWDWN, &err);
691 690 break;
692 691 case PCIE_PCIECAP_DEV_TYPE_PCI2PCIE:
693 692 e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
694 693 TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCIEX_BUS, &err);
695 694 break;
696 695 case PCIE_PCIECAP_DEV_TYPE_PCIE2PCI:
697 696 e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
698 697 TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCI_BUS, &err);
699 698 break;
700 699 case PCIE_PCIECAP_DEV_TYPE_PCIE_DEV:
701 700 e = topo_prop_set_string(tn, TOPO_PGROUP_PCI,
702 701 TOPO_PCI_EXCAP, TOPO_PROP_IMMUTABLE, PCIEX_DEVICE, &err);
703 702 break;
704 703 }
705 704 if (e != 0)
706 705 return (topo_mod_seterrno(did_mod(pd), err));
707 706 return (0);
708 707 }
709 708
710 709 /*ARGSUSED*/
711 710 static int
712 711 DEVprop_set(tnode_t *tn, did_t *pd,
713 712 const char *dpnm, const char *tpgrp, const char *tpnm)
714 713 {
715 714 topo_mod_t *mp;
716 715 char *dnpath;
717 716 char *path, *fpath;
718 717 int d, f;
719 718 int err, e;
720 719
721 720 mp = did_mod(pd);
722 721 if ((dnpath = di_devfs_path(did_dinode(pd))) == NULL) {
723 722 topo_mod_dprintf(mp, "NULL di_devfs_path.\n");
724 723 return (topo_mod_seterrno(mp, ETOPO_PROP_NOENT));
725 724 }
726 725 if ((path = topo_mod_strdup(mp, dnpath)) == NULL) {
727 726 di_devfs_path_free(dnpath);
728 727 return (-1);
729 728 }
730 729 di_devfs_path_free(dnpath);
731 730
732 731 /* The DEV path is modified for hostbridges */
733 732 if (strcmp(topo_node_name(tn), HOSTBRIDGE) == 0) {
734 733 fpath = dev_for_hostbridge(did_mod(pd), path);
735 734 } else {
736 735 did_BDF(pd, NULL, &d, &f);
737 736 fpath = dev_path_fix(mp, path, d, f);
738 737 }
739 738 if (fpath == NULL)
740 739 return (-1);
741 740 e = topo_prop_set_string(tn,
742 741 tpgrp, tpnm, TOPO_PROP_IMMUTABLE, fpath, &err);
743 742 topo_mod_strfree(mp, fpath);
744 743 if (e != 0)
745 744 return (topo_mod_seterrno(mp, err));
746 745 return (0);
747 746 }
748 747
749 748 /*ARGSUSED*/
750 749 static int
751 750 DRIVERprop_set(tnode_t *tn, did_t *pd,
752 751 const char *dpnm, const char *tpgrp, const char *tpnm)
753 752 {
754 753 char *dnm;
755 754 int err;
756 755
757 756 if ((dnm = di_driver_name(did_dinode(pd))) == NULL)
758 757 return (0);
759 758 if (topo_prop_set_string(tn,
760 759 tpgrp, tpnm, TOPO_PROP_IMMUTABLE, dnm, &err) < 0)
761 760 return (topo_mod_seterrno(did_mod(pd), err));
762 761
763 762 return (0);
764 763 }
765 764
766 765 /*ARGSUSED*/
767 766 static int
768 767 MODULEprop_set(tnode_t *tn, did_t *pd,
769 768 const char *dpnm, const char *tpgrp, const char *tpnm)
770 769 {
771 770 nvlist_t *mod;
772 771 topo_mod_t *mp;
773 772 char *dnm;
774 773 int err;
775 774
776 775 if ((dnm = di_driver_name(did_dinode(pd))) == NULL)
777 776 return (0);
778 777
779 778 mp = did_mod(pd);
780 779 if ((mod = topo_mod_modfmri(mp, FM_MOD_SCHEME_VERSION, dnm)) == NULL)
781 780 return (0); /* driver maybe detached, return success */
782 781
783 782 if (topo_prop_set_fmri(tn, tpgrp, tpnm, TOPO_PROP_IMMUTABLE, mod,
784 783 &err) < 0) {
785 784 nvlist_free(mod);
786 785 return (topo_mod_seterrno(mp, err));
787 786 }
788 787 nvlist_free(mod);
789 788
790 789 return (0);
791 790 }
792 791
793 792 /*ARGSUSED*/
794 793 static int
795 794 maybe_di_chars_copy(tnode_t *tn, did_t *pd,
796 795 const char *dpnm, const char *tpgrp, const char *tpnm)
797 796 {
798 797 topo_mod_t *mp;
799 798 uchar_t *typbuf;
800 799 char *tmpbuf;
801 800 int sz = -1;
802 801 int err, e;
803 802
804 803 if (di_bytes_get(did_mod(pd), did_dinode(pd), dpnm, &sz, &typbuf) < 0)
805 804 return (0);
806 805 mp = did_mod(pd);
807 806
808 807 if ((tmpbuf = topo_mod_alloc(mp, sz + 1)) == NULL)
809 808 return (topo_mod_seterrno(mp, EMOD_NOMEM));
810 809
811 810 bcopy(typbuf, tmpbuf, sz);
812 811 tmpbuf[sz] = 0;
813 812 e = topo_prop_set_string(tn,
814 813 tpgrp, tpnm, TOPO_PROP_IMMUTABLE, tmpbuf, &err);
815 814 topo_mod_free(mp, tmpbuf, sz + 1);
816 815 if (e != 0)
817 816 return (topo_mod_seterrno(mp, err));
818 817 return (0);
819 818 }
820 819
821 820 static int
822 821 uint_to_strprop(topo_mod_t *mp, uint_t v, tnode_t *tn,
823 822 const char *tpgrp, const char *tpnm)
824 823 {
825 824 char str[21]; /* sizeof (UINT64_MAX) + '\0' */
826 825 int e;
827 826
828 827 (void) snprintf(str, 21, "%x", v);
829 828 if (topo_prop_set_string(tn,
830 829 tpgrp, tpnm, TOPO_PROP_IMMUTABLE, str, &e) < 0)
831 830 return (topo_mod_seterrno(mp, e));
832 831 return (0);
833 832 }
834 833
835 834 static int
836 835 maybe_di_uint_to_str(tnode_t *tn, did_t *pd,
837 836 const char *dpnm, const char *tpgrp, const char *tpnm)
838 837 {
839 838 uint_t v;
840 839
841 840 if (di_uintprop_get(did_mod(pd), did_dinode(pd), dpnm, &v) < 0)
842 841 return (0);
843 842
844 843 return (uint_to_strprop(did_mod(pd), v, tn, tpgrp, tpnm));
845 844 }
846 845
847 846 static int
848 847 uint_to_dec_strprop(topo_mod_t *mp, uint_t v, tnode_t *tn,
849 848 const char *tpgrp, const char *tpnm)
850 849 {
851 850 char str[21]; /* sizeof (UINT64_MAX) + '\0' */
852 851 int e;
853 852
854 853 (void) snprintf(str, 21, "%d", v);
855 854 if (topo_prop_set_string(tn,
856 855 tpgrp, tpnm, TOPO_PROP_IMMUTABLE, str, &e) < 0)
857 856 return (topo_mod_seterrno(mp, e));
858 857 return (0);
859 858 }
860 859
861 860 static int
862 861 maybe_di_uint_to_dec_str(tnode_t *tn, did_t *pd,
863 862 const char *dpnm, const char *tpgrp, const char *tpnm)
864 863 {
865 864 uint_t v;
866 865
867 866 if (di_uintprop_get(did_mod(pd), did_dinode(pd), dpnm, &v) < 0)
868 867 return (0);
869 868
870 869 return (uint_to_dec_strprop(did_mod(pd), v, tn, tpgrp, tpnm));
871 870 }
872 871
873 872 static int
874 873 AADDR_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp,
875 874 const char *tpnm)
876 875 {
877 876 topo_mod_t *mp;
878 877 uchar_t *typbuf;
879 878 int sz = -1;
880 879 int err, e;
881 880
882 881 if (di_bytes_get(did_mod(pd), did_dinode(pd), dpnm, &sz, &typbuf) < 0)
883 882 return (0);
884 883
885 884 mp = did_mod(pd);
886 885
887 886 e = topo_prop_set_uint32_array(tn, tpgrp, tpnm, TOPO_PROP_IMMUTABLE,
888 887 /*LINTED*/
889 888 (uint32_t *)typbuf, sz/4, &err);
890 889
891 890 if (e != 0)
892 891 return (topo_mod_seterrno(mp, err));
893 892 return (0);
894 893 }
895 894
896 895 /*ARGSUSED*/
897 896 static int
898 897 BDF_set(tnode_t *tn, did_t *pd, const char *dpnm, const char *tpgrp,
899 898 const char *tpnm)
900 899 {
901 900 int bdf;
902 901 char str[23]; /* '0x' + sizeof (UINT64_MAX) + '\0' */
903 902 int e;
904 903
905 904 if ((bdf = did_bdf(pd)) <= 0)
906 905 return (0);
907 906
908 907 (void) snprintf(str, 23, "0x%x", bdf);
909 908 if (topo_prop_set_string(tn,
910 909 tpgrp, tpnm, TOPO_PROP_IMMUTABLE, str, &e) < 0)
911 910 return (topo_mod_seterrno(did_mod(pd), e));
912 911 return (0);
913 912 }
914 913
915 914 int
916 915 did_props_set(tnode_t *tn, did_t *pd, txprop_t txarray[], int txnum)
917 916 {
918 917 topo_mod_t *mp;
919 918 int i, r, e;
920 919
921 920 mp = did_mod(pd);
922 921 for (i = 0; i < txnum; i++) {
923 922 /*
924 923 * Ensure the property group has been created.
925 924 */
926 925 if (txarray[i].tx_tpgroup != NULL) {
927 926 if (topo_pgroup_create(tn, txarray[i].tx_tpgroup, &e)
928 927 < 0) {
929 928 if (e != ETOPO_PROP_DEFD)
930 929 return (topo_mod_seterrno(mp, e));
931 930 }
932 931 }
933 932
934 933 topo_mod_dprintf(mp,
935 934 "Setting property %s in group %s.\n",
936 935 txarray[i].tx_tprop, txarray[i].tx_tpgroup->tpi_name);
937 936 r = txarray[i].tx_xlate(tn, pd,
938 937 txarray[i].tx_diprop, txarray[i].tx_tpgroup->tpi_name,
939 938 txarray[i].tx_tprop);
940 939 if (r != 0) {
941 940 topo_mod_dprintf(mp, "failed.\n");
942 941 topo_mod_dprintf(mp, "Error was %s.\n",
943 942 topo_strerror(topo_mod_errno(mp)));
944 943 return (-1);
945 944 }
946 945 topo_mod_dprintf(mp, "succeeded.\n");
947 946 }
948 947 return (0);
949 948 }
↓ open down ↓ |
323 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX