1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <stdio.h> 26 #include <libdevinfo.h> 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <string.h> 30 #include <fcntl.h> 31 #include <unistd.h> 32 #include <stropts.h> 33 #include <stdlib.h> 34 #include <errno.h> 35 #include <strings.h> 36 #include <libintl.h> 37 #include <net/if_types.h> 38 #include <net/if_dl.h> 39 #include <sys/dld.h> 40 #include <sys/ib/ib_types.h> 41 #include <sys/ibpart.h> 42 #include <libdllink.h> 43 #include <libdladm.h> 44 #include <libdlib.h> 45 #include <libdladm_impl.h> 46 47 /* 48 * IP over IB administration API; see PSARC/2010/085 49 */ 50 51 /* 52 * Function prototypes 53 */ 54 dladm_status_t dladm_part_create(dladm_handle_t, datalink_id_t, ib_pkey_t, 55 uint32_t, char *, datalink_id_t *, dladm_arg_list_t *); 56 static dladm_status_t i_dladm_part_create(dladm_handle_t, 57 dladm_part_attr_t *); 58 static dladm_status_t dladm_part_persist_conf(dladm_handle_t, const char *, 59 dladm_part_attr_t *); 60 static dladm_status_t i_dladm_part_delete(dladm_handle_t, datalink_id_t); 61 dladm_status_t dladm_part_delete(dladm_handle_t, datalink_id_t, int); 62 static int i_dladm_part_up(dladm_handle_t, datalink_id_t, void *); 63 dladm_status_t dladm_part_up(dladm_handle_t, datalink_id_t, uint32_t); 64 65 /* 66 * Convert a error status returned by the IP over IB kernel driver to a 67 * valid dladm status. 68 */ 69 static dladm_status_t 70 dladm_ib_ioctl_err2status(int err) 71 { 72 switch (err) { 73 case 0: 74 return (DLADM_STATUS_OK); 75 case IBD_INVALID_PORT_INST: 76 return (DLADM_STATUS_INVALID_PORT_INSTANCE); 77 case IBD_PORT_IS_DOWN: 78 return (DLADM_STATUS_PORT_IS_DOWN); 79 case IBD_PKEY_NOT_PRESENT: 80 return (DLADM_STATUS_PKEY_NOT_PRESENT); 81 case IBD_PARTITION_EXISTS: 82 return (DLADM_STATUS_PARTITION_EXISTS); 83 case IBD_INVALID_PKEY: 84 return (DLADM_STATUS_INVALID_PKEY); 85 case IBD_NO_HW_RESOURCE: 86 return (DLADM_STATUS_NO_IB_HW_RESOURCE); 87 case IBD_INVALID_PKEY_TBL_SIZE: 88 return (DLADM_STATUS_INVALID_PKEY_TBL_SIZE); 89 default: 90 return (DLADM_STATUS_FAILED); 91 } 92 } 93 94 static dladm_status_t 95 i_dladm_ib_ioctl(dladm_handle_t handle, int ioccmd, ibd_ioctl_t *iocp) 96 { 97 if (ioctl(dladm_dld_fd(handle), ioccmd, iocp) == 0) 98 return (DLADM_STATUS_OK); 99 100 if (iocp->ioc_status == 0) 101 return (dladm_errno2status(errno)); 102 103 return (dladm_ib_ioctl_err2status(iocp->ioc_status)); 104 } 105 106 /* 107 * Get the active configuration information for the partition given by 108 * the 'linkid'. 109 */ 110 static dladm_status_t 111 i_dladm_part_info_active(dladm_handle_t handle, datalink_id_t linkid, 112 dladm_part_attr_t *attrp) 113 { 114 ibpart_ioctl_t ioc; 115 dladm_status_t status = DLADM_STATUS_OK; 116 117 bzero(&ioc, sizeof (ioc)); 118 bzero(attrp, sizeof (*attrp)); 119 /* 120 * The ioc_linkid here will contain the data link id of the IB partition 121 * object. 122 */ 123 ioc.ibdioc.ioc_linkid = linkid; 124 ioc.ibdioc.ioc_info_cmd = IBD_INFO_CMD_IBPART; 125 126 status = i_dladm_ib_ioctl(handle, IBD_INFO_IBPART, (ibd_ioctl_t *)&ioc); 127 if (status != DLADM_STATUS_OK) 128 goto bail; 129 130 /* 131 * On return from the ioctl ioc_linkid field contains the IB port's 132 * linkid. 133 */ 134 attrp->dia_physlinkid = ioc.ibdioc.ioc_linkid; 135 attrp->dia_partlinkid = ioc.ioc_partid; 136 attrp->dia_pkey = ioc.ioc_pkey; 137 attrp->dia_portnum = ioc.ibdioc.ioc_portnum; 138 attrp->dia_hca_guid = ioc.ibdioc.ioc_hcaguid; 139 attrp->dia_port_guid = ioc.ibdioc.ioc_portguid; 140 attrp->dia_instance = ioc.ibdioc.ioc_port_inst; 141 142 /* 143 * If the IP over IB driver reports that this partition was created 144 * forcibly, then set the force create flag. 145 */ 146 if (ioc.ioc_force_create) 147 attrp->dia_flags |= DLADM_PART_FORCE_CREATE; 148 149 bail: 150 return (status); 151 } 152 153 /* 154 * Get the configuration information about the IB partition 'linkid' from the 155 * persistent configuration. 156 */ 157 static dladm_status_t 158 i_dladm_part_info_persist(dladm_handle_t handle, datalink_id_t linkid, 159 dladm_part_attr_t *attrp) 160 { 161 dladm_conf_t conf; 162 dladm_status_t status; 163 char linkover[MAXLINKNAMELEN]; 164 datalink_class_t class; 165 boolean_t force = B_FALSE; 166 167 /* Get the IB partition's datalink ID */ 168 if ((status = dladm_datalink_id2info(handle, linkid, NULL, &class, 169 NULL, NULL, 0)) != DLADM_STATUS_OK) 170 goto done; 171 172 bzero(attrp, sizeof (*attrp)); 173 attrp->dia_partlinkid = linkid; 174 if ((status = dladm_read_conf(handle, linkid, &conf)) != 175 DLADM_STATUS_OK) 176 return (status); 177 178 /* 179 * Get the name of the IB Phys link over which IB partition was 180 * created. 181 */ 182 status = dladm_get_conf_field(handle, conf, FLINKOVER, linkover, 183 sizeof (linkover)); 184 if (status != DLADM_STATUS_OK) { 185 attrp->dia_physlinkid = DATALINK_INVALID_LINKID; 186 goto done; 187 } else { 188 /* Get the IB Phys link's datalink ID */ 189 if ((status = dladm_name2info(handle, linkover, 190 &attrp->dia_physlinkid, NULL, NULL, NULL)) != 191 DLADM_STATUS_OK) 192 goto done; 193 } 194 195 /* Get the IB partition's P_Key */ 196 status = dladm_get_conf_field(handle, conf, FPORTPKEY, 197 &attrp->dia_pkey, sizeof (uint64_t)); 198 if (status != DLADM_STATUS_OK) 199 goto done; 200 201 if (class != DATALINK_CLASS_PART) { 202 status = DLADM_STATUS_BADARG; 203 goto done; 204 } 205 206 /* 207 * If the FFORCE field is set in the persistent configuration database 208 * set the force create flag in the partition attributes. 209 */ 210 status = dladm_get_conf_field(handle, conf, FFORCE, &force, 211 sizeof (boolean_t)); 212 if (status != DLADM_STATUS_OK) { 213 if (status != DLADM_STATUS_NOTFOUND) 214 goto done; 215 } else if (force == B_TRUE) { 216 attrp->dia_flags |= DLADM_PART_FORCE_CREATE; 217 } 218 219 status = DLADM_STATUS_OK; 220 done: 221 dladm_destroy_conf(handle, conf); 222 return (status); 223 } 224 225 /* 226 * Get the configuration information for the IB partition given by the datalink 227 * ID 'linkid'. Based on the 'flags' field the information is either from the 228 * active system (DLADM_OPT_ACTIVE) or from the persistent configuration 229 * database. 230 */ 231 dladm_status_t 232 dladm_part_info(dladm_handle_t handle, datalink_id_t linkid, 233 dladm_part_attr_t *attrp, uint32_t flags) 234 { 235 if (flags == DLADM_OPT_ACTIVE) 236 return (i_dladm_part_info_active(handle, linkid, attrp)); 237 else if (flags == DLADM_OPT_PERSIST) 238 return (i_dladm_part_info_persist(handle, linkid, attrp)); 239 else 240 return (DLADM_STATUS_BADARG); 241 } 242 243 /* 244 * Get the configuration information for the IB Phys link given by the datalink 245 * ID 'linkid'. 246 */ 247 /* ARGSUSED */ 248 dladm_status_t 249 dladm_ib_info(dladm_handle_t handle, datalink_id_t linkid, 250 dladm_ib_attr_t *attrp, uint32_t flags) 251 { 252 uint_t instance; 253 ibport_ioctl_t ioc; 254 dladm_phys_attr_t dpa; 255 dladm_status_t status = DLADM_STATUS_OK; 256 257 /* 258 * We need to get the device name of the IB Phys link to get the 259 * correct instance number of the IP over IB driver instance. 260 */ 261 if (dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE) 262 != DLADM_STATUS_OK) 263 return (DLADM_STATUS_BADARG); 264 265 /* 266 * Get the instance number of the IP over IB driver instance which 267 * represents this IB Phys link. 268 */ 269 if (dladm_parselink(dpa.dp_dev, NULL, &instance) != DLADM_STATUS_OK) 270 return (DLADM_STATUS_FAILED); 271 272 bzero(&ioc, sizeof (ioc)); 273 /* 274 * The ioc_linkid here will contain IB port linkid here. We make the 275 * first ioctl call to get the P_Key table size for this HCA port. 276 */ 277 ioc.ibdioc.ioc_linkid = linkid; 278 ioc.ibdioc.ioc_info_cmd = IBD_INFO_CMD_PKEYTBLSZ; 279 ioc.ioc_pkey_tbl_sz = 0; 280 ioc.ibdioc.ioc_port_inst = instance; 281 282 status = i_dladm_ib_ioctl(handle, IBD_INFO_IBPART, (ibd_ioctl_t *)&ioc); 283 if (status != DLADM_STATUS_OK) 284 return (status); 285 286 /* 287 * Now allocate the memory for the P_Key table based on the table size 288 * return by the ioctl. 289 */ 290 ioc.ioc_pkeys = calloc(sizeof (ib_pkey_t), ioc.ioc_pkey_tbl_sz); 291 if (ioc.ioc_pkeys == NULL) { 292 status = dladm_errno2status(errno); 293 goto bail; 294 } 295 296 /* 297 * Call the ioctl again to get the P_Key table and other IB Phys link 298 * attributes. 299 */ 300 ioc.ibdioc.ioc_linkid = linkid; 301 ioc.ibdioc.ioc_port_inst = instance; 302 ioc.ibdioc.ioc_info_cmd = IBD_INFO_CMD_IBPORT; 303 304 status = i_dladm_ib_ioctl(handle, IBD_INFO_IBPART, (ibd_ioctl_t *)&ioc); 305 if (status != DLADM_STATUS_OK) 306 goto bail; 307 308 attrp->dia_physlinkid = ioc.ibdioc.ioc_linkid; 309 attrp->dia_portnum = ioc.ibdioc.ioc_portnum; 310 attrp->dia_port_pkey_tbl_sz = ioc.ioc_pkey_tbl_sz; 311 attrp->dia_port_pkeys = ioc.ioc_pkeys; 312 attrp->dia_hca_guid = ioc.ibdioc.ioc_hcaguid; 313 attrp->dia_port_guid = ioc.ibdioc.ioc_portguid; 314 attrp->dia_instance = ioc.ibdioc.ioc_port_inst; 315 return (status); 316 bail: 317 free(ioc.ioc_pkeys); 318 return (status); 319 } 320 321 /* 322 * Free the memory allocated for the IB HCA port's P_Key table by 323 * dladm_ib_info library call. 324 */ 325 void 326 dladm_free_ib_info(dladm_ib_attr_t *attr) 327 { 328 if (attr && attr->dia_port_pkeys) 329 free(attr->dia_port_pkeys); 330 } 331 332 /* 333 * Call into the IP over IB driver to create a partition object. 334 */ 335 static dladm_status_t 336 i_dladm_part_create(dladm_handle_t handle, dladm_part_attr_t *pattr) 337 { 338 ibpart_ioctl_t ioc; 339 340 bzero(&ioc, sizeof (ioc)); 341 342 /* IB Physical datalink ID */ 343 ioc.ibdioc.ioc_linkid = pattr->dia_physlinkid; 344 /* IB Partition datalink ID */ 345 ioc.ioc_partid = pattr->dia_partlinkid; 346 ioc.ioc_pkey = pattr->dia_pkey; 347 ioc.ibdioc.ioc_port_inst = pattr->dia_instance; 348 ioc.ioc_force_create = ((pattr->dia_flags & DLADM_OPT_FORCE) 349 != 0); 350 351 return (i_dladm_ib_ioctl(handle, IBD_CREATE_IBPART, &ioc.ibdioc)); 352 } 353 354 /* 355 * Create an entry in the dladm persistent configuration database for the 356 * partition specified by pattr. 357 */ 358 dladm_status_t 359 dladm_part_persist_conf(dladm_handle_t handle, const char *pname, 360 dladm_part_attr_t *pattr) 361 { 362 363 dladm_conf_t conf; 364 dladm_status_t status; 365 char linkover[MAXLINKNAMELEN]; 366 uint64_t u64; 367 368 status = dladm_create_conf(handle, pname, pattr->dia_partlinkid, 369 DATALINK_CLASS_PART, DL_IB, &conf); 370 if (status != DLADM_STATUS_OK) 371 return (status); 372 373 /* 374 * Get the name of the IB Phys link over which this partition was 375 * created. 376 */ 377 status = dladm_datalink_id2info(handle, pattr->dia_physlinkid, 378 NULL, NULL, NULL, linkover, sizeof (linkover)); 379 if (status != DLADM_STATUS_OK) 380 return (status); 381 382 /* Store IB Phys link name (linkover) */ 383 status = dladm_set_conf_field(handle, conf, FLINKOVER, DLADM_TYPE_STR, 384 linkover); 385 if (status != DLADM_STATUS_OK) 386 return (status); 387 388 u64 = pattr->dia_pkey; 389 390 /* Store the IB Partitions P_Key */ 391 status = dladm_set_conf_field(handle, conf, FPORTPKEY, 392 DLADM_TYPE_UINT64, &u64); 393 if (status != DLADM_STATUS_OK) 394 return (status); 395 396 if (pattr->dia_flags & DLADM_OPT_FORCE) { 397 boolean_t force = B_TRUE; 398 /* Store the force create flag. */ 399 status = dladm_set_conf_field(handle, conf, FFORCE, 400 DLADM_TYPE_BOOLEAN, &force); 401 if (status != DLADM_STATUS_OK) 402 goto done; 403 } 404 405 status = dladm_write_conf(handle, conf); 406 if (status != DLADM_STATUS_OK) 407 return (status); 408 409 dladm_destroy_conf(handle, conf); 410 done: 411 return (status); 412 } 413 414 /* 415 * Create a new IB Partition datalink of name 'pname' over the IB Physical link 416 * given in 'physlinkid' with the P_key 'pkey' and return the datalink ID in 417 * 'partlinkid'. If the 'force' option is set in the 'flags' argument, the 418 * partition will be created even if the P_Key 'pkey' does not exist or if the 419 * HCA port represented by the IB Phys link is down. If the 'temporary' flag is 420 * set, then the configuration information is not added to the persistent 421 * database. 422 */ 423 dladm_status_t 424 dladm_part_create(dladm_handle_t handle, datalink_id_t physlinkid, 425 ib_pkey_t pkey, uint32_t flags, char *pname, datalink_id_t *partlinkid, 426 dladm_arg_list_t *proplist) 427 { 428 int i; 429 dladm_status_t status; 430 uint_t media; 431 boolean_t part_created = B_FALSE; 432 boolean_t conf_set = B_FALSE; 433 dladm_phys_attr_t dpa; 434 dladm_part_attr_t pattr; 435 436 pattr.dia_pkey = pkey; 437 pattr.dia_physlinkid = physlinkid; /* IB Phys link's datalink id */ 438 pattr.dia_flags = flags; 439 440 flags &= ~DLADM_OPT_FORCE; 441 442 /* 443 * Check whether the PKEY is valid. If not, return immediately 444 * Only full members are allowed as per the IPoIB specification 445 */ 446 if (pattr.dia_pkey <= IB_PKEY_INVALID_FULL) 447 return (DLADM_STATUS_INVALID_PKEY); 448 449 /* 450 * Get the media type of the Phys link datalink ID provided and 451 * make sure that it is Infiniband media DL_IB) 452 */ 453 if ((status = dladm_datalink_id2info(handle, pattr.dia_physlinkid, NULL, 454 NULL, &media, NULL, 0)) != DLADM_STATUS_OK) 455 return (status); 456 457 if (media != DL_IB) 458 return (dladm_errno2status(ENOTSUP)); 459 460 /* 461 * Get the instance number of the IP over IB driver instance which the 462 * IB Phys link 'physlinkid' over which we will be creating our IB 463 * partition. 464 */ 465 if ((status = dladm_phys_info(handle, pattr.dia_physlinkid, &dpa, 466 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) 467 return (status); 468 469 if (dladm_parselink(dpa.dp_dev, NULL, (uint_t *)&pattr.dia_instance) != 470 DLADM_STATUS_OK) 471 return (DLADM_STATUS_FAILED); 472 473 474 if ((status = dladm_create_datalink_id(handle, pname, 475 DATALINK_CLASS_PART, DL_IB, flags, &pattr.dia_partlinkid)) != 476 DLADM_STATUS_OK) 477 return (status); 478 479 /* 480 * Create the IB partition object. 481 */ 482 status = i_dladm_part_create(handle, &pattr); 483 if (status != DLADM_STATUS_OK) 484 goto done; 485 486 part_created = B_TRUE; 487 488 /* 489 * If the persist flag is set then write this partition information 490 * to the persistent configuration. 491 */ 492 if (pattr.dia_flags & DLADM_OPT_PERSIST) { 493 status = dladm_part_persist_conf(handle, pname, &pattr); 494 if (status != DLADM_STATUS_OK) 495 goto done; 496 conf_set = B_TRUE; 497 } 498 499 /* 500 * If the name-value pair list of properties were provided set those 501 * properties over the datalink. 502 */ 503 if (proplist != NULL) { 504 for (i = 0; i < proplist->al_count; i++) { 505 dladm_arg_info_t *aip = &proplist->al_info[i]; 506 507 status = dladm_set_linkprop(handle, 508 pattr.dia_partlinkid, aip->ai_name, aip->ai_val, 509 aip->ai_count, pattr.dia_flags); 510 if (status != DLADM_STATUS_OK) 511 break; 512 } 513 } 514 done: 515 if (status != DLADM_STATUS_OK) { 516 if (conf_set) 517 (void) dladm_remove_conf(handle, pattr.dia_partlinkid); 518 if (part_created) 519 (void) i_dladm_part_delete(handle, 520 pattr.dia_partlinkid); 521 (void) dladm_destroy_datalink_id(handle, pattr.dia_partlinkid, 522 flags); 523 } 524 525 if (partlinkid != NULL) 526 *partlinkid = pattr.dia_partlinkid; 527 528 return (status); 529 } 530 531 /* 532 * Call into the IP over IB driver to delete the IB partition and free up all 533 * the resources allocated for it. 534 */ 535 static dladm_status_t 536 i_dladm_part_delete(dladm_handle_t handle, datalink_id_t partid) 537 { 538 ibpart_ioctl_t ioc; 539 540 bzero(&ioc, sizeof (ioc)); 541 ioc.ioc_partid = partid; 542 return (i_dladm_ib_ioctl(handle, IBD_DELETE_IBPART, &ioc.ibdioc)); 543 } 544 545 /* 546 * Delete an IB partition if 'flags' contains the active flag. Update the 547 * persistent configuration if 'flags' contains the persist flag. 548 */ 549 dladm_status_t 550 dladm_part_delete(dladm_handle_t handle, datalink_id_t partid, int flags) 551 { 552 dladm_status_t status = DLADM_STATUS_OK; 553 datalink_class_t class; 554 555 if (flags == 0) 556 return (DLADM_STATUS_BADARG); 557 558 /* 559 * Make sure that the datalinkid provided is an IB partition class 560 * datalink ID. 561 */ 562 if ((dladm_datalink_id2info(handle, partid, NULL, &class, NULL, NULL, 0) 563 != DLADM_STATUS_OK)) 564 return (DLADM_STATUS_BADARG); 565 566 if (class != DATALINK_CLASS_PART) 567 return (DLADM_STATUS_BADARG); 568 569 if ((flags & DLADM_OPT_ACTIVE) != 0) { 570 status = i_dladm_part_delete(handle, partid); 571 if (status == DLADM_STATUS_OK) { 572 (void) dladm_set_linkprop(handle, partid, NULL, NULL, 0, 573 DLADM_OPT_ACTIVE); 574 (void) dladm_destroy_datalink_id(handle, partid, 575 DLADM_OPT_ACTIVE); 576 } else if (status != DLADM_STATUS_NOTFOUND || 577 !(flags & DLADM_OPT_PERSIST)) { 578 return (status); 579 } 580 } 581 582 if ((flags & DLADM_OPT_PERSIST) != 0) { 583 dladm_status_t db_status; 584 db_status = dladm_remove_conf(handle, partid); 585 586 /* 587 * A partition could have been temporarily deleted in which 588 * case the delete of the active partition above would have 589 * failed. In that case, we update the status to be returned 590 * to that of the status returned for deleting the persistent 591 * database entry. 592 */ 593 if (status == DLADM_STATUS_NOTFOUND) 594 status = db_status; 595 596 (void) dladm_destroy_datalink_id(handle, partid, 597 DLADM_OPT_PERSIST); 598 } 599 600 return (status); 601 } 602 603 /* 604 * Call into the IP over IB driver to create the active instances of one or all 605 * IB partitions present in the persistent configuration. 606 */ 607 /* ARGSUSED */ 608 static int 609 i_dladm_part_up(dladm_handle_t handle, datalink_id_t plinkid, void *arg) 610 { 611 dladm_conf_t conf; 612 datalink_id_t linkid; 613 ib_pkey_t pkey; 614 uint64_t u64; 615 char linkover[MAXLINKNAMELEN]; 616 dladm_status_t status; 617 dladm_phys_attr_t dpa; 618 dladm_part_attr_t pattr; 619 620 /* 621 * plinkid is the IB partition datalink's ID. Get an handle to the 622 * persistent configuration entry for this datalink ID. If this datalink 623 * ID is not present in the persistent configuration return. 624 */ 625 if ((status = dladm_read_conf(handle, plinkid, &conf)) != 626 DLADM_STATUS_OK) 627 return (status); 628 629 /* 630 * Get the name of the IB Phys link over which this partition was 631 * created. 632 */ 633 status = dladm_get_conf_field(handle, conf, FLINKOVER, linkover, 634 sizeof (linkover)); 635 if (status != DLADM_STATUS_OK) 636 goto done; 637 638 if ((status = dladm_name2info(handle, linkover, &linkid, NULL, NULL, 639 NULL)) != DLADM_STATUS_OK) 640 goto done; 641 642 /* 643 * Get the phys attribute of the IB Phys link to get the device name 644 * associated with the phys link. We need this to get the IP over IB 645 * driver instance number. 646 */ 647 if (dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE) 648 != DLADM_STATUS_OK) 649 goto done; 650 651 /* Get the IB partition's P_key */ 652 status = dladm_get_conf_field(handle, conf, FPORTPKEY, &u64, 653 sizeof (u64)); 654 if (status != DLADM_STATUS_OK) 655 goto done; 656 657 pkey = (ib_pkey_t)u64; 658 659 /* 660 * We always set the force flag during dladm_part_up because we want 661 * the partition creation to succeed even if the IB HCA port over which 662 * the partition is being created is still down. Since dladm_part_up 663 * is usually invoked during early boot sequence, it is possible under 664 * some IB subnet configurations for dladm_up_part to be called before 665 * the IB link negotiation is completed and port state is set to active 666 * and P_Key table is updated. 667 */ 668 pattr.dia_flags = DLADM_OPT_FORCE | DLADM_OPT_ACTIVE | 669 DLADM_OPT_PERSIST; 670 /* IB Phys link's datalink ID. */ 671 pattr.dia_physlinkid = linkid; 672 /* IB Partition's datalink ID. */ 673 pattr.dia_partlinkid = plinkid; 674 pattr.dia_pkey = pkey; 675 if (dladm_parselink(dpa.dp_dev, NULL, (uint_t *)&pattr.dia_instance) != 676 DLADM_STATUS_OK) 677 return (DLADM_WALK_CONTINUE); 678 679 /* Create the active IB Partition object. */ 680 if (i_dladm_part_create(handle, &pattr) == DLADM_STATUS_OK && 681 dladm_up_datalink_id(handle, plinkid) != DLADM_STATUS_OK) 682 (void) i_dladm_part_delete(handle, linkid); 683 684 done: 685 dladm_destroy_conf(handle, conf); 686 return (DLADM_WALK_CONTINUE); 687 } 688 689 /* 690 * Bring up one or all IB partition(s) present in the persistent configuration 691 * database. If we need to bring up one IB Partition, its datalink ID is 692 * provided in 'linkid'. 693 */ 694 /* ARGSUSED */ 695 dladm_status_t 696 dladm_part_up(dladm_handle_t handle, datalink_id_t linkid, uint32_t flags) 697 { 698 dladm_status_t status = DLADM_STATUS_OK; 699 700 if (linkid == DATALINK_ALL_LINKID) { 701 (void) dladm_walk_datalink_id(i_dladm_part_up, handle, 702 &status, DATALINK_CLASS_PART, DATALINK_ANY_MEDIATYPE, 703 DLADM_OPT_PERSIST); 704 return (DLADM_STATUS_OK); 705 } else { 706 (void) i_dladm_part_up(handle, linkid, &status); 707 return (status); 708 } 709 } 710