Print this page
9637 Memleak in pcibus.so`pci_slot_label_lookup.
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/fm/topo/modules/common/pcibus/pcibus_labels.c
+++ new/usr/src/lib/fm/topo/modules/common/pcibus/pcibus_labels.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 (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 #include <alloca.h>
27 27 #include <assert.h>
28 28 #include <fm/topo_mod.h>
29 29 #include <libnvpair.h>
30 30 #include <string.h>
31 31 #include <sys/fm/protocol.h>
32 32
33 33 #include <did.h>
34 34 #include <pcibus.h>
35 35 #include <pcibus_labels.h>
36 36
37 37 extern slotnm_rewrite_t *Slot_Rewrites;
38 38 extern physlot_names_t *Physlot_Names;
39 39 extern missing_names_t *Missing_Names;
40 40
41 41 /*
42 42 * Do a platform specific label lookup based on physical slot number.
43 43 */
44 44 static const char *
45 45 pci_label_physlot_lookup(topo_mod_t *mod, char *platform, did_t *dp)
46 46 {
47 47 const char *rlabel = NULL;
48 48 int n, p, i;
49 49
50 50 topo_mod_dprintf(mod, "%s: doing a lookup for platform=%s\n",
51 51 __func__, platform);
52 52
53 53 if ((n = did_physlot(dp)) < 0 || Physlot_Names == NULL ||
54 54 platform == NULL)
55 55 return (NULL);
56 56
57 57 topo_mod_dprintf(mod, "%s: doing a lookup for physlot=%d\n",
58 58 __func__, n);
59 59
60 60 for (p = 0; p < Physlot_Names->psn_nplats; p++) {
61 61 topo_mod_dprintf(mod, "%s: comparing against platform=%s\n",
62 62 __func__, Physlot_Names->psn_names[p].pnm_platform);
63 63 if (strcasecmp(Physlot_Names->psn_names[p].pnm_platform,
64 64 platform) != 0)
65 65 continue;
66 66 topo_mod_dprintf(mod, "%s: found lookup table for this "
67 67 "platform\n", __func__);
68 68 for (i = 0; i < Physlot_Names->psn_names[p].pnm_nnames; i++) {
69 69 physnm_t ps;
70 70 ps = Physlot_Names->psn_names[p].pnm_names[i];
71 71 if (ps.ps_num == n) {
72 72 topo_mod_dprintf(mod, "%s: matched entry=%d, "
73 73 "label=%s\n", __func__, i, ps.ps_label);
74 74 rlabel = ps.ps_label;
75 75 break;
76 76 }
77 77 }
78 78 break;
79 79 }
80 80 if (rlabel != NULL) {
81 81 topo_mod_dprintf(mod, "%s: returning label=%s\n",
82 82 __func__, rlabel);
83 83 }
84 84 return (rlabel);
85 85 }
86 86
87 87 /*
88 88 * Do a platform specific label lookup based on slot name.
89 89 */
90 90 static const char *
91 91 pci_label_slotname_lookup(topo_mod_t *mod, char *platform,
92 92 const char *label, did_t *dp)
93 93 {
94 94 const char *rlabel = label;
95 95 int s, i, ret;
96 96
97 97 if (Slot_Rewrites == NULL || platform == NULL)
98 98 return (rlabel);
99 99
100 100 topo_mod_dprintf(mod, "%s: doing a lookup for platform=%s\n",
101 101 __func__, platform);
102 102
103 103 for (s = 0; s < Slot_Rewrites->srw_nplats; s++) {
104 104 topo_mod_dprintf(mod, "%s: comparing against platform=%s\n",
105 105 __func__, Slot_Rewrites->srw_platrewrites[s].prw_platform);
106 106 if (strcasecmp(Slot_Rewrites->srw_platrewrites[s].prw_platform,
107 107 platform) != 0)
108 108 continue;
109 109 topo_mod_dprintf(mod, "%s: found lookup table for this "
110 110 "platform\n", __func__);
111 111 for (i = 0;
112 112 i < Slot_Rewrites->srw_platrewrites[s].prw_nrewrites;
113 113 i++) {
114 114 slot_rwd_t rw;
115 115 rw = Slot_Rewrites->srw_platrewrites[s].prw_rewrites[i];
116 116 if (strcmp(rw.srw_obp, label) == 0) {
117 117 topo_mod_dprintf(mod, "%s: matched entry=%d, "
118 118 "old_label=%s, new_label=%s\n",
119 119 __func__, i, rw.srw_obp,
120 120 rw.srw_new ? rw.srw_new : NULL);
121 121 /*
122 122 * If a test function is specified then call
123 123 * it to do an additional check.
124 124 */
125 125 if (rw.srw_test != NULL) {
126 126 topo_mod_dprintf(mod,
127 127 "%s: calling test function=%p\n",
128 128 __func__, rw.srw_test);
129 129 if (ret = rw.srw_test(mod, dp))
130 130 rlabel = rw.srw_new;
131 131 topo_mod_dprintf(mod,
132 132 "%s: test function return=%d\n",
133 133 __func__, ret);
134 134 } else {
135 135 rlabel = rw.srw_new;
136 136 }
137 137 break;
138 138 }
139 139 }
140 140 break;
141 141 }
142 142 topo_mod_dprintf(mod, "%s: returning label=%s\n", __func__,
143 143 rlabel ? rlabel : "NULL");
144 144 return (rlabel);
145 145 }
146 146
147 147 /*
148 148 * Do a platform specific label lookup based on bus, dev, etc.
149 149 */
150 150 static const char *
151 151 pci_label_missing_lookup(topo_mod_t *mod, char *platform, did_t *dp)
152 152 {
153 153 const char *rlabel = NULL;
154 154 int board, bridge, rc, bus, dev;
155 155 int p, i, ret;
156 156
157 157 if (Missing_Names == NULL || platform == NULL)
158 158 return (NULL);
159 159
160 160 bridge = did_bridge(dp);
161 161 board = did_board(dp);
162 162 rc = did_rc(dp);
163 163 did_BDF(dp, &bus, &dev, NULL);
164 164
165 165 topo_mod_dprintf(mod, "%s: doing a lookup for platform=%s, "
166 166 "board=%d, bridge=%d, rc=%d, bus=%d, dev=%d\n",
167 167 __func__, platform, board, bridge, rc, bus, dev);
168 168
169 169 for (p = 0; p < Missing_Names->mn_nplats; p++) {
170 170 topo_mod_dprintf(mod, "%s: comparing against platform=%s\n",
171 171 __func__, Missing_Names->mn_names[p].pdl_platform);
172 172 if (strcasecmp(Missing_Names->mn_names[p].pdl_platform,
173 173 platform) != 0)
174 174 continue;
175 175 topo_mod_dprintf(mod, "%s: found lookup table for this "
176 176 "platform\n", __func__);
177 177 for (i = 0; i < Missing_Names->mn_names[p].pdl_nnames; i++) {
178 178 devlab_t m;
179 179 m = Missing_Names->mn_names[p].pdl_names[i];
180 180 if (m.dl_board == board && m.dl_bridge == bridge &&
181 181 m.dl_rc == rc &&
182 182 (m.dl_bus == -1 || m.dl_bus == bus) &&
183 183 (m.dl_dev == -1 || m.dl_dev == dev)) {
184 184 topo_mod_dprintf(mod, "%s: matched entry=%d, "
185 185 "label=%s\n", __func__, i, m.dl_label);
186 186 /*
187 187 * If a test function is specified then call
188 188 * it to do an additional test.
189 189 */
190 190 if (m.dl_test != NULL) {
191 191 topo_mod_dprintf(mod,
192 192 "%s: calling test function=%p\n",
193 193 __func__, m.dl_test);
194 194 if (ret = m.dl_test(mod, dp))
195 195 rlabel = m.dl_label;
196 196 topo_mod_dprintf(mod,
197 197 "%s: test function return=%d\n",
198 198 __func__, ret);
199 199 if (ret)
200 200 break;
201 201 } else {
202 202 rlabel = m.dl_label;
203 203 break;
204 204 }
205 205 }
206 206 }
207 207 break;
208 208 }
209 209 if (rlabel != NULL) {
210 210 topo_mod_dprintf(mod, "%s: match found, label=%s\n",
211 211 __func__, rlabel);
212 212 }
213 213 return (rlabel);
↓ open down ↓ |
213 lines elided |
↑ open up ↑ |
214 214 }
215 215
216 216 /*
217 217 * Do an overall slot label lookup for the device node.
218 218 */
219 219 char *
220 220 pci_slot_label_lookup(topo_mod_t *mod, tnode_t *node, did_t *dp, did_t *pdp)
221 221 {
222 222 tnode_t *anode, *apnode;
223 223 did_t *adp, *apdp;
224 - char *plat, *pp, *l, *ancestor_l = NULL, *new_l = NULL;
224 + char *plat, *pp, *l = NULL, *ancestor_l = NULL, *new_l = NULL;
225 225 int err, b, d, f, done = 0;
226 226 size_t len;
227 227
228 228 did_BDF(dp, &b, &d, &f);
229 229
230 230 topo_mod_dprintf(mod, "%s: entry: node=%p, node_name=%s, "
231 231 "node_inst=%d, dp=%p, dp_bdf=%d/%d/%d, pdp=%p\n",
232 232 __func__, node, topo_node_name(node), topo_node_instance(node),
233 233 dp, b, d, f, pdp);
234 234
235 235 /*
236 236 * If this device has a physical slot number then check if
237 237 * an ancestor also has a slot label.
238 238 *
239 239 * If an ancestor has a slot label, then this node's label
240 240 * is generated by concatenating a default label onto the
241 241 * ancestor's label.
242 242 *
243 243 * We grab pairs of ancestors (parent and child) as we go up
244 244 * the tree because the parent is checked for the presence
245 245 * of a slot while the child contains the label.
246 246 *
247 247 * Note that this algorithm only applies to nodes which have
248 248 * a physcal slot number. (i.e. PCIE devices or PCI/PCIX
249 249 * devices off of a PCIE to PCIX switch)
250 250 */
251 251 if (did_physlot(pdp) >= 0) {
252 252
253 253 topo_mod_dprintf(mod, "%s: node=%p: node has a physical "
254 254 "slot=%d, checking ancestors for slots\n",
255 255 __func__, node, did_physlot(pdp));
256 256
257 257 /*
258 258 * Get this device's physical slot name.
259 259 */
260 260 l = (char *)did_physlot_name(pdp, d);
261 261
262 262 anode = topo_node_parent(node);
263 263
264 264 /*
265 265 * Check ancestors for a slot label until we
266 266 * either find one or hit a non-pci device.
267 267 */
268 268 while (!done) {
269 269
270 270 /*
271 271 * Get next ancestor node and data pointers.
272 272 */
273 273 anode = topo_node_parent(anode);
274 274 if (anode != NULL) {
275 275 adp = did_find(mod,
276 276 topo_node_getspecific(anode));
277 277 apnode = topo_node_parent(anode);
278 278 if (apnode != NULL)
279 279 apdp = did_find(mod,
280 280 topo_node_getspecific(apnode));
281 281 else
282 282 apdp = NULL;
283 283 } else {
284 284 apnode = NULL;
285 285 apdp = adp = NULL;
286 286 }
287 287
288 288 topo_mod_dprintf(mod, "%s: node=%p: checking next "
289 289 "two ancestors: anode=%p, adp=%p "
290 290 "apnode=%p, apdp=%p\n",
291 291 __func__, node, anode, adp, apnode, apdp);
292 292 if ((anode != NULL) && (adp != NULL)) {
293 293 did_BDF(adp, &b, &d, &f);
294 294 topo_mod_dprintf(mod, "%s: node=%p: "
295 295 "anode_name=%s[%d], anode_bdf=%d/%d/%d\n",
296 296 __func__, node, topo_node_name(anode),
297 297 topo_node_instance(anode), b, d, f);
298 298 }
299 299 if ((apnode != NULL) && (apdp != NULL)) {
300 300 did_BDF(apdp, &b, &d, &f);
301 301 topo_mod_dprintf(mod, "%s: node=%p: "
302 302 "apnode_name=%s[%d], "
303 303 "apnode_bdf=%d/%d/%d\n",
304 304 __func__, node, topo_node_name(apnode),
305 305 topo_node_instance(apnode), b, d, f);
306 306 }
307 307
308 308 /*
309 309 * If the ancestors do not exist or are not pci
310 310 * devices then we're done searching.
311 311 *
312 312 * Otherwise, if the ancestor has a physical slot,
313 313 * and it is a different slot than the one we
314 314 * started with then lookup the ancestor label,
315 315 * and we're done.
316 316 */
317 317 if ((anode == NULL) || (adp == NULL) ||
318 318 (apnode == NULL) || (apdp == NULL)) {
319 319 done++;
320 320 } else if (did_physlot_exists(apdp) &&
321 321 (apdp != pdp)) {
322 322 if (topo_node_label(anode, &ancestor_l,
323 323 &err) != 0) {
324 324 topo_mod_dprintf(mod,
325 325 "%s: node=%p: topo_node_label() "
326 326 "FAILED!", __func__, node);
327 327 (void) topo_mod_seterrno(mod, err);
328 328 return (NULL);
329 329 }
330 330 done++;
331 331 topo_mod_dprintf(mod, "%s: node=%p: found "
332 332 "ancestor with a slot, label=%s ",
333 333 __func__, node, ancestor_l);
334 334 }
335 335 }
336 336 if (ancestor_l == NULL) {
337 337 topo_mod_dprintf(mod, "%s: node=%p: no ancestor "
338 338 "slot found\n", __func__, node);
339 339 }
340 340 }
341 341
342 342 /*
343 343 * If we found an ancestor with a slot label, and this node has
344 344 * a physical slot number label then concatenate the two to form
↓ open down ↓ |
110 lines elided |
↑ open up ↑ |
345 345 * this node's label. Otherwise, do a full slot label lookup.
346 346 */
347 347 if (ancestor_l && l) {
348 348 topo_mod_dprintf(mod, "%s: node=%p: concatenating "
349 349 "ancestor_l=%s and l=%s\n",
350 350 __func__, node, ancestor_l, l);
351 351 len = strlen(ancestor_l) + strlen(l) + 2;
352 352 new_l = alloca(len);
353 353 (void) snprintf(new_l, len, "%s/%s", ancestor_l, l);
354 354 l = new_l;
355 - } else {
355 + } else if (topo_prop_get_string(node, FM_FMRI_AUTHORITY,
356 + FM_FMRI_AUTH_PRODUCT, &plat, &err) == 0) {
356 357 /*
357 - * Get platform name used for lookups.
358 - */
359 - if (topo_prop_get_string(node, FM_FMRI_AUTHORITY,
360 - FM_FMRI_AUTH_PRODUCT, &plat, &err) < 0) {
361 - (void) topo_mod_seterrno(mod, err);
362 - return (NULL);
363 - }
364 - /*
365 358 * Trim SUNW, from the platform name
366 359 */
367 360 pp = strchr(plat, ',');
368 361 if (pp == NULL)
369 362 pp = plat;
370 363 else
371 364 ++pp;
372 365 /*
373 366 * Get device number used for lookup.
374 367 */
375 368 did_BDF(dp, NULL, &d, NULL);
376 369
377 370 /*
378 371 * The slot label is determined in the following order:
379 372 * - Platform specific lookup based on physical slot #.
380 373 * - Platform specific lookup based on default label string.
381 374 * - Platform specific lookup based on device number.
382 375 * - Default label.
383 376 * The default label is based on the slot names property
384 377 * if it exists, else it is a generic name derived from
385 378 * the slot #.
386 379 */
387 380 if ((l = (char *)pci_label_physlot_lookup(mod, pp, pdp))
388 381 == NULL) {
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
389 382 if ((l = (char *)did_physlot_name(pdp, d)) != NULL) {
390 383 l = (char *)
391 384 pci_label_slotname_lookup(mod, pp, l, dp);
392 385 }
393 386 if (l == NULL) {
394 387 l = (char *)
395 388 pci_label_missing_lookup(mod, pp, dp);
396 389 }
397 390 }
398 391 topo_mod_strfree(mod, plat);
392 + } else {
393 + (void) topo_mod_seterrno(mod, err);
394 + l = NULL;
399 395 }
400 396
397 + topo_mod_strfree(mod, ancestor_l);
398 +
401 399 /*
402 400 * If we calculated a slot label, then save it in the
403 401 * node's data structure so we can free it later.
404 402 */
405 403 if (l) {
406 404 if (did_slot_label_get(dp) != NULL)
407 405 topo_mod_strfree(mod, did_slot_label_get(dp));
408 406 l = topo_mod_strdup(mod, l);
409 407 did_slot_label_set(dp, l);
410 408 }
411 409
412 410 topo_mod_dprintf(mod, "%s: exit: node=%p: label=%s\n",
413 411 __func__, node, (l ? l : "NULL"));
414 412
415 413 return (l);
416 414 }
417 415
418 416 int
419 417 pci_label_cmn(topo_mod_t *mod, tnode_t *node, nvlist_t *in, nvlist_t **out)
420 418 {
421 419 uint64_t ptr;
422 420 char *l;
423 421 did_t *dp, *pdp;
424 422 tnode_t *pnode;
425 423 char *nm;
426 424 int err;
427 425
428 426 /*
429 427 * If it's not a device or a PCI-express bus (which could potentially
430 428 * represent a slot, and therefore we might need to capture its slot
431 429 * name information), just inherit any label from our parent
432 430 */
433 431 *out = NULL;
434 432 nm = topo_node_name(node);
435 433 if (strcmp(nm, PCI_DEVICE) != 0 && strcmp(nm, PCIEX_DEVICE) != 0 &&
436 434 strcmp(nm, PCIEX_BUS) != 0) {
437 435 if (topo_node_label_set(node, NULL, &err) < 0)
438 436 if (err != ETOPO_PROP_NOENT)
439 437 return (topo_mod_seterrno(mod, err));
440 438 return (0);
441 439 }
442 440
443 441 if (nvlist_lookup_uint64(in, TOPO_METH_LABEL_ARG_NVL, &ptr) != 0) {
444 442 topo_mod_dprintf(mod,
445 443 "%s: label method argument not found.\n", __func__);
446 444 return (-1);
447 445 }
448 446 dp = (did_t *)(uintptr_t)ptr;
449 447 pnode = did_gettnode(dp);
450 448 pdp = did_find(mod, topo_node_getspecific(pnode));
451 449
452 450 /*
453 451 * Is there a slot label associated with the device?
454 452 */
455 453 if ((l = pci_slot_label_lookup(mod, node, dp, pdp)) != NULL) {
456 454 nvlist_t *rnvl;
457 455
458 456 if (topo_mod_nvalloc(mod, &rnvl, NV_UNIQUE_NAME) != 0 ||
459 457 nvlist_add_string(rnvl, TOPO_METH_LABEL_RET_STR, l) != 0)
460 458 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
461 459 *out = rnvl;
462 460 return (0);
463 461 } else {
464 462 if (topo_node_label_set(node, NULL, &err) < 0)
465 463 if (err != ETOPO_PROP_NOENT)
466 464 return (topo_mod_seterrno(mod, err));
467 465 return (0);
468 466 }
469 467 }
470 468
471 469 int
472 470 pci_fru_cmn(topo_mod_t *mod, tnode_t *node, nvlist_t *in, nvlist_t **out)
473 471 {
474 472 int err = 0;
475 473 uint64_t ptr;
476 474 did_t *dp, *pdp;
477 475 tnode_t *pnode;
478 476 char *nm;
479 477
480 478 *out = NULL;
481 479 nm = topo_node_name(node);
482 480 if (strcmp(nm, PCI_DEVICE) != 0 && strcmp(nm, PCIEX_DEVICE) != 0 &&
483 481 strcmp(nm, PCIEX_BUS) != 0)
484 482 return (0);
485 483
486 484 if (nvlist_lookup_uint64(in, "nv1", &ptr) != 0) {
487 485 topo_mod_dprintf(mod,
488 486 "%s: label method argument not found.\n", __func__);
489 487 return (-1);
490 488 }
491 489 dp = (did_t *)(uintptr_t)ptr;
492 490 pnode = did_gettnode(dp);
493 491 pdp = did_find(mod, topo_node_getspecific(pnode));
494 492
495 493 /*
496 494 * Is there a slot label associated with the device?
497 495 */
498 496 if (pci_slot_label_lookup(mod, pnode, dp, pdp) != NULL) {
499 497 nvlist_t *rnvl;
500 498
501 499 if (topo_node_resource(node, &rnvl, &err) < 0 || rnvl == NULL) {
502 500 topo_mod_dprintf(mod, "%s: error: %s\n",
503 501 __func__, topo_strerror(topo_mod_errno(mod)));
504 502 return (topo_mod_seterrno(mod, err));
505 503 }
506 504 *out = rnvl;
507 505 }
508 506 return (0);
509 507 }
↓ open down ↓ |
99 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX