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