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 conf.ds_readonly = B_FALSE; 168 conf.ds_confid = DLADM_INVALID_CONF; 169 170 /* Get the IB partition's datalink ID */ 171 if ((status = dladm_datalink_id2info(handle, linkid, NULL, &class, 172 NULL, NULL, 0)) != DLADM_STATUS_OK) 173 goto done; 174 175 bzero(attrp, sizeof (*attrp)); 176 attrp->dia_partlinkid = linkid; 177 if ((status = dladm_getsnap_conf(handle, linkid, &conf)) != 178 DLADM_STATUS_OK) 179 return (status); 180 181 /* 182 * Get the name of the IB Phys link over which IB partition was 183 * created. 184 */ 185 status = dladm_get_conf_field(handle, conf, FLINKOVER, linkover, 186 sizeof (linkover)); 187 if (status != DLADM_STATUS_OK) { 188 attrp->dia_physlinkid = DATALINK_INVALID_LINKID; 189 goto done; 190 } else { 191 /* Get the IB Phys link's datalink ID */ 192 if ((status = dladm_name2info(handle, linkover, 193 &attrp->dia_physlinkid, NULL, NULL, NULL)) != 194 DLADM_STATUS_OK) 195 goto done; 196 } 197 198 /* Get the IB partition's P_Key */ 199 status = dladm_get_conf_field(handle, conf, FPORTPKEY, 200 &attrp->dia_pkey, sizeof (uint64_t)); 201 if (status != DLADM_STATUS_OK) 202 goto done; 203 204 if (class != DATALINK_CLASS_PART) { 205 status = DLADM_STATUS_BADARG; 206 goto done; 207 } 208 209 /* 210 * If the FFORCE field is set in the persistent configuration database 211 * set the force create flag in the partition attributes. 212 */ 213 status = dladm_get_conf_field(handle, conf, FFORCE, &force, 214 sizeof (boolean_t)); 215 if (status != DLADM_STATUS_OK) { 216 if (status != DLADM_STATUS_NOTFOUND) 217 goto done; 218 } else if (force == B_TRUE) { 219 attrp->dia_flags |= DLADM_PART_FORCE_CREATE; 220 } 221 222 status = DLADM_STATUS_OK; 223 done: 224 dladm_destroy_conf(handle, conf); 225 return (status); 226 } 227 228 /* 229 * Get the configuration information for the IB partition given by the datalink 230 * ID 'linkid'. Based on the 'flags' field the information is either from the 231 * active system (DLADM_OPT_ACTIVE) or from the persistent configuration 232 * database. 233 */ 234 dladm_status_t 235 dladm_part_info(dladm_handle_t handle, datalink_id_t linkid, 236 dladm_part_attr_t *attrp, uint32_t flags) 237 { 238 if (flags == DLADM_OPT_ACTIVE) 239 return (i_dladm_part_info_active(handle, linkid, attrp)); 240 else if (flags == DLADM_OPT_PERSIST) 241 return (i_dladm_part_info_persist(handle, linkid, attrp)); 242 else 243 return (DLADM_STATUS_BADARG); 244 } 245 246 /* 247 * Get the configuration information for the IB Phys link given by the datalink 248 * ID 'linkid'. 249 */ 250 /* ARGSUSED */ 251 dladm_status_t 252 dladm_ib_info(dladm_handle_t handle, datalink_id_t linkid, 253 dladm_ib_attr_t *attrp, uint32_t flags) 254 { 255 uint_t instance; 256 ibport_ioctl_t ioc; 257 dladm_phys_attr_t dpa; 258 dladm_status_t status = DLADM_STATUS_OK; 259 260 /* 261 * We need to get the device name of the IB Phys link to get the 262 * correct instance number of the IP over IB driver instance. 263 */ 264 if (dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE) 265 != DLADM_STATUS_OK) 266 return (DLADM_STATUS_BADARG); 267 268 /* 269 * Get the instance number of the IP over IB driver instance which 270 * represents this IB Phys link. 271 */ 272 if (dladm_parselink(dpa.dp_dev, NULL, &instance) != DLADM_STATUS_OK) 273 return (DLADM_STATUS_FAILED); 274 275 bzero(&ioc, sizeof (ioc)); 276 /* 277 * The ioc_linkid here will contain IB port linkid here. We make the 278 * first ioctl call to get the P_Key table size for this HCA port. 279 */ 280 ioc.ibdioc.ioc_linkid = linkid; 281 ioc.ibdioc.ioc_info_cmd = IBD_INFO_CMD_PKEYTBLSZ; 282 ioc.ioc_pkey_tbl_sz = 0; 283 ioc.ibdioc.ioc_port_inst = instance; 284 285 status = i_dladm_ib_ioctl(handle, IBD_INFO_IBPART, (ibd_ioctl_t *)&ioc); 286 if (status != DLADM_STATUS_OK) 287 return (status); 288 289 /* 290 * Now allocate the memory for the P_Key table based on the table size 291 * return by the ioctl. 292 */ 293 ioc.ioc_pkeys = calloc(sizeof (ib_pkey_t), ioc.ioc_pkey_tbl_sz); 294 if (ioc.ioc_pkeys == NULL) { 295 status = dladm_errno2status(errno); 296 goto bail; 297 } 298 299 /* 300 * Call the ioctl again to get the P_Key table and other IB Phys link 301 * attributes. 302 */ 303 ioc.ibdioc.ioc_linkid = linkid; 304 ioc.ibdioc.ioc_port_inst = instance; 305 ioc.ibdioc.ioc_info_cmd = IBD_INFO_CMD_IBPORT; 306 307 status = i_dladm_ib_ioctl(handle, IBD_INFO_IBPART, (ibd_ioctl_t *)&ioc); 308 if (status != DLADM_STATUS_OK) 309 goto bail; 310 311 attrp->dia_physlinkid = ioc.ibdioc.ioc_linkid; 312 attrp->dia_portnum = ioc.ibdioc.ioc_portnum; 313 attrp->dia_port_pkey_tbl_sz = ioc.ioc_pkey_tbl_sz; 314 attrp->dia_port_pkeys = ioc.ioc_pkeys; 315 attrp->dia_hca_guid = ioc.ibdioc.ioc_hcaguid; 316 attrp->dia_port_guid = ioc.ibdioc.ioc_portguid; 317 attrp->dia_instance = ioc.ibdioc.ioc_port_inst; 318 return (status); 319 bail: 320 free(ioc.ioc_pkeys); 321 return (status); 322 } 323 324 /* 325 * Free the memory allocated for the IB HCA port's P_Key table by 326 * dladm_ib_info library call. 327 */ 328 void 329 dladm_free_ib_info(dladm_ib_attr_t *attr) 330 { 331 if (attr && attr->dia_port_pkeys) 332 free(attr->dia_port_pkeys); 333 } 334 335 /* 336 * Call into the IP over IB driver to create a partition object. 337 */ 338 static dladm_status_t 339 i_dladm_part_create(dladm_handle_t handle, dladm_part_attr_t *pattr) 340 { 341 ibpart_ioctl_t ioc; 342 343 bzero(&ioc, sizeof (ioc)); 344 345 /* IB Physical datalink ID */ 346 ioc.ibdioc.ioc_linkid = pattr->dia_physlinkid; 347 /* IB Partition datalink ID */ 348 ioc.ioc_partid = pattr->dia_partlinkid; 349 ioc.ioc_pkey = pattr->dia_pkey; 350 ioc.ibdioc.ioc_port_inst = pattr->dia_instance; 351 ioc.ioc_force_create = ((pattr->dia_flags & DLADM_OPT_FORCE) 352 != 0); 353 354 return (i_dladm_ib_ioctl(handle, IBD_CREATE_IBPART, &ioc.ibdioc)); 355 } 356 357 /* 358 * Create an entry in the dladm persistent configuration database for the 359 * partition specified by pattr. 360 */ 361 dladm_status_t 362 dladm_part_persist_conf(dladm_handle_t handle, const char *pname, 363 dladm_part_attr_t *pattr) 364 { 365 366 dladm_conf_t conf; 367 dladm_status_t status; 368 char linkover[MAXLINKNAMELEN]; 369 uint64_t u64; 370 371 status = dladm_create_conf(handle, pname, pattr->dia_partlinkid, 372 DATALINK_CLASS_PART, DL_IB, &conf); 373 if (status != DLADM_STATUS_OK) 374 return (status); 375 376 /* 377 * Get the name of the IB Phys link over which this partition was 378 * created. 379 */ 380 status = dladm_datalink_id2info(handle, pattr->dia_physlinkid, 381 NULL, NULL, NULL, linkover, sizeof (linkover)); 382 if (status != DLADM_STATUS_OK) 383 return (status); 384 385 /* Store IB Phys link name (linkover) */ 386 status = dladm_set_conf_field(handle, conf, FLINKOVER, DLADM_TYPE_STR, 387 linkover); 388 if (status != DLADM_STATUS_OK) 389 return (status); 390 391 u64 = pattr->dia_pkey; 392 393 /* Store the IB Partitions P_Key */ 394 status = dladm_set_conf_field(handle, conf, FPORTPKEY, 395 DLADM_TYPE_UINT64, &u64); 396 if (status != DLADM_STATUS_OK) 397 return (status); 398 399 if (pattr->dia_flags & DLADM_OPT_FORCE) { 400 boolean_t force = B_TRUE; 401 /* Store the force create flag. */ 402 status = dladm_set_conf_field(handle, conf, FFORCE, 403 DLADM_TYPE_BOOLEAN, &force); 404 if (status != DLADM_STATUS_OK) 405 goto done; 406 } 407 408 status = dladm_write_conf(handle, conf); 409 if (status != DLADM_STATUS_OK) 410 return (status); 411 412 dladm_destroy_conf(handle, conf); 413 done: 414 return (status); 415 } 416 417 /* 418 * Create a new IB Partition datalink of name 'pname' over the IB Physical link 419 * given in 'physlinkid' with the P_key 'pkey' and return the datalink ID in 420 * 'partlinkid'. If the 'force' option is set in the 'flags' argument, the 421 * partition will be created even if the P_Key 'pkey' does not exist or if the 422 * HCA port represented by the IB Phys link is down. If the 'temporary' flag is 423 * set, then the configuration information is not added to the persistent 424 * database. 425 */ 426 dladm_status_t 427 dladm_part_create(dladm_handle_t handle, datalink_id_t physlinkid, 428 ib_pkey_t pkey, uint32_t flags, char *pname, datalink_id_t *partlinkid, 429 dladm_arg_list_t *proplist) 430 { 431 int i; 432 dladm_status_t status; 433 uint_t media; 434 boolean_t part_created = B_FALSE; 435 boolean_t conf_set = B_FALSE; 436 dladm_phys_attr_t dpa; 437 dladm_part_attr_t pattr; 438 439 pattr.dia_pkey = pkey; 440 pattr.dia_physlinkid = physlinkid; /* IB Phys link's datalink id */ 441 pattr.dia_flags = flags; 442 443 flags &= ~DLADM_OPT_FORCE; 444 445 /* 446 * Check whether the PKEY is valid. If not, return immediately 447 * Only full members are allowed as per the IPoIB specification 448 */ 449 if (pattr.dia_pkey <= IB_PKEY_INVALID_FULL) 450 return (DLADM_STATUS_INVALID_PKEY); 451 452 /* 453 * Get the media type of the Phys link datalink ID provided and 454 * make sure that it is Infiniband media DL_IB) 455 */ 456 if ((status = dladm_datalink_id2info(handle, pattr.dia_physlinkid, NULL, 457 NULL, &media, NULL, 0)) != DLADM_STATUS_OK) 458 return (status); 459 460 if (media != DL_IB) 461 return (dladm_errno2status(ENOTSUP)); 462 463 /* 464 * Get the instance number of the IP over IB driver instance which the 465 * IB Phys link 'physlinkid' over which we will be creating our IB 466 * partition. 467 */ 468 if ((status = dladm_phys_info(handle, pattr.dia_physlinkid, &dpa, 469 DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) 470 return (status); 471 472 if (dladm_parselink(dpa.dp_dev, NULL, (uint_t *)&pattr.dia_instance) != 473 DLADM_STATUS_OK) 474 return (DLADM_STATUS_FAILED); 475 476 477 if ((status = dladm_create_datalink_id(handle, pname, 478 DATALINK_CLASS_PART, DL_IB, flags, &pattr.dia_partlinkid)) != 479 DLADM_STATUS_OK) 480 return (status); 481 482 /* 483 * Create the IB partition object. 484 */ 485 status = i_dladm_part_create(handle, &pattr); 486 if (status != DLADM_STATUS_OK) 487 goto done; 488 489 part_created = B_TRUE; 490 491 /* 492 * If the persist flag is set then write this partition information 493 * to the persistent configuration. 494 */ 495 if (pattr.dia_flags & DLADM_OPT_PERSIST) { 496 status = dladm_part_persist_conf(handle, pname, &pattr); 497 if (status != DLADM_STATUS_OK) 498 goto done; 499 conf_set = B_TRUE; 500 } 501 502 /* 503 * If the name-value pair list of properties were provided set those 504 * properties over the datalink. 505 */ 506 if (proplist != NULL) { 507 for (i = 0; i < proplist->al_count; i++) { 508 dladm_arg_info_t *aip = &proplist->al_info[i]; 509 510 status = dladm_set_linkprop(handle, 511 pattr.dia_partlinkid, aip->ai_name, aip->ai_val, 512 aip->ai_count, pattr.dia_flags); 513 if (status != DLADM_STATUS_OK) 514 break; 515 } 516 } 517 done: 518 if (status != DLADM_STATUS_OK) { 519 if (conf_set) 520 (void) dladm_remove_conf(handle, pattr.dia_partlinkid); 521 if (part_created) 522 (void) i_dladm_part_delete(handle, 523 pattr.dia_partlinkid); 524 (void) dladm_destroy_datalink_id(handle, pattr.dia_partlinkid, 525 flags); 526 } 527 528 if (partlinkid != NULL) 529 *partlinkid = pattr.dia_partlinkid; 530 531 return (status); 532 } 533 534 /* 535 * Call into the IP over IB driver to delete the IB partition and free up all 536 * the resources allocated for it. 537 */ 538 static dladm_status_t 539 i_dladm_part_delete(dladm_handle_t handle, datalink_id_t partid) 540 { 541 ibpart_ioctl_t ioc; 542 543 bzero(&ioc, sizeof (ioc)); 544 ioc.ioc_partid = partid; 545 return (i_dladm_ib_ioctl(handle, IBD_DELETE_IBPART, &ioc.ibdioc)); 546 } 547 548 /* 549 * Delete an IB partition if 'flags' contains the active flag. Update the 550 * persistent configuration if 'flags' contains the persist flag. 551 */ 552 dladm_status_t 553 dladm_part_delete(dladm_handle_t handle, datalink_id_t partid, int flags) 554 { 555 dladm_status_t status = DLADM_STATUS_OK; 556 datalink_class_t class; 557 558 if (flags == 0) 559 return (DLADM_STATUS_BADARG); 560 561 /* 562 * Make sure that the datalinkid provided is an IB partition class 563 * datalink ID. 564 */ 565 if ((dladm_datalink_id2info(handle, partid, NULL, &class, NULL, NULL, 0) 566 != DLADM_STATUS_OK)) 567 return (DLADM_STATUS_BADARG); 568 569 if (class != DATALINK_CLASS_PART) 570 return (DLADM_STATUS_BADARG); 571 572 if ((flags & DLADM_OPT_ACTIVE) != 0) { 573 status = i_dladm_part_delete(handle, partid); 574 if (status == DLADM_STATUS_OK) { 575 (void) dladm_set_linkprop(handle, partid, NULL, NULL, 0, 576 DLADM_OPT_ACTIVE); 577 (void) dladm_destroy_datalink_id(handle, partid, 578 DLADM_OPT_ACTIVE); 579 } else if (status != DLADM_STATUS_NOTFOUND || 580 !(flags & DLADM_OPT_PERSIST)) { 581 return (status); 582 } 583 } 584 585 if ((flags & DLADM_OPT_PERSIST) != 0) { 586 dladm_status_t db_status; 587 db_status = dladm_remove_conf(handle, partid); 588 589 /* 590 * A partition could have been temporarily deleted in which 591 * case the delete of the active partition above would have 592 * failed. In that case, we update the status to be returned 593 * to that of the status returned for deleting the persistent 594 * database entry. 595 */ 596 if (status == DLADM_STATUS_NOTFOUND) 597 status = db_status; 598 599 (void) dladm_destroy_datalink_id(handle, partid, 600 DLADM_OPT_PERSIST); 601 } 602 603 return (status); 604 } 605 606 /* 607 * Call into the IP over IB driver to create the active instances of one or all 608 * IB partitions present in the persistent configuration. 609 */ 610 /* ARGSUSED */ 611 static int 612 i_dladm_part_up(dladm_handle_t handle, datalink_id_t plinkid, void *arg) 613 { 614 dladm_conf_t conf; 615 datalink_id_t linkid; 616 ib_pkey_t pkey; 617 uint64_t u64; 618 char linkover[MAXLINKNAMELEN]; 619 dladm_status_t status; 620 dladm_phys_attr_t dpa; 621 dladm_part_attr_t pattr; 622 623 /* 624 * plinkid is the IB partition datalink's ID. Get an handle to the 625 * persistent configuration entry for this datalink ID. If this datalink 626 * ID is not present in the persistent configuration return. 627 */ 628 if ((status = dladm_getsnap_conf(handle, plinkid, &conf)) != 629 DLADM_STATUS_OK) 630 return (status); 631 632 /* 633 * Get the name of the IB Phys link over which this partition was 634 * created. 635 */ 636 status = dladm_get_conf_field(handle, conf, FLINKOVER, linkover, 637 sizeof (linkover)); 638 if (status != DLADM_STATUS_OK) 639 goto done; 640 641 if ((status = dladm_name2info(handle, linkover, &linkid, NULL, NULL, 642 NULL)) != DLADM_STATUS_OK) 643 goto done; 644 645 /* 646 * Get the phys attribute of the IB Phys link to get the device name 647 * associated with the phys link. We need this to get the IP over IB 648 * driver instance number. 649 */ 650 if (dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE) 651 != DLADM_STATUS_OK) 652 goto done; 653 654 /* Get the IB partition's P_key */ 655 status = dladm_get_conf_field(handle, conf, FPORTPKEY, &u64, 656 sizeof (u64)); 657 if (status != DLADM_STATUS_OK) 658 goto done; 659 660 pkey = (ib_pkey_t)u64; 661 662 /* 663 * We always set the force flag during dladm_part_up because we want 664 * the partition creation to succeed even if the IB HCA port over which 665 * the partition is being created is still down. Since dladm_part_up 666 * is usually invoked during early boot sequence, it is possible under 667 * some IB subnet configurations for dladm_up_part to be called before 668 * the IB link negotiation is completed and port state is set to active 669 * and P_Key table is updated. 670 */ 671 pattr.dia_flags = DLADM_OPT_FORCE | DLADM_OPT_ACTIVE | 672 DLADM_OPT_PERSIST; 673 /* IB Phys link's datalink ID. */ 674 pattr.dia_physlinkid = linkid; 675 /* IB Partition's datalink ID. */ 676 pattr.dia_partlinkid = plinkid; 677 pattr.dia_pkey = pkey; 678 if (dladm_parselink(dpa.dp_dev, NULL, (uint_t *)&pattr.dia_instance) != 679 DLADM_STATUS_OK) 680 return (DLADM_WALK_CONTINUE); 681 682 /* Create the active IB Partition object. */ 683 if (i_dladm_part_create(handle, &pattr) == DLADM_STATUS_OK && 684 dladm_up_datalink_id(handle, plinkid) != DLADM_STATUS_OK) 685 (void) i_dladm_part_delete(handle, linkid); 686 687 done: 688 dladm_destroy_conf(handle, conf); 689 return (DLADM_WALK_CONTINUE); 690 } 691 692 /* 693 * Bring up one or all IB partition(s) present in the persistent configuration 694 * database. If we need to bring up one IB Partition, its datalink ID is 695 * provided in 'linkid'. 696 */ 697 /* ARGSUSED */ 698 dladm_status_t 699 dladm_part_up(dladm_handle_t handle, datalink_id_t linkid, uint32_t flags) 700 { 701 dladm_status_t status = DLADM_STATUS_OK; 702 703 if (linkid == DATALINK_ALL_LINKID) { 704 (void) dladm_walk_datalink_id(i_dladm_part_up, handle, 705 &status, DATALINK_CLASS_PART, DATALINK_ANY_MEDIATYPE, 706 DLADM_OPT_PERSIST); 707 return (DLADM_STATUS_OK); 708 } else { 709 (void) i_dladm_part_up(handle, linkid, &status); 710 return (status); 711 } 712 } 713