Print this page
5552 libsun_sas leaks devids
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Jean McCormack <jean.mccormack@nexenta.com>
Reviewed by: Marcel Telka <marcel.telka@nexenta.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/sun_sas/common/devtree_device_disco.c
+++ new/usr/src/lib/sun_sas/common/devtree_device_disco.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.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
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 + * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
25 26 */
26 27
27 28 #include <sun_sas.h>
28 29 #include <sys/types.h>
29 30 #include <netinet/in.h>
30 31 #include <inttypes.h>
31 32 #include <ctype.h>
32 33 #include <sys/scsi/scsi_address.h>
33 34 #include <libdevid.h>
34 35
35 36 /*
36 37 * Get the preferred minor node for the given path.
37 38 * ":n" for tapes, ":c,raw" for disks,
38 39 * and ":0" for enclosures.
39 40 */
40 41 static void
41 42 get_minor(char *devpath, char *minor)
42 43 {
43 44 const char ROUTINE[] = "get_minor";
44 45 char fullpath[MAXPATHLEN];
45 46 int fd;
46 47
47 48 if ((strstr(devpath, "/st@")) || (strstr(devpath, "/tape@"))) {
48 49 (void) strcpy(minor, ":n");
49 50 } else if (strstr(devpath, "/smp@")) {
50 51 (void) strcpy(minor, ":smp");
51 52 } else if ((strstr(devpath, "/ssd@")) || (strstr(devpath, "/sd@")) ||
52 53 (strstr(devpath, "/disk@"))) {
53 54 (void) strcpy(minor, ":c,raw");
54 55 } else if ((strstr(devpath, "/ses@")) || (strstr(devpath,
55 56 "/enclosure@"))) {
56 57 (void) snprintf(fullpath, MAXPATHLEN, "%s%s%s", DEVICES_DIR,
57 58 devpath, ":0");
58 59 /* reset errno to 0 */
59 60 errno = 0;
60 61 if ((fd = open(fullpath, O_RDONLY)) == -1) {
61 62 /*
62 63 * :0 minor doesn't exist. assume bound to sgen driver
63 64 * and :ses minor exist.
64 65 */
65 66 if (errno == ENOENT) {
66 67 (void) strcpy(minor, ":ses");
67 68 }
68 69 } else {
69 70 (void) strcpy(minor, ":0");
70 71 (void) close(fd);
71 72 }
72 73 } else {
73 74 log(LOG_DEBUG, ROUTINE, "Unrecognized target (%s)",
74 75 devpath);
75 76 minor[0] = '\0';
76 77 }
77 78
78 79 }
79 80
80 81 /*
81 82 * Free the attached port allocation.
82 83 */
83 84 static void
84 85 free_attached_port(struct sun_sas_port *port_ptr)
85 86 {
86 87 struct sun_sas_port *tgt_port, *last_tgt_port;
87 88 struct ScsiEntryList *scsi_info = NULL, *last_scsi_info = NULL;
88 89
89 90 tgt_port = port_ptr->first_attached_port;
90 91 while (tgt_port != NULL) {
91 92 /* Free target mapping data list first. */
92 93 scsi_info = tgt_port->scsiInfo;
93 94 while (scsi_info != NULL) {
94 95 last_scsi_info = scsi_info;
95 96 scsi_info = scsi_info->next;
96 97 free(last_scsi_info);
97 98 }
98 99 last_tgt_port = tgt_port;
99 100 tgt_port = tgt_port->next;
100 101 free(last_tgt_port->port_attributes.\
101 102 PortSpecificAttribute.SASPort);
102 103 free(last_tgt_port);
103 104 }
104 105
105 106 port_ptr->first_attached_port = NULL;
106 107 port_ptr->port_attributes.PortSpecificAttribute.\
107 108 SASPort->NumberofDiscoveredPorts = 0;
108 109 }
109 110
110 111 /*
111 112 * Fill domainPortWWN.
112 113 * should be called after completing discovered port discovery.
113 114 */
114 115 void
115 116 fillDomainPortWWN(struct sun_sas_port *port_ptr)
116 117 {
117 118 const char ROUTINE[] = "fillDomainPortWWN";
118 119 struct sun_sas_port *disco_port_ptr;
119 120 struct phy_info *phy_ptr;
120 121 uint64_t domainPort = 0;
121 122 struct ScsiEntryList *mapping_ptr;
122 123
123 124 for (disco_port_ptr = port_ptr->first_attached_port;
124 125 disco_port_ptr != NULL; disco_port_ptr = disco_port_ptr->next) {
125 126 if (disco_port_ptr->port_attributes.PortType ==
126 127 HBA_PORTTYPE_SASEXPANDER &&
127 128 wwnConversion(disco_port_ptr->port_attributes.
128 129 PortSpecificAttribute.SASPort->
129 130 AttachedSASAddress.wwn) ==
130 131 wwnConversion(port_ptr->port_attributes.
131 132 PortSpecificAttribute.SASPort->
132 133 LocalSASAddress.wwn)) {
133 134 (void) memcpy(&domainPort,
134 135 disco_port_ptr->port_attributes.
135 136 PortSpecificAttribute.
136 137 SASPort->LocalSASAddress.wwn, 8);
137 138 break;
138 139 }
139 140 }
140 141
141 142 if (domainPort == 0) {
142 143 if (port_ptr->first_attached_port) {
143 144 /*
144 145 * there is no expander device attached on an HBA port
145 146 * domainPortWWN should not stay to 0 since multiple
146 147 * hba ports can have the same LocalSASAddres within
147 148 * the same HBA.
148 149 * Set the SAS address of direct attached target.
149 150 */
150 151 if (wwnConversion(port_ptr->port_attributes.
151 152 PortSpecificAttribute.SASPort->
152 153 LocalSASAddress.wwn) ==
153 154 wwnConversion(port_ptr->first_attached_port->
154 155 port_attributes.PortSpecificAttribute.
155 156 SASPort->AttachedSASAddress.wwn)) {
156 157 (void) memcpy(&domainPort,
157 158 port_ptr->first_attached_port->
158 159 port_attributes.PortSpecificAttribute.
159 160 SASPort->LocalSASAddress.wwn, 8);
160 161 } else {
161 162 /*
162 163 * SAS address is not upstream connected.
163 164 * domainPortWWN stays as 0.
164 165 */
165 166 log(LOG_DEBUG, ROUTINE,
166 167 "DomainPortWWN is not set. "
167 168 "Device(s) are visible on the HBA port "
168 169 "but there is no expander or directly "
169 170 "attached port with matching upsteam "
170 171 "attached SAS address for "
171 172 "HBA port (Local SAS Address: %016llx).",
172 173 wwnConversion(port_ptr->port_attributes.
173 174 PortSpecificAttribute.
174 175 SASPort->LocalSASAddress.wwn));
175 176 return;
176 177 }
177 178 } else {
178 179 /*
179 180 * There existss an iport without properly configured
180 181 * child smp ndoes or child node or pathinfo.
181 182 * domainPortWWN stays as 0.
182 183 */
183 184 log(LOG_DEBUG, ROUTINE,
184 185 "DomainPortWWN is not set. No properly "
185 186 "configured smp or directly attached port "
186 187 "found on HBA port(Local SAS Address: %016llx).",
187 188 wwnConversion(port_ptr->port_attributes.
188 189 PortSpecificAttribute.
189 190 SASPort->LocalSASAddress.wwn));
190 191 return;
191 192 }
192 193 }
193 194
194 195 /* fill up phy info */
195 196 for (phy_ptr = port_ptr->first_phy; phy_ptr != NULL;
196 197 phy_ptr = phy_ptr->next) {
197 198 (void) memcpy(phy_ptr->phy.domainPortWWN.wwn, &domainPort, 8);
198 199 }
199 200
200 201 /* fill up target mapping */
201 202 for (disco_port_ptr = port_ptr->first_attached_port;
202 203 disco_port_ptr != NULL; disco_port_ptr = disco_port_ptr->next) {
203 204 for (mapping_ptr = disco_port_ptr->scsiInfo;
204 205 mapping_ptr != NULL;
205 206 mapping_ptr = mapping_ptr->next) {
206 207 (void) memcpy(mapping_ptr->entry.PortLun.
207 208 domainPortWWN.wwn, &domainPort, 8);
208 209 }
209 210 }
210 211 }
211 212
212 213 /*
213 214 * Finds attached device(target) from devinfo node.
214 215 */
215 216 static HBA_STATUS
216 217 get_attached_devices_info(di_node_t node, struct sun_sas_port *port_ptr)
217 218 {
218 219 const char ROUTINE[] = "get_attached_devices_info";
219 220 char *propStringData = NULL;
220 221 int *propIntData = NULL;
221 222 int64_t *propInt64Data = NULL;
222 223 scsi_lun_t samLun;
223 224 ddi_devid_t devid;
224 225 char *guidStr;
225 226 char *unit_address;
226 227 char *charptr;
227 228 char *devpath, link[MAXNAMELEN];
228 229 char fullpath[MAXPATHLEN+1];
229 230 char minorname[MAXNAMELEN+1];
230 231 struct ScsiEntryList *mapping_ptr;
231 232 HBA_WWN SASAddress, AttachedSASAddress;
232 233 struct sun_sas_port *disco_port_ptr;
233 234 uint_t state = 0;
234 235 int portfound, rval, size;
235 236 int port_state = HBA_PORTSTATE_ONLINE;
236 237 uint64_t tmpAddr;
237 238
238 239 if (port_ptr == NULL) {
239 240 log(LOG_DEBUG, ROUTINE, "NULL port_ptr argument");
240 241 return (HBA_STATUS_ERROR);
241 242 }
242 243
243 244 if ((devpath = di_devfs_path(node)) == NULL) {
244 245 log(LOG_DEBUG, ROUTINE,
245 246 "Device in device tree has no path. Skipping.");
246 247 return (HBA_STATUS_ERROR);
247 248 }
248 249
249 250 if ((di_instance(node) == -1) || di_retired(node)) {
250 251 log(LOG_DEBUG, ROUTINE,
251 252 "dev node (%s) returned instance of -1 or is retired. "
252 253 " Skipping.", devpath);
253 254 di_devfs_path_free(devpath);
254 255 return (HBA_STATUS_OK);
255 256 }
256 257 state = di_state(node);
257 258 /* when node is not attached and online, set the state to offline. */
258 259 if (((state & DI_DRIVER_DETACHED) == DI_DRIVER_DETACHED) ||
259 260 ((state & DI_DEVICE_OFFLINE) == DI_DEVICE_OFFLINE)) {
260 261 log(LOG_DEBUG, ROUTINE,
261 262 "dev node (%s) is either OFFLINE or DETACHED",
262 263 devpath);
263 264 port_state = HBA_PORTSTATE_OFFLINE;
264 265 }
265 266
266 267 /* add the "/devices" in the begining at the end */
267 268 (void) snprintf(fullpath, sizeof (fullpath), "%s%s",
268 269 DEVICES_DIR, devpath);
269 270
270 271 (void) memset(&SASAddress, 0, sizeof (SASAddress));
271 272 if ((unit_address = di_bus_addr(node)) != NULL) {
272 273 if ((charptr = strchr(unit_address, ',')) != NULL) {
273 274 *charptr = '\0';
274 275 }
275 276 for (charptr = unit_address; *charptr != '\0'; charptr++) {
276 277 if (isxdigit(*charptr)) {
277 278 break;
278 279 }
279 280 }
280 281 if (*charptr != '\0') {
281 282 tmpAddr = htonll(strtoll(charptr, NULL, 16));
282 283 (void) memcpy(&SASAddress.wwn[0], &tmpAddr, 8);
283 284 } else {
284 285 log(LOG_DEBUG, ROUTINE,
285 286 "No proper target port info on unit address of %s",
286 287 fullpath);
287 288 di_devfs_path_free(devpath);
288 289 return (HBA_STATUS_ERROR);
289 290 }
290 291 } else {
291 292 log(LOG_DEBUG, ROUTINE,
292 293 "Fail to get unit address of %s.",
293 294 fullpath);
294 295 di_devfs_path_free(devpath);
295 296 return (HBA_STATUS_ERROR);
296 297 }
297 298
298 299 (void) memset(&AttachedSASAddress, 0, sizeof (AttachedSASAddress));
299 300 if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "attached-port",
300 301 &propStringData) != -1) {
301 302 for (charptr = propStringData; *charptr != '\0'; charptr++) {
302 303 if (isxdigit(*charptr)) {
303 304 break;
304 305 }
305 306 }
306 307 if (*charptr != '\0') {
307 308 tmpAddr = htonll(strtoll(charptr, NULL, 16));
308 309 (void) memcpy(AttachedSASAddress.wwn, &tmpAddr, 8);
309 310 /* check the attached address of hba port. */
310 311 if (memcmp(port_ptr->port_attributes.
311 312 PortSpecificAttribute.SASPort->LocalSASAddress.wwn,
312 313 &tmpAddr, 8) == 0) {
313 314 /*
314 315 * When attached-port is set from iport
315 316 * attached-port prop, we do the cross check
316 317 * with device's own SAS address.
317 318 *
318 319 * If not set, we store device's own SAS
319 320 * address to iport attached SAS address.
320 321 */
321 322 if (wwnConversion(port_ptr->port_attributes.
322 323 PortSpecificAttribute.SASPort->
323 324 AttachedSASAddress.wwn)) {
324 325 /* verify the Attaached SAS Addr. */
325 326 if (memcmp(port_ptr->port_attributes.
326 327 PortSpecificAttribute.SASPort->
327 328 AttachedSASAddress.wwn,
328 329 SASAddress.wwn, 8) != 0) {
329 330 /* indentation move begin. */
330 331 log(LOG_DEBUG, ROUTINE,
331 332 "iport attached-port(%016llx) do not"
332 333 " match with level 1 Local"
333 334 " SAS address(%016llx).",
334 335 wwnConversion(port_ptr->port_attributes.
335 336 PortSpecificAttribute.
336 337 SASPort->AttachedSASAddress.wwn),
337 338 wwnConversion(SASAddress.wwn));
338 339 di_devfs_path_free(devpath);
339 340 free_attached_port(port_ptr);
340 341 return (HBA_STATUS_ERROR);
341 342 /* indentation move ends. */
342 343 }
343 344 } else {
344 345 (void) memcpy(port_ptr->port_attributes.
345 346 PortSpecificAttribute.
346 347 SASPort->AttachedSASAddress.wwn,
347 348 &SASAddress.wwn[0], 8);
348 349 }
349 350 }
350 351 } else {
351 352 log(LOG_DEBUG, ROUTINE,
352 353 "No proper attached SAS address value on device %s",
353 354 fullpath);
354 355 di_devfs_path_free(devpath);
355 356 free_attached_port(port_ptr);
356 357 return (HBA_STATUS_ERROR);
357 358 }
358 359 } else {
359 360 log(LOG_DEBUG, ROUTINE,
360 361 "Property AttachedSASAddress not found for device \"%s\"",
361 362 fullpath);
362 363 di_devfs_path_free(devpath);
363 364 free_attached_port(port_ptr);
364 365 return (HBA_STATUS_ERROR);
365 366 }
366 367
367 368 /*
368 369 * walk the disco list to make sure that there isn't a matching
369 370 * port and node wwn or a matching device path
370 371 */
371 372 portfound = 0;
372 373 for (disco_port_ptr = port_ptr->first_attached_port;
373 374 disco_port_ptr != NULL;
374 375 disco_port_ptr = disco_port_ptr->next) {
375 376 if ((disco_port_ptr->port_attributes.PortState !=
376 377 HBA_PORTSTATE_ERROR) && (memcmp(disco_port_ptr->
377 378 port_attributes.PortSpecificAttribute.
378 379 SASPort->LocalSASAddress.wwn, SASAddress.wwn, 8) == 0)) {
379 380 /*
380 381 * found matching disco_port
381 382 * look for matching device path
382 383 */
383 384 portfound = 1;
384 385 for (mapping_ptr = disco_port_ptr->scsiInfo;
385 386 mapping_ptr != NULL;
386 387 mapping_ptr = mapping_ptr->next) {
387 388 if (strstr(mapping_ptr-> entry.ScsiId.
388 389 OSDeviceName, devpath) != 0) {
389 390 log(LOG_DEBUG, ROUTINE,
390 391 "Found an already discovered "
391 392 "device %s.", fullpath);
392 393 di_devfs_path_free(devpath);
393 394 return (HBA_STATUS_OK);
394 395 }
395 396 }
396 397 if (portfound == 1) {
397 398 break;
398 399 }
399 400 }
400 401 }
401 402
402 403 if (portfound == 0) {
403 404 /*
404 405 * there are no matching SAS address.
405 406 * this must be a new device
406 407 */
407 408 if ((disco_port_ptr = (struct sun_sas_port *)calloc(1,
408 409 sizeof (struct sun_sas_port))) == NULL) {
409 410 OUT_OF_MEMORY(ROUTINE);
410 411 di_devfs_path_free(devpath);
411 412 free_attached_port(port_ptr);
412 413 return (HBA_STATUS_ERROR);
413 414 }
414 415
415 416 if ((disco_port_ptr->port_attributes.PortSpecificAttribute.\
416 417 SASPort = (struct SMHBA_SAS_Port *)calloc(1,
417 418 sizeof (struct SMHBA_SAS_Port))) == NULL) {
418 419 OUT_OF_MEMORY("add_hba_port_info");
419 420 di_devfs_path_free(devpath);
420 421 free_attached_port(port_ptr);
421 422 return (HBA_STATUS_ERROR);
422 423 }
423 424
424 425 (void) memcpy(disco_port_ptr->port_attributes.
425 426 PortSpecificAttribute.SASPort->LocalSASAddress.wwn,
426 427 SASAddress.wwn, 8);
427 428 (void) memcpy(disco_port_ptr->port_attributes.
428 429 PortSpecificAttribute.SASPort->AttachedSASAddress.wwn,
429 430 AttachedSASAddress.wwn, 8);
430 431
431 432 /* Default to unknown until we figure out otherwise */
432 433 rval = di_prop_lookup_strings(DDI_DEV_T_ANY, node,
433 434 "variant", &propStringData);
434 435 if (rval < 0) {
435 436 /* check if it is SMP target */
436 437 charptr = di_driver_name(node);
437 438 if (charptr != NULL && (strncmp(charptr, "smp",
438 439 strlen(charptr)) == 0)) {
439 440 disco_port_ptr->port_attributes.PortType =
440 441 HBA_PORTTYPE_SASEXPANDER;
441 442 disco_port_ptr->port_attributes.
442 443 PortSpecificAttribute.
443 444 SASPort->PortProtocol =
444 445 HBA_SASPORTPROTOCOL_SMP;
445 446 if (lookupSMPLink(devpath, (char *)link) ==
446 447 HBA_STATUS_OK) {
447 448 /* indentation changed here. */
448 449 (void) strlcpy(disco_port_ptr->port_attributes.
449 450 OSDeviceName, link,
450 451 sizeof (disco_port_ptr->port_attributes.OSDeviceName));
451 452 /* indentation change ends here. */
452 453 } else {
453 454 /* indentation changed here. */
454 455 get_minor(devpath, minorname);
455 456 (void) snprintf(fullpath, sizeof (fullpath), "%s%s%s",
456 457 DEVICES_DIR, devpath, minorname);
457 458 (void) strlcpy(disco_port_ptr->port_attributes.
458 459 OSDeviceName, fullpath,
459 460 sizeof (disco_port_ptr->port_attributes.OSDeviceName));
460 461 /* indentation change ends here. */
461 462 }
462 463 } else {
463 464 disco_port_ptr->port_attributes.PortType =
464 465 HBA_PORTTYPE_SASDEVICE;
465 466 disco_port_ptr->port_attributes.\
466 467 PortSpecificAttribute.\
467 468 SASPort->PortProtocol =
468 469 HBA_SASPORTPROTOCOL_SSP;
469 470 }
470 471 } else {
471 472 if ((strcmp(propStringData, "sata") == 0) ||
472 473 (strcmp(propStringData, "atapi") == 0)) {
473 474 disco_port_ptr->port_attributes.PortType =
474 475 HBA_PORTTYPE_SATADEVICE;
475 476 disco_port_ptr->port_attributes.\
476 477 PortSpecificAttribute.SASPort->PortProtocol
477 478 = HBA_SASPORTPROTOCOL_SATA;
478 479 } else {
479 480 log(LOG_DEBUG, ROUTINE,
480 481 "Unexpected variant prop value %s found on",
481 482 " device %s", propStringData, fullpath);
482 483 /*
483 484 * Port type will be 0
484 485 * which is not valid type.
485 486 */
486 487 }
487 488 }
488 489
489 490 /* SMP device was handled already */
490 491 if (disco_port_ptr->port_attributes.OSDeviceName[0] == '\0') {
491 492 /* indentation change due to ctysle check on sizeof. */
492 493 size = sizeof (disco_port_ptr->port_attributes.OSDeviceName);
493 494 (void) strlcpy(disco_port_ptr->port_attributes.
494 495 OSDeviceName, fullpath, size);
495 496 }
496 497
497 498 /* add new discovered port into the list */
498 499
499 500 if (port_ptr->first_attached_port == NULL) {
500 501 port_ptr->first_attached_port = disco_port_ptr;
501 502 disco_port_ptr->index = 0;
502 503 port_ptr->port_attributes.PortSpecificAttribute.\
503 504 SASPort->NumberofDiscoveredPorts = 1;
504 505 } else {
505 506 disco_port_ptr->next = port_ptr->first_attached_port;
506 507 port_ptr->first_attached_port = disco_port_ptr;
507 508 disco_port_ptr->index = port_ptr->port_attributes.\
508 509 PortSpecificAttribute.\
509 510 SASPort->NumberofDiscoveredPorts;
510 511 port_ptr->port_attributes.PortSpecificAttribute.\
511 512 SASPort->NumberofDiscoveredPorts++;
512 513 }
513 514 disco_port_ptr->port_attributes.PortState = port_state;
514 515 }
515 516
516 517 if (disco_port_ptr->port_attributes.PortType ==
517 518 HBA_PORTTYPE_SASEXPANDER) {
518 519 /* No mapping data for expander device. return ok here. */
519 520 di_devfs_path_free(devpath);
520 521 return (HBA_STATUS_OK);
521 522 }
522 523
523 524 if ((mapping_ptr = (struct ScsiEntryList *)calloc
524 525 (1, sizeof (struct ScsiEntryList))) == NULL) {
525 526 OUT_OF_MEMORY(ROUTINE);
526 527 di_devfs_path_free(devpath);
527 528 free_attached_port(port_ptr);
528 529 return (HBA_STATUS_ERROR);
529 530 }
530 531
531 532 if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "lun",
532 533 &propIntData) != -1) {
533 534 mapping_ptr->entry.ScsiId.ScsiOSLun = *propIntData;
534 535 } else {
535 536 if ((charptr = strchr(unit_address, ',')) != NULL) {
536 537 charptr++;
537 538 mapping_ptr->entry.ScsiId.ScsiOSLun =
538 539 strtoull(charptr, NULL, 10);
539 540 } else {
540 541 log(LOG_DEBUG, ROUTINE,
541 542 "Failed to get LUN from the unit address of device "
542 543 " %s.", fullpath);
543 544 di_devfs_path_free(devpath);
544 545 free_attached_port(port_ptr);
545 546 return (HBA_STATUS_ERROR);
546 547 }
547 548 }
548 549
549 550 /* get TargetLun(SAM-LUN). */
550 551 if (di_prop_lookup_int64(DDI_DEV_T_ANY, node, "lun64",
551 552 &propInt64Data) != -1) {
552 553 samLun = scsi_lun64_to_lun(*propInt64Data);
553 554 (void) memcpy(&mapping_ptr->entry.PortLun.TargetLun,
554 555 &samLun, 8);
555 556 } else {
556 557 log(LOG_DEBUG, "get_attached_devices_info",
557 558 "No lun64 prop found on device %s.", fullpath);
558 559 di_devfs_path_free(devpath);
559 560 free_attached_port(port_ptr);
560 561 return (HBA_STATUS_ERROR);
561 562 }
562 563
563 564 if (di_prop_lookup_ints(DDI_DEV_T_ANY, node,
564 565 "target", &propIntData) != -1) {
565 566 mapping_ptr->entry.ScsiId.ScsiTargetNumber = *propIntData;
566 567 } else {
567 568 mapping_ptr->entry.ScsiId.ScsiTargetNumber = di_instance(node);
568 569 }
569 570
570 571 /* get ScsiBusNumber */
571 572 mapping_ptr->entry.ScsiId.ScsiBusNumber = port_ptr->cntlNumber;
572 573
573 574 (void) memcpy(mapping_ptr->entry.PortLun.PortWWN.wwn,
574 575 SASAddress.wwn, 8);
575 576
576 577 /* Store the devices path for now. We'll convert to /dev later */
577 578 get_minor(devpath, minorname);
578 579 (void) snprintf(mapping_ptr->entry.ScsiId.OSDeviceName,
579 580 sizeof (mapping_ptr->entry.ScsiId.OSDeviceName),
↓ open down ↓ |
545 lines elided |
↑ open up ↑ |
580 581 "%s%s%s", DEVICES_DIR, devpath, minorname);
581 582
582 583 /* reset errno to 0 */
583 584 errno = 0;
584 585 if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "devid",
585 586 &propStringData) != -1) {
586 587 if (devid_str_decode(propStringData, &devid, NULL) != -1) {
587 588 guidStr = devid_to_guid(devid);
588 589 if (guidStr != NULL) {
589 590 (void) strlcpy(mapping_ptr->entry.LUID.buffer,
590 - guidStr, 256);
591 + guidStr,
592 + sizeof (mapping_ptr->entry.LUID.buffer));
591 593 devid_free_guid(guidStr);
592 594 } else {
593 595 /*
594 596 * Note:
595 597 * if logical unit associated page 83 id
596 598 * descriptor is not avaialble for the device
597 - * devid_to_guid returns NULl with errno 0.
599 + * devid_to_guid returns NULL with errno 0.
598 600 */
599 601 log(LOG_DEBUG, ROUTINE,
600 602 "failed to get devid guid on (%s) : %s",
601 603 devpath, strerror(errno));
602 604 }
605 +
606 + devid_free(devid);
603 607 } else {
604 608 /*
605 609 * device may not support proper page 83 id descriptor.
606 610 * leave LUID attribute to NULL and continue.
607 611 */
608 612 log(LOG_DEBUG, ROUTINE,
609 613 "failed to decode devid prop on (%s) : %s",
610 614 devpath, strerror(errno));
611 615 }
612 616 } else {
613 617 /* leave LUID attribute to NULL and continue. */
614 618 log(LOG_DEBUG, ROUTINE,
615 619 "failed to get devid prop on (%s) : %s",
616 620 devpath, strerror(errno));
617 621 }
618 622
619 623 if (disco_port_ptr->scsiInfo == NULL) {
620 624 disco_port_ptr->scsiInfo = mapping_ptr;
621 625 } else {
622 626 mapping_ptr->next = disco_port_ptr->scsiInfo;
623 627 disco_port_ptr->scsiInfo = mapping_ptr;
624 628 }
625 629
626 630 di_devfs_path_free(devpath);
627 631
628 632 return (HBA_STATUS_OK);
629 633 }
630 634
631 635 /*
632 636 * Finds attached device(target) from pathinfo node.
633 637 */
634 638 static HBA_STATUS
635 639 get_attached_paths_info(di_path_t path, struct sun_sas_port *port_ptr)
636 640 {
637 641 char ROUTINE[] = "get_attached_paths_info";
638 642 char *propStringData = NULL;
639 643 int *propIntData = NULL;
640 644 int64_t *propInt64Data = NULL;
641 645 scsi_lun_t samLun;
642 646 ddi_devid_t devid;
643 647 char *guidStr;
644 648 char *unit_address;
645 649 char *charptr;
646 650 char *clientdevpath = NULL;
647 651 char *pathdevpath = NULL;
648 652 char fullpath[MAXPATHLEN+1];
649 653 char minorname[MAXNAMELEN+1];
650 654 struct ScsiEntryList *mapping_ptr;
651 655 HBA_WWN SASAddress, AttachedSASAddress;
652 656 struct sun_sas_port *disco_port_ptr;
653 657 di_path_state_t state = 0;
654 658 di_node_t clientnode;
655 659 int portfound, size;
656 660 int port_state = HBA_PORTSTATE_ONLINE;
657 661 uint64_t tmpAddr;
658 662
659 663 if (port_ptr == NULL) {
660 664 log(LOG_DEBUG, ROUTINE, "NULL port_ptr argument");
661 665 return (HBA_STATUS_ERROR);
662 666 }
663 667
664 668 /* if not null, free before return. */
665 669 pathdevpath = di_path_devfs_path(path);
666 670
667 671 state = di_path_state(path);
668 672 /* when node is not attached and online, set the state to offline. */
669 673 if ((state == DI_PATH_STATE_OFFLINE) ||
670 674 (state == DI_PATH_STATE_FAULT)) {
671 675 log(LOG_DEBUG, ROUTINE,
672 676 "path node (%s) is either OFFLINE or FAULT state",
673 677 pathdevpath ? pathdevpath : "(missing device path)");
674 678 port_state = HBA_PORTSTATE_OFFLINE;
675 679 }
676 680
677 681 if (clientnode = di_path_client_node(path)) {
678 682 if (di_retired(clientnode)) {
679 683 log(LOG_DEBUG, ROUTINE,
680 684 "client node of path (%s) is retired. Skipping.",
681 685 pathdevpath ? pathdevpath :
682 686 "(missing device path)");
683 687 if (pathdevpath) di_devfs_path_free(pathdevpath);
684 688 return (HBA_STATUS_OK);
685 689 }
686 690 if ((clientdevpath = di_devfs_path(clientnode)) == NULL) {
687 691 log(LOG_DEBUG, ROUTINE,
688 692 "Client device of path (%s) has no path. Skipping.",
689 693 pathdevpath ? pathdevpath :
690 694 "(missing device path)");
691 695 if (pathdevpath) di_devfs_path_free(pathdevpath);
692 696 return (HBA_STATUS_ERROR);
693 697 }
694 698 } else {
695 699 log(LOG_DEBUG, ROUTINE,
696 700 "Failed to get client device from a path (%s).",
697 701 pathdevpath ? pathdevpath :
698 702 "(missing device path)");
699 703 if (pathdevpath) di_devfs_path_free(pathdevpath);
700 704 return (HBA_STATUS_ERROR);
701 705 }
702 706
703 707 /* add the "/devices" in the begining and the :devctl at the end */
704 708 (void) snprintf(fullpath, sizeof (fullpath), "%s%s", DEVICES_DIR,
705 709 clientdevpath);
706 710
707 711 (void) memset(&SASAddress, 0, sizeof (SASAddress));
708 712 if ((unit_address = di_path_bus_addr(path)) != NULL) {
709 713 if ((charptr = strchr(unit_address, ',')) != NULL) {
710 714 *charptr = '\0';
711 715 }
712 716 for (charptr = unit_address; *charptr != '\0'; charptr++) {
713 717 if (isxdigit(*charptr)) {
714 718 break;
715 719 }
716 720 }
717 721 if (charptr != '\0') {
718 722 tmpAddr = htonll(strtoll(charptr, NULL, 16));
719 723 (void) memcpy(&SASAddress.wwn[0], &tmpAddr, 8);
720 724 } else {
721 725 log(LOG_DEBUG, ROUTINE,
722 726 "No proper target port info on unit address of "
723 727 "path (%s).", pathdevpath ? pathdevpath :
724 728 "(missing device path)");
725 729 if (pathdevpath) di_devfs_path_free(pathdevpath);
726 730 di_devfs_path_free(clientdevpath);
727 731 return (HBA_STATUS_ERROR);
728 732 }
729 733 } else {
730 734 log(LOG_DEBUG, ROUTINE, "Fail to get unit address of path(%s).",
731 735 "path (%s).", pathdevpath ? pathdevpath :
732 736 "(missing device path)");
733 737 if (pathdevpath) di_devfs_path_free(pathdevpath);
734 738 di_devfs_path_free(clientdevpath);
735 739 return (HBA_STATUS_ERROR);
736 740 }
737 741
738 742 (void) memset(&AttachedSASAddress, 0, sizeof (AttachedSASAddress));
739 743 if (di_path_prop_lookup_strings(path, "attached-port",
740 744 &propStringData) != -1) {
741 745 for (charptr = propStringData; *charptr != '\0'; charptr++) {
742 746 if (isxdigit(*charptr)) {
743 747 break;
744 748 }
745 749 }
746 750 if (*charptr != '\0') {
747 751 tmpAddr = htonll(strtoll(charptr, NULL, 16));
748 752 (void) memcpy(AttachedSASAddress.wwn, &tmpAddr, 8);
749 753 /* check the attached address of hba port. */
750 754 if (memcmp(port_ptr->port_attributes.
751 755 PortSpecificAttribute.SASPort->
752 756 LocalSASAddress.wwn, &tmpAddr, 8) == 0) {
753 757 if (wwnConversion(port_ptr->port_attributes.
754 758 PortSpecificAttribute.SASPort->
755 759 AttachedSASAddress.wwn)) {
756 760 /* verify the attaached SAS Addr. */
757 761 if (memcmp(port_ptr->port_attributes.
758 762 PortSpecificAttribute.SASPort->
759 763 AttachedSASAddress.wwn,
760 764 SASAddress.wwn, 8) != 0) {
761 765 /* indentation move begin. */
762 766 log(LOG_DEBUG, ROUTINE,
763 767 "iport attached-port(%016llx) do not"
764 768 " match with level 1 Local"
765 769 " SAS address(%016llx).",
766 770 wwnConversion(port_ptr->port_attributes.
767 771 PortSpecificAttribute.
768 772 SASPort->AttachedSASAddress.wwn),
769 773 wwnConversion(SASAddress.wwn));
770 774 if (pathdevpath)
771 775 di_devfs_path_free(pathdevpath);
772 776 di_devfs_path_free(clientdevpath);
773 777 free_attached_port(port_ptr);
774 778 return (HBA_STATUS_ERROR);
775 779 /* indentation move ends. */
776 780 }
777 781 } else {
778 782 /* store the Attaached SAS Addr. */
779 783 (void) memcpy(port_ptr->port_attributes.
780 784 PortSpecificAttribute.
781 785 SASPort->AttachedSASAddress.wwn,
782 786 &SASAddress.wwn[0], 8);
783 787 }
784 788 }
785 789 } else {
786 790 log(LOG_DEBUG, ROUTINE,
787 791 "No proper attached SAS address value of path (%s)",
788 792 pathdevpath ? pathdevpath :
789 793 "(missing device path)");
790 794 if (pathdevpath) di_devfs_path_free(pathdevpath);
791 795 di_devfs_path_free(clientdevpath);
792 796 free_attached_port(port_ptr);
793 797 return (HBA_STATUS_ERROR);
794 798 }
795 799 } else {
796 800 log(LOG_DEBUG, ROUTINE,
797 801 "Property attached-port not found for path (%s)",
798 802 pathdevpath ? pathdevpath :
799 803 "(missing device path)");
800 804 if (pathdevpath) di_devfs_path_free(pathdevpath);
801 805 di_devfs_path_free(clientdevpath);
802 806 free_attached_port(port_ptr);
803 807 return (HBA_STATUS_ERROR);
804 808 }
805 809
806 810 /*
807 811 * walk the disco list to make sure that there isn't a matching
808 812 * port and node wwn or a matching device path
809 813 */
810 814 portfound = 0;
811 815 for (disco_port_ptr = port_ptr->first_attached_port;
812 816 disco_port_ptr != NULL;
813 817 disco_port_ptr = disco_port_ptr->next) {
814 818 if ((disco_port_ptr->port_attributes.PortState !=
815 819 HBA_PORTSTATE_ERROR) &&
816 820 (memcmp(disco_port_ptr->port_attributes.
817 821 PortSpecificAttribute.SASPort->LocalSASAddress.wwn,
818 822 SASAddress.wwn, 8) == 0)) {
819 823 /*
820 824 * found matching disco_port
821 825 * look for matching device path
822 826 */
823 827 portfound = 1;
824 828 for (mapping_ptr = disco_port_ptr->scsiInfo;
825 829 mapping_ptr != NULL;
826 830 mapping_ptr = mapping_ptr->next) {
827 831 if (strstr(mapping_ptr-> entry.ScsiId.
828 832 OSDeviceName, clientdevpath) != 0) {
829 833 log(LOG_DEBUG, ROUTINE,
830 834 "Found an already discovered "
831 835 "device %s.", clientdevpath);
832 836 if (pathdevpath)
833 837 di_devfs_path_free(pathdevpath);
834 838 di_devfs_path_free(clientdevpath);
835 839 return (HBA_STATUS_OK);
836 840 }
837 841 }
838 842 if (portfound == 1) {
839 843 break;
840 844 }
841 845 }
842 846 }
843 847
844 848 if (portfound == 0) {
845 849 /*
846 850 * there are no matching SAS address.
847 851 * this must be a new device
848 852 */
849 853 if ((disco_port_ptr = (struct sun_sas_port *)calloc(1,
850 854 sizeof (struct sun_sas_port))) == NULL) {
851 855 OUT_OF_MEMORY(ROUTINE);
852 856 if (pathdevpath) di_devfs_path_free(pathdevpath);
853 857 di_devfs_path_free(clientdevpath);
854 858 free_attached_port(port_ptr);
855 859 return (HBA_STATUS_ERROR);
856 860 }
857 861
858 862 if ((disco_port_ptr->port_attributes.PortSpecificAttribute.\
859 863 SASPort = (struct SMHBA_SAS_Port *)calloc(1,
860 864 sizeof (struct SMHBA_SAS_Port))) == NULL) {
861 865 OUT_OF_MEMORY("add_hba_port_info");
862 866 if (pathdevpath) di_devfs_path_free(pathdevpath);
863 867 di_devfs_path_free(clientdevpath);
864 868 free_attached_port(port_ptr);
865 869 return (HBA_STATUS_ERROR);
866 870 }
867 871
868 872 (void) memcpy(disco_port_ptr->port_attributes.
869 873 PortSpecificAttribute.
870 874 SASPort->LocalSASAddress.wwn, SASAddress.wwn, 8);
871 875 (void) memcpy(disco_port_ptr->port_attributes.
872 876 PortSpecificAttribute.
873 877 SASPort->AttachedSASAddress.wwn, AttachedSASAddress.wwn, 8);
874 878
875 879 /* Default to unknown until we figure out otherwise */
876 880 if (di_path_prop_lookup_strings(path, "variant",
877 881 &propStringData) != -1) {
878 882 if ((strcmp(propStringData, "sata") == 0) ||
879 883 (strcmp(propStringData, "atapi") == 0)) {
880 884 disco_port_ptr->port_attributes.PortType =
881 885 HBA_PORTTYPE_SATADEVICE;
882 886 disco_port_ptr->port_attributes.\
883 887 PortSpecificAttribute.SASPort->PortProtocol
884 888 = HBA_SASPORTPROTOCOL_SATA;
885 889 } else {
886 890 log(LOG_DEBUG, ROUTINE,
887 891 "Unexpected variant prop value %s found on",
888 892 " path (%s)", propStringData,
889 893 pathdevpath ? pathdevpath :
890 894 "(missing device path)");
891 895 /*
892 896 * Port type will be 0
893 897 * which is not valid type.
894 898 */
895 899 }
896 900 } else {
897 901 disco_port_ptr->port_attributes.PortType =
898 902 HBA_PORTTYPE_SASDEVICE;
899 903 disco_port_ptr->port_attributes.PortSpecificAttribute.\
900 904 SASPort->PortProtocol = HBA_SASPORTPROTOCOL_SSP;
901 905 }
902 906
903 907 if (disco_port_ptr->port_attributes.OSDeviceName[0] == '\0') {
904 908 /* indentation change due to ctysle check on sizeof. */
905 909 size = sizeof (disco_port_ptr->port_attributes.OSDeviceName);
906 910 if (pathdevpath != NULL) {
907 911 (void) strlcpy(disco_port_ptr->port_attributes.
908 912 OSDeviceName, pathdevpath, size);
909 913 }
910 914 }
911 915
912 916 /* add new discovered port into the list */
913 917 if (port_ptr->first_attached_port == NULL) {
914 918 port_ptr->first_attached_port = disco_port_ptr;
915 919 disco_port_ptr->index = 0;
916 920 port_ptr->port_attributes.PortSpecificAttribute.\
917 921 SASPort->NumberofDiscoveredPorts = 1;
918 922 } else {
919 923 disco_port_ptr->next = port_ptr->first_attached_port;
920 924 port_ptr->first_attached_port = disco_port_ptr;
921 925 disco_port_ptr->index = port_ptr->port_attributes.\
922 926 PortSpecificAttribute.\
923 927 SASPort->NumberofDiscoveredPorts;
924 928 port_ptr->port_attributes.PortSpecificAttribute.\
925 929 SASPort->NumberofDiscoveredPorts++;
926 930 }
927 931 disco_port_ptr->port_attributes.PortState = port_state;
928 932 }
929 933
930 934 if ((mapping_ptr = (struct ScsiEntryList *)calloc
931 935 (1, sizeof (struct ScsiEntryList))) == NULL) {
932 936 OUT_OF_MEMORY(ROUTINE);
933 937 if (pathdevpath) di_devfs_path_free(pathdevpath);
934 938 di_devfs_path_free(clientdevpath);
935 939 free_attached_port(port_ptr);
936 940 return (HBA_STATUS_ERROR);
937 941 }
938 942
939 943 if (di_path_prop_lookup_ints(path, "lun", &propIntData) != -1) {
940 944 mapping_ptr->entry.ScsiId.ScsiOSLun = *propIntData;
941 945 } else {
942 946 if ((charptr = strchr(unit_address, ',')) != NULL) {
943 947 charptr++;
944 948 mapping_ptr->entry.ScsiId.ScsiOSLun =
945 949 strtoull(charptr, NULL, 10);
946 950 } else {
947 951 log(LOG_DEBUG, ROUTINE,
948 952 "Failed to get LUN from unit address of path(%s).",
949 953 pathdevpath ? pathdevpath :
950 954 "(missing device path)");
951 955 if (pathdevpath) di_devfs_path_free(pathdevpath);
952 956 di_devfs_path_free(clientdevpath);
953 957 free_attached_port(port_ptr);
954 958 return (HBA_STATUS_ERROR);
955 959 }
956 960 }
957 961
958 962 /* Get TargetLun(SAM LUN). */
959 963 if (di_path_prop_lookup_int64s(path, "lun64", &propInt64Data) != -1) {
960 964 samLun = scsi_lun64_to_lun(*propInt64Data);
961 965 (void) memcpy(&mapping_ptr->entry.PortLun.TargetLun,
962 966 &samLun, 8);
963 967 } else {
964 968 log(LOG_DEBUG, ROUTINE, "No lun64 prop found on path (%s)",
965 969 pathdevpath ? pathdevpath :
966 970 "(missing device path)");
967 971 if (pathdevpath) di_devfs_path_free(pathdevpath);
968 972 di_devfs_path_free(clientdevpath);
969 973 free_attached_port(port_ptr);
970 974 return (HBA_STATUS_ERROR);
971 975 }
972 976
973 977 if (di_path_prop_lookup_ints(path, "target", &propIntData) != -1) {
974 978 mapping_ptr->entry.ScsiId.ScsiTargetNumber = *propIntData;
975 979 } else {
976 980 mapping_ptr->entry.ScsiId.ScsiTargetNumber =
977 981 di_path_instance(path);
978 982 }
979 983
980 984 /* get ScsiBusNumber */
981 985 mapping_ptr->entry.ScsiId.ScsiBusNumber = port_ptr->cntlNumber;
982 986
983 987 (void) memcpy(mapping_ptr->entry.PortLun.PortWWN.wwn,
984 988 SASAddress.wwn, 8);
985 989
986 990 /* Store the devices path for now. We'll convert to /dev later */
987 991 get_minor(clientdevpath, minorname);
988 992 (void) snprintf(mapping_ptr->entry.ScsiId.OSDeviceName,
989 993 sizeof (mapping_ptr->entry.ScsiId.OSDeviceName),
990 994 "%s%s%s", DEVICES_DIR, clientdevpath, minorname);
991 995
992 996 /* get luid. */
993 997 errno = 0; /* reset errno to 0 */
994 998 if (di_prop_lookup_strings(DDI_DEV_T_ANY, clientnode, "devid",
995 999 &propStringData) != -1) {
996 1000 if (devid_str_decode(propStringData, &devid, NULL) != -1) {
997 1001 guidStr = devid_to_guid(devid);
↓ open down ↓ |
385 lines elided |
↑ open up ↑ |
998 1002 if (guidStr != NULL) {
999 1003 (void) strlcpy(mapping_ptr->entry.LUID.buffer,
1000 1004 guidStr,
1001 1005 sizeof (mapping_ptr->entry.LUID.buffer));
1002 1006 devid_free_guid(guidStr);
1003 1007 } else {
1004 1008 /*
1005 1009 * Note:
1006 1010 * if logical unit associated page 83 id
1007 1011 * descriptor is not avaialble for the device
1008 - * devid_to_guid returns NULl with errno 0.
1012 + * devid_to_guid returns NULL with errno 0.
1009 1013 */
1010 1014 log(LOG_DEBUG, ROUTINE,
1011 1015 "failed to get devid guid on (%s)",
1012 1016 " associated with path(%s) : %s",
1013 1017 clientdevpath,
1014 1018 pathdevpath ? pathdevpath :
1015 1019 "(missing device path)",
1016 1020 strerror(errno));
1017 1021 }
1022 +
1023 + devid_free(devid);
1018 1024 } else {
1019 1025 /*
1020 1026 * device may not support proper page 83 id descriptor.
1021 1027 * leave LUID attribute to NULL and continue.
1022 1028 */
1023 1029 log(LOG_DEBUG, ROUTINE,
1024 1030 "failed to decode devid prop on (%s)",
1025 1031 " associated with path(%s) : %s",
1026 1032 clientdevpath,
1027 1033 pathdevpath ? pathdevpath :
1028 1034 "(missing device path)",
1029 1035 strerror(errno));
1030 1036 }
1031 1037 } else {
1032 1038 /* leave LUID attribute to NULL and continue. */
1033 1039 log(LOG_DEBUG, ROUTINE, "Failed to get devid on %s"
1034 1040 " associated with path(%s) : %s", clientdevpath,
1035 1041 pathdevpath ? pathdevpath : "(missing device path)",
1036 1042 strerror(errno));
1037 1043 }
1038 1044
1039 1045 if (disco_port_ptr->scsiInfo == NULL) {
1040 1046 disco_port_ptr->scsiInfo = mapping_ptr;
1041 1047 } else {
1042 1048 mapping_ptr->next = disco_port_ptr->scsiInfo;
1043 1049 disco_port_ptr->scsiInfo = mapping_ptr;
1044 1050 }
1045 1051
1046 1052 if (pathdevpath) di_devfs_path_free(pathdevpath);
1047 1053 di_devfs_path_free(clientdevpath);
1048 1054
1049 1055 return (HBA_STATUS_OK);
1050 1056 }
1051 1057
1052 1058 /*
1053 1059 * walks the devinfo tree retrieving all hba information
1054 1060 */
1055 1061 extern HBA_STATUS
1056 1062 devtree_attached_devices(di_node_t node, struct sun_sas_port *port_ptr)
1057 1063 {
1058 1064 const char ROUTINE[] = "devtree_attached_devices";
1059 1065 di_node_t nodechild = DI_NODE_NIL;
1060 1066 di_path_t path = DI_PATH_NIL;
1061 1067
1062 1068 /* child should be device */
1063 1069 if ((nodechild = di_child_node(node)) == DI_NODE_NIL) {
1064 1070 log(LOG_DEBUG, ROUTINE,
1065 1071 "No devinfo child on the HBA port node.");
1066 1072 }
1067 1073
1068 1074 if ((path = di_path_phci_next_path(node, path)) ==
1069 1075 DI_PATH_NIL) {
1070 1076 log(LOG_DEBUG, ROUTINE,
1071 1077 "No pathinfo node on the HBA port node.");
1072 1078 }
1073 1079
1074 1080 if ((nodechild == DI_NODE_NIL) && (path == DI_PATH_NIL)) {
1075 1081 return (HBA_STATUS_OK);
1076 1082 }
1077 1083
1078 1084 while (nodechild != DI_NODE_NIL) {
1079 1085 if (get_attached_devices_info(nodechild, port_ptr)
1080 1086 != HBA_STATUS_OK) {
1081 1087 break;
1082 1088 }
1083 1089 nodechild = di_sibling_node(nodechild);
1084 1090 }
1085 1091
1086 1092
1087 1093 while (path != DI_PATH_NIL) {
1088 1094 if (get_attached_paths_info(path, port_ptr)
1089 1095 != HBA_STATUS_OK) {
1090 1096 break;
1091 1097 }
1092 1098 path = di_path_phci_next_path(node, path);
1093 1099 }
1094 1100
1095 1101 return (HBA_STATUS_OK);
1096 1102 }
↓ open down ↓ |
69 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX