1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2019 Joyent, Inc. 14 */ 15 16 /* 17 * This implements logic to allow us to dump IMC data for decoding purposes, 18 * such that we can later encode it elsewhere. In general, dumping is done by 19 * the kernel and reconstituting this data is done by user land. 20 */ 21 22 #include "imc.h" 23 24 #ifndef _KERNEL 25 #include <stdint.h> 26 #include <strings.h> 27 #endif /* !_KERNEL */ 28 29 30 static nvlist_t * 31 imc_dump_sad(imc_sad_t *sad) 32 { 33 uint_t i; 34 nvlist_t *nvl; 35 nvlist_t *rules[IMC_MAX_SAD_RULES]; 36 nvlist_t *routes[IMC_MAX_SAD_MCROUTES]; 37 38 nvl = fnvlist_alloc(); 39 fnvlist_add_uint32(nvl, "isad_flags", sad->isad_flags); 40 fnvlist_add_uint32(nvl, "isad_valid", sad->isad_valid); 41 fnvlist_add_uint64(nvl, "isad_tolm", sad->isad_tolm); 42 fnvlist_add_uint64(nvl, "isad_tohm", sad->isad_tohm); 43 44 for (i = 0; i < sad->isad_nrules; i++) { 45 nvlist_t *n = fnvlist_alloc(); 46 imc_sad_rule_t *r = &sad->isad_rules[i]; 47 48 fnvlist_add_boolean_value(n, "isr_enable", r->isr_enable); 49 fnvlist_add_boolean_value(n, "isr_a7mode", r->isr_a7mode); 50 fnvlist_add_boolean_value(n, "isr_need_mod3", r->isr_need_mod3); 51 fnvlist_add_uint64(n, "isr_limit", r->isr_limit); 52 fnvlist_add_uint32(n, "isr_type", r->isr_type); 53 fnvlist_add_uint32(n, "isr_imode", r->isr_imode); 54 fnvlist_add_uint32(n, "isr_mod_mode", r->isr_mod_mode); 55 fnvlist_add_uint32(n, "isr_mod_type", r->isr_mod_type); 56 fnvlist_add_uint8_array(n, "isr_targets", r->isr_targets, 57 r->isr_ntargets); 58 59 rules[i] = n; 60 } 61 fnvlist_add_nvlist_array(nvl, "isad_rules", rules, sad->isad_nrules); 62 for (i = 0; i < sad->isad_nrules; i++) { 63 nvlist_free(rules[i]); 64 } 65 66 if (sad->isad_mcroute.ismc_nroutes == 0) { 67 return (nvl); 68 } 69 70 for (i = 0; i < sad->isad_mcroute.ismc_nroutes; i++) { 71 nvlist_t *r = fnvlist_alloc(); 72 imc_sad_mcroute_entry_t *e = 73 &sad->isad_mcroute.ismc_mcroutes[i]; 74 75 fnvlist_add_uint8(r, "ismce_imc", e->ismce_imc); 76 fnvlist_add_uint8(r, "ismce_pchannel", e->ismce_pchannel); 77 routes[i] = r; 78 } 79 fnvlist_add_nvlist_array(nvl, "isad_mcroute", routes, i); 80 for (i = 0; i < sad->isad_mcroute.ismc_nroutes; i++) { 81 nvlist_free(routes[i]); 82 } 83 84 return (nvl); 85 } 86 87 static nvlist_t * 88 imc_dump_tad(imc_tad_t *tad) 89 { 90 uint_t i; 91 nvlist_t *nvl; 92 nvlist_t *rules[IMC_MAX_TAD_RULES]; 93 94 nvl = fnvlist_alloc(); 95 fnvlist_add_uint32(nvl, "itad_valid", tad->itad_valid); 96 fnvlist_add_uint32(nvl, "itad_flags", tad->itad_flags); 97 for (i = 0; i < tad->itad_nrules; i++) { 98 nvlist_t *t = fnvlist_alloc(); 99 imc_tad_rule_t *r = &tad->itad_rules[i]; 100 101 fnvlist_add_uint64(t, "itr_base", r->itr_base); 102 fnvlist_add_uint64(t, "itr_limit", r->itr_limit); 103 fnvlist_add_uint8(t, "itr_sock_way", r->itr_sock_way); 104 fnvlist_add_uint8(t, "itr_chan_way", r->itr_chan_way); 105 fnvlist_add_uint32(t, "itr_sock_gran", r->itr_sock_gran); 106 fnvlist_add_uint32(t, "itr_chan_gran", r->itr_chan_gran); 107 fnvlist_add_uint8_array(t, "itr_targets", r->itr_targets, 108 r->itr_ntargets); 109 110 rules[i] = t; 111 } 112 fnvlist_add_nvlist_array(nvl, "itad_rules", rules, tad->itad_nrules); 113 for (i = 0; i < tad->itad_nrules; i++) { 114 nvlist_free(rules[i]); 115 } 116 117 return (nvl); 118 } 119 120 static nvlist_t * 121 imc_dump_channel(imc_channel_t *chan) 122 { 123 uint_t i; 124 nvlist_t *nvl; 125 nvlist_t *dimms[IMC_MAX_DIMMPERCHAN]; 126 nvlist_t *ranks[IMC_MAX_RANK_WAYS]; 127 128 nvl = fnvlist_alloc(); 129 fnvlist_add_uint32(nvl, "ich_valid", chan->ich_valid); 130 for (i = 0; i < chan->ich_ndimms; i++) { 131 nvlist_t *d = fnvlist_alloc(); 132 imc_dimm_t *dimm = &chan->ich_dimms[i]; 133 134 fnvlist_add_uint32(d, "idimm_valid", dimm->idimm_valid); 135 fnvlist_add_boolean_value(d, "idimm_present", 136 dimm->idimm_present); 137 if (!dimm->idimm_present) 138 goto add; 139 140 fnvlist_add_uint8(d, "idimm_nbanks", dimm->idimm_nbanks); 141 fnvlist_add_uint8(d, "idimm_nranks", dimm->idimm_nranks); 142 fnvlist_add_uint8(d, "idimm_width", dimm->idimm_width); 143 fnvlist_add_uint8(d, "idimm_density", dimm->idimm_density); 144 fnvlist_add_uint8(d, "idimm_nrows", dimm->idimm_nrows); 145 fnvlist_add_uint8(d, "idimm_ncolumns", dimm->idimm_ncolumns); 146 fnvlist_add_uint64(d, "idimm_size", dimm->idimm_size); 147 add: 148 dimms[i] = d; 149 } 150 fnvlist_add_nvlist_array(nvl, "ich_dimms", dimms, i); 151 for (i = 0; i < chan->ich_ndimms; i++) { 152 nvlist_free(dimms[i]); 153 } 154 155 fnvlist_add_uint64_array(nvl, "ich_tad_offsets", chan->ich_tad_offsets, 156 chan->ich_ntad_offsets); 157 158 for (i = 0; i < chan->ich_nrankileaves; i++) { 159 uint_t j; 160 nvlist_t *r = fnvlist_alloc(); 161 nvlist_t *ileaves[IMC_MAX_RANK_INTERLEAVES]; 162 imc_rank_ileave_t *rank = &chan->ich_rankileaves[i]; 163 164 fnvlist_add_boolean_value(r, "irle_enabled", 165 rank->irle_enabled); 166 fnvlist_add_uint8(r, "irle_nways", rank->irle_nways); 167 fnvlist_add_uint8(r, "irle_nwaysbits", rank->irle_nwaysbits); 168 fnvlist_add_uint64(r, "irle_limit", rank->irle_limit); 169 170 for (j = 0; j < rank->irle_nentries; j++) { 171 nvlist_t *e = fnvlist_alloc(); 172 173 fnvlist_add_uint8(e, "irle_target", 174 rank->irle_entries[j].irle_target); 175 fnvlist_add_uint64(e, "irle_offset", 176 rank->irle_entries[j].irle_offset); 177 ileaves[j] = e; 178 } 179 fnvlist_add_nvlist_array(r, "irle_entries", ileaves, j); 180 for (j = 0; j < rank->irle_nentries; j++) { 181 nvlist_free(ileaves[j]); 182 } 183 184 ranks[i] = r; 185 } 186 fnvlist_add_nvlist_array(nvl, "ich_rankileaves", ranks, i); 187 for (i = 0; i < chan->ich_nrankileaves; i++) { 188 nvlist_free(ranks[i]); 189 } 190 191 return (nvl); 192 } 193 194 static nvlist_t * 195 imc_dump_mc(imc_mc_t *mc) 196 { 197 uint_t i; 198 nvlist_t *nvl; 199 nvlist_t *channels[IMC_MAX_CHANPERMC]; 200 201 nvl = fnvlist_alloc(); 202 fnvlist_add_boolean_value(nvl, "icn_ecc", mc->icn_ecc); 203 fnvlist_add_boolean_value(nvl, "icn_lockstep", mc->icn_lockstep); 204 fnvlist_add_boolean_value(nvl, "icn_closed", mc->icn_closed); 205 fnvlist_add_uint32(nvl, "icn_dimm_type", mc->icn_dimm_type); 206 207 for (i = 0; i < mc->icn_nchannels; i++) { 208 channels[i] = imc_dump_channel(&mc->icn_channels[i]); 209 } 210 fnvlist_add_nvlist_array(nvl, "icn_channels", channels, i); 211 for (i = 0; i < mc->icn_nchannels; i++) { 212 nvlist_free(channels[i]); 213 } 214 215 return (nvl); 216 } 217 218 static nvlist_t * 219 imc_dump_socket(imc_socket_t *sock) 220 { 221 uint_t i; 222 nvlist_t *nvl, *sad; 223 nvlist_t *tad[IMC_MAX_TAD]; 224 nvlist_t *mc[IMC_MAX_IMCPERSOCK]; 225 226 nvl = fnvlist_alloc(); 227 228 sad = imc_dump_sad(&sock->isock_sad); 229 fnvlist_add_nvlist(nvl, "isock_sad", sad); 230 nvlist_free(sad); 231 232 for (i = 0; i < sock->isock_ntad; i++) { 233 tad[i] = imc_dump_tad(&sock->isock_tad[i]); 234 } 235 fnvlist_add_nvlist_array(nvl, "isock_tad", tad, i); 236 for (i = 0; i < sock->isock_ntad; i++) { 237 fnvlist_free(tad[i]); 238 } 239 240 fnvlist_add_uint32(nvl, "isock_nodeid", sock->isock_nodeid); 241 242 for (i = 0; i < sock->isock_nimc; i++) { 243 mc[i] = imc_dump_mc(&sock->isock_imcs[i]); 244 } 245 fnvlist_add_nvlist_array(nvl, "isock_imcs", mc, i); 246 for (i = 0; i < sock->isock_nimc; i++) { 247 fnvlist_free(mc[i]); 248 } 249 return (nvl); 250 } 251 252 nvlist_t * 253 imc_dump_decoder(imc_t *imc) 254 { 255 uint_t i; 256 nvlist_t *nvl, *invl; 257 nvlist_t *sockets[IMC_MAX_SOCKETS]; 258 259 nvl = fnvlist_alloc(); 260 fnvlist_add_uint32(nvl, "mc_dump_version", 0); 261 fnvlist_add_string(nvl, "mc_dump_driver", "imc"); 262 263 invl = fnvlist_alloc(); 264 fnvlist_add_uint32(invl, "imc_gen", imc->imc_gen); 265 266 for (i = 0; i < imc->imc_nsockets; i++) { 267 sockets[i] = imc_dump_socket(&imc->imc_sockets[i]); 268 } 269 fnvlist_add_nvlist_array(invl, "imc_sockets", sockets, i); 270 fnvlist_add_nvlist(nvl, "imc", invl); 271 272 for (i = 0; i < imc->imc_nsockets; i++) { 273 nvlist_free(sockets[i]); 274 } 275 nvlist_free(invl); 276 277 return (nvl); 278 } 279 280 static boolean_t 281 imc_restore_sad(nvlist_t *nvl, imc_sad_t *sad) 282 { 283 nvlist_t **rules, **routes; 284 uint_t i, nroutes; 285 286 if (nvlist_lookup_uint32(nvl, "isad_flags", &sad->isad_flags) != 0 || 287 nvlist_lookup_uint32(nvl, "isad_valid", &sad->isad_valid) != 0 || 288 nvlist_lookup_uint64(nvl, "isad_tolm", &sad->isad_tolm) != 0 || 289 nvlist_lookup_uint64(nvl, "isad_tohm", &sad->isad_tohm) != 0 || 290 nvlist_lookup_nvlist_array(nvl, "isad_rules", 291 &rules, &sad->isad_nrules) != 0) { 292 return (B_FALSE); 293 } 294 295 for (i = 0; i < sad->isad_nrules; i++) { 296 imc_sad_rule_t *r = &sad->isad_rules[i]; 297 uint8_t *targs; 298 299 if (nvlist_lookup_boolean_value(rules[i], "isr_enable", 300 &r->isr_enable) != 0 || 301 nvlist_lookup_boolean_value(rules[i], "isr_a7mode", 302 &r->isr_a7mode) != 0 || 303 nvlist_lookup_boolean_value(rules[i], "isr_need_mod3", 304 &r->isr_need_mod3) != 0 || 305 nvlist_lookup_uint64(rules[i], "isr_limit", 306 &r->isr_limit) != 0 || 307 nvlist_lookup_uint32(rules[i], "isr_type", 308 &r->isr_type) != 0 || 309 nvlist_lookup_uint32(rules[i], "isr_imode", 310 &r->isr_imode) != 0 || 311 nvlist_lookup_uint32(rules[i], "isr_mod_mode", 312 &r->isr_mod_mode) != 0 || 313 nvlist_lookup_uint32(rules[i], "isr_mod_type", 314 &r->isr_mod_type) != 0 || 315 nvlist_lookup_uint8_array(rules[i], "isr_targets", &targs, 316 &r->isr_ntargets) != 0 || 317 r->isr_ntargets > IMC_MAX_SAD_RULES) { 318 return (B_FALSE); 319 } 320 321 bcopy(targs, r->isr_targets, r->isr_ntargets * 322 sizeof (uint8_t)); 323 } 324 325 /* 326 * The mcroutes entry right now is only included conditionally. 327 */ 328 if (nvlist_lookup_nvlist_array(nvl, "isad_mcroute", &routes, 329 &nroutes) == 0) { 330 if (nroutes > IMC_MAX_SAD_MCROUTES) 331 return (B_FALSE); 332 sad->isad_mcroute.ismc_nroutes = nroutes; 333 for (i = 0; i < nroutes; i++) { 334 imc_sad_mcroute_entry_t *r = 335 &sad->isad_mcroute.ismc_mcroutes[i]; 336 if (nvlist_lookup_uint8(routes[i], "ismce_imc", 337 &r->ismce_imc) != 0 || 338 nvlist_lookup_uint8(routes[i], "ismce_pchannel", 339 &r->ismce_pchannel) != 0) { 340 return (B_FALSE); 341 } 342 } 343 } 344 345 return (B_TRUE); 346 } 347 348 static boolean_t 349 imc_restore_tad(nvlist_t *nvl, imc_tad_t *tad) 350 { 351 nvlist_t **rules; 352 353 if (nvlist_lookup_uint32(nvl, "itad_valid", &tad->itad_valid) != 0 || 354 nvlist_lookup_uint32(nvl, "itad_flags", &tad->itad_flags) != 0 || 355 nvlist_lookup_nvlist_array(nvl, "itad_rules", &rules, 356 &tad->itad_nrules) != 0 || tad->itad_nrules > IMC_MAX_TAD_RULES) { 357 return (B_FALSE); 358 } 359 360 for (uint_t i = 0; i < tad->itad_nrules; i++) { 361 imc_tad_rule_t *r = &tad->itad_rules[i]; 362 uint8_t *targs; 363 364 if (nvlist_lookup_uint64(rules[i], "itr_base", 365 &r->itr_base) != 0 || 366 nvlist_lookup_uint64(rules[i], "itr_limit", 367 &r->itr_limit) != 0 || 368 nvlist_lookup_uint8(rules[i], "itr_sock_way", 369 &r->itr_sock_way) != 0 || 370 nvlist_lookup_uint8(rules[i], "itr_chan_way", 371 &r->itr_chan_way) != 0 || 372 nvlist_lookup_uint32(rules[i], "itr_sock_gran", 373 &r->itr_sock_gran) != 0 || 374 nvlist_lookup_uint32(rules[i], "itr_chan_gran", 375 &r->itr_chan_gran) != 0 || 376 nvlist_lookup_uint8_array(rules[i], "itr_targets", 377 &targs, &r->itr_ntargets) != 0 || 378 r->itr_ntargets > IMC_MAX_TAD_TARGETS) { 379 return (B_FALSE); 380 } 381 382 bcopy(targs, r->itr_targets, r->itr_ntargets * 383 sizeof (uint8_t)); 384 } 385 386 return (B_TRUE); 387 } 388 389 static boolean_t 390 imc_restore_channel(nvlist_t *nvl, imc_channel_t *chan) 391 { 392 nvlist_t **dimms, **rir; 393 uint64_t *tadoff; 394 395 if (nvlist_lookup_uint32(nvl, "ich_valid", &chan->ich_valid) != 0 || 396 nvlist_lookup_nvlist_array(nvl, "ich_dimms", &dimms, 397 &chan->ich_ndimms) != 0 || 398 chan->ich_ndimms > IMC_MAX_DIMMPERCHAN || 399 nvlist_lookup_uint64_array(nvl, "ich_tad_offsets", &tadoff, 400 &chan->ich_ntad_offsets) != 0 || 401 chan->ich_ntad_offsets > IMC_MAX_TAD_RULES || 402 nvlist_lookup_nvlist_array(nvl, "ich_rankileaves", &rir, 403 &chan->ich_nrankileaves) != 0 || 404 chan->ich_nrankileaves > IMC_MAX_RANK_WAYS) { 405 return (B_FALSE); 406 } 407 408 for (uint_t i = 0; i < chan->ich_ndimms; i++) { 409 imc_dimm_t *d = &chan->ich_dimms[i]; 410 411 if (nvlist_lookup_uint32(dimms[i], "idimm_valid", 412 &d->idimm_valid) != 0 || 413 nvlist_lookup_boolean_value(dimms[i], "idimm_present", 414 &d->idimm_present) != 0) { 415 return (B_FALSE); 416 } 417 418 if (!d->idimm_present) 419 continue; 420 421 if (nvlist_lookup_uint8(dimms[i], "idimm_nbanks", 422 &d->idimm_nbanks) != 0 || 423 nvlist_lookup_uint8(dimms[i], "idimm_nranks", 424 &d->idimm_nranks) != 0 || 425 nvlist_lookup_uint8(dimms[i], "idimm_width", 426 &d->idimm_width) != 0 || 427 nvlist_lookup_uint8(dimms[i], "idimm_density", 428 &d->idimm_density) != 0 || 429 nvlist_lookup_uint8(dimms[i], "idimm_nrows", 430 &d->idimm_nrows) != 0 || 431 nvlist_lookup_uint8(dimms[i], "idimm_ncolumns", 432 &d->idimm_ncolumns) != 0 || 433 nvlist_lookup_uint64(dimms[i], "idimm_size", 434 &d->idimm_size) != 0) { 435 return (B_FALSE); 436 } 437 } 438 439 bcopy(tadoff, chan->ich_tad_offsets, chan->ich_ntad_offsets * 440 sizeof (uint64_t)); 441 442 for (uint_t i = 0; i < chan->ich_nrankileaves; i++) { 443 nvlist_t **ileaves; 444 imc_rank_ileave_t *r = &chan->ich_rankileaves[i]; 445 446 if (nvlist_lookup_boolean_value(rir[i], "irle_enabled", 447 &r->irle_enabled) != 0 || 448 nvlist_lookup_uint8(rir[i], "irle_nways", 449 &r->irle_nways) != 0 || 450 nvlist_lookup_uint8(rir[i], "irle_nwaysbits", 451 &r->irle_nwaysbits) != 0 || 452 nvlist_lookup_uint64(rir[i], "irle_limit", 453 &r->irle_limit) != 0 || 454 nvlist_lookup_nvlist_array(rir[i], "irle_entries", 455 &ileaves, &r->irle_nentries) != 0 || 456 r->irle_nentries > IMC_MAX_RANK_INTERLEAVES) { 457 return (B_FALSE); 458 } 459 460 for (uint_t j = 0; j < r->irle_nentries; j++) { 461 imc_rank_ileave_entry_t *ril = &r->irle_entries[j]; 462 463 if (nvlist_lookup_uint8(ileaves[j], "irle_target", 464 &ril->irle_target) != 0 || 465 nvlist_lookup_uint64(ileaves[j], "irle_offset", 466 &ril->irle_offset) != 0) { 467 return (B_FALSE); 468 } 469 } 470 } 471 472 return (B_TRUE); 473 } 474 475 static boolean_t 476 imc_restore_mc(nvlist_t *nvl, imc_mc_t *mc) 477 { 478 nvlist_t **channels; 479 480 if (nvlist_lookup_boolean_value(nvl, "icn_ecc", &mc->icn_ecc) != 0 || 481 nvlist_lookup_boolean_value(nvl, "icn_lockstep", 482 &mc->icn_lockstep) != 0 || 483 nvlist_lookup_boolean_value(nvl, "icn_closed", 484 &mc->icn_closed) != 0 || 485 nvlist_lookup_uint32(nvl, "icn_dimm_type", 486 &mc->icn_dimm_type) != 0 || 487 nvlist_lookup_nvlist_array(nvl, "icn_channels", &channels, 488 &mc->icn_nchannels) != 0 || mc->icn_nchannels > IMC_MAX_CHANPERMC) { 489 return (B_FALSE); 490 } 491 492 for (uint_t i = 0; i < mc->icn_nchannels; i++) { 493 if (!imc_restore_channel(channels[i], &mc->icn_channels[i])) { 494 return (B_FALSE); 495 } 496 } 497 498 return (B_TRUE); 499 } 500 501 static boolean_t 502 imc_restore_socket(nvlist_t *nvl, imc_socket_t *sock) 503 { 504 uint_t i; 505 nvlist_t *sad, **tads, **imcs; 506 507 if (nvlist_lookup_nvlist(nvl, "isock_sad", &sad) != 0 || 508 nvlist_lookup_nvlist_array(nvl, "isock_tad", &tads, 509 &sock->isock_ntad) != 0 || 510 nvlist_lookup_uint32(nvl, "isock_nodeid", 511 &sock->isock_nodeid) != 0 || 512 nvlist_lookup_nvlist_array(nvl, "isock_imcs", &imcs, 513 &sock->isock_nimc) != 0 || 514 sock->isock_ntad > IMC_MAX_TAD || 515 sock->isock_nimc > IMC_MAX_IMCPERSOCK) { 516 return (B_FALSE); 517 } 518 519 if (!imc_restore_sad(sad, &sock->isock_sad)) { 520 return (B_FALSE); 521 } 522 523 for (i = 0; i < sock->isock_ntad; i++) { 524 if (!imc_restore_tad(tads[i], &sock->isock_tad[i])) { 525 return (B_FALSE); 526 } 527 } 528 529 for (i = 0; i < sock->isock_nimc; i++) { 530 if (!imc_restore_mc(imcs[i], &sock->isock_imcs[i])) { 531 return (B_FALSE); 532 } 533 } 534 535 return (B_TRUE); 536 } 537 538 boolean_t 539 imc_restore_decoder(nvlist_t *nvl, imc_t *imc) 540 { 541 uint_t i; 542 uint32_t vers; 543 nvlist_t *invl, **socks; 544 char *driver; 545 546 bzero(imc, sizeof (imc_t)); 547 548 if (nvlist_lookup_uint32(nvl, "mc_dump_version", &vers) != 0 || 549 vers != 0 || 550 nvlist_lookup_string(nvl, "mc_dump_driver", &driver) != 0 || 551 strcmp(driver, "imc") != 0 || 552 nvlist_lookup_nvlist(nvl, "imc", &invl) != 0) { 553 return (B_FALSE); 554 } 555 556 if (nvlist_lookup_uint32(invl, "imc_gen", &imc->imc_gen) != 0 || 557 nvlist_lookup_nvlist_array(invl, "imc_sockets", &socks, 558 &imc->imc_nsockets) != 0 || 559 imc->imc_nsockets > IMC_MAX_SOCKETS) { 560 return (B_FALSE); 561 } 562 563 for (i = 0; i < imc->imc_nsockets; i++) { 564 if (!imc_restore_socket(socks[i], &imc->imc_sockets[i])) 565 return (B_FALSE); 566 } 567 568 return (B_TRUE); 569 } 570