1 /* 2 * Copyright (c) 2006-2009 Voltaire, Inc. All rights reserved. 3 * Copyright (c) 2010-2015 Mellanox Technologies LTD. All rights reserved. 4 * Copyright (c) 2009 HNR Consulting. All rights reserved. 5 * 6 * This software is available to you under a choice of one of two 7 * licenses. You may choose to be licensed under the terms of the GNU 8 * General Public License (GPL) Version 2, available from the file 9 * COPYING in the main directory of this source tree, or the 10 * OpenIB.org BSD license below: 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above 17 * copyright notice, this list of conditions and the following 18 * disclaimer. 19 * 20 * - Redistributions in binary form must reproduce the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer in the documentation and/or other materials 23 * provided with the distribution. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 * SOFTWARE. 33 * 34 */ 35 36 /* 37 * Abstract: 38 * Implementation of OpenSM QoS infrastructure primitives 39 */ 40 41 #if HAVE_CONFIG_H 42 # include <config.h> 43 #endif /* HAVE_CONFIG_H */ 44 45 #include <stdlib.h> 46 #include <string.h> 47 48 #include <iba/ib_types.h> 49 #include <complib/cl_qmap.h> 50 #include <complib/cl_debug.h> 51 #include <opensm/osm_file_ids.h> 52 #define FILE_ID OSM_FILE_QOS_C 53 #include <opensm/osm_opensm.h> 54 #include <opensm/osm_subnet.h> 55 #include <opensm/osm_qos_policy.h> 56 57 struct qos_config { 58 uint8_t max_vls; 59 uint8_t vl_high_limit; 60 ib_vl_arb_table_t vlarb_high[2]; 61 ib_vl_arb_table_t vlarb_low[2]; 62 ib_slvl_table_t sl2vl; 63 }; 64 65 typedef struct qos_mad_item { 66 cl_list_item_t list_item; 67 osm_madw_t *p_madw; 68 } qos_mad_item_t; 69 70 typedef struct qos_mad_list { 71 cl_list_item_t list_item; 72 cl_qlist_t port_mad_list; 73 } qos_mad_list_t; 74 75 static void qos_build_config(struct qos_config *cfg, 76 osm_qos_options_t * opt, 77 osm_qos_options_t * dflt); 78 79 /* 80 * QoS primitives 81 */ 82 83 static qos_mad_item_t *osm_qos_mad_create(IN osm_sm_t * sm, 84 IN osm_physp_t * p, 85 IN uint32_t data_size, 86 IN uint8_t * p_data, 87 IN ib_net16_t attr_id, 88 IN uint32_t attr_mod) 89 90 { 91 qos_mad_item_t *p_mad; 92 osm_madw_context_t context; 93 osm_madw_t *p_madw; 94 osm_node_t *p_node; 95 osm_physp_t *physp0; 96 ib_net64_t m_key; 97 98 p_node = osm_physp_get_node_ptr(p); 99 if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && 100 osm_physp_get_port_num(p) != 0) { 101 physp0 = osm_node_get_physp_ptr(p_node, 0); 102 m_key = ib_port_info_get_m_key(&physp0->port_info); 103 } else 104 m_key = ib_port_info_get_m_key(&p->port_info); 105 106 switch (attr_id){ 107 case IB_MAD_ATTR_SLVL_TABLE: 108 context.slvl_context.node_guid = osm_node_get_node_guid(p_node); 109 context.slvl_context.port_guid = osm_physp_get_port_guid(p); 110 context.slvl_context.set_method = TRUE; 111 break; 112 case IB_MAD_ATTR_VL_ARBITRATION: 113 context.vla_context.node_guid = osm_node_get_node_guid(p_node); 114 context.vla_context.port_guid = osm_physp_get_port_guid(p); 115 context.vla_context.set_method = TRUE; 116 break; 117 default: 118 return NULL; 119 } 120 121 p_mad = (qos_mad_item_t *) malloc(sizeof(*p_mad)); 122 if (!p_mad) 123 return NULL; 124 125 memset(p_mad, 0, sizeof(*p_mad)); 126 127 p_madw = osm_prepare_req_set(sm, osm_physp_get_dr_path_ptr(p), 128 p_data, data_size, 129 attr_id, cl_hton32(attr_mod), 130 FALSE, m_key, 131 CL_DISP_MSGID_NONE, &context); 132 133 if (p_madw == NULL) { 134 free(p_mad); 135 return NULL; 136 } 137 p_mad->p_madw = p_madw; 138 return p_mad; 139 } 140 141 static void osm_qos_mad_delete(qos_mad_item_t ** p_item) 142 { 143 free(*p_item); 144 *p_item = NULL; 145 } 146 147 static ib_api_status_t vlarb_update_table_block(osm_sm_t * sm, 148 osm_physp_t * p, 149 uint8_t port_num, 150 unsigned force_update, 151 const ib_vl_arb_table_t * 152 table_block, 153 unsigned block_length, 154 unsigned block_num, 155 cl_qlist_t *mad_list) 156 { 157 struct osm_routing_engine *re = sm->p_subn->p_osm->routing_engine_used; 158 ib_vl_arb_table_t block; 159 uint32_t attr_mod; 160 unsigned vl_mask, i; 161 qos_mad_item_t *p_mad; 162 vl_mask = (1 << (ib_port_info_get_op_vls(&p->port_info) - 1)) - 1; 163 164 memset(&block, 0, sizeof(block)); 165 memcpy(&block, table_block, block_length * sizeof(block.vl_entry[0])); 166 167 if (re && re->update_vlarb) 168 re->update_vlarb(re->context, p, port_num, &block, 169 block_length, block_num); 170 171 for (i = 0; i < block_length; i++) 172 block.vl_entry[i].vl &= vl_mask; 173 174 if (!force_update && 175 !memcmp(&p->vl_arb[block_num], &block, 176 block_length * sizeof(block.vl_entry[0]))) 177 return IB_SUCCESS; 178 179 attr_mod = ((block_num + 1) << 16) | port_num; 180 181 p_mad = osm_qos_mad_create(sm,p,sizeof(block),(uint8_t *) & block, 182 IB_MAD_ATTR_VL_ARBITRATION, attr_mod); 183 184 if (!p_mad) 185 return IB_INSUFFICIENT_MEMORY; 186 187 /* 188 * Zero the stored VL Arbitration block, so in case the MAD will 189 * end up with error, we will resend it in the next sweep. 190 */ 191 memset(&p->vl_arb[block_num], 0, 192 block_length * sizeof(block.vl_entry[0])); 193 194 cl_qlist_insert_tail(mad_list, &p_mad->list_item); 195 196 return IB_SUCCESS; 197 } 198 199 static ib_api_status_t vlarb_update(osm_sm_t * sm, osm_physp_t * p, 200 uint8_t port_num, unsigned force_update, 201 const struct qos_config *qcfg, 202 cl_qlist_t *mad_list) 203 { 204 ib_api_status_t status = IB_SUCCESS; 205 ib_port_info_t *p_pi = &p->port_info; 206 unsigned len; 207 208 if (p_pi->vl_arb_low_cap > 0) { 209 len = p_pi->vl_arb_low_cap < IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK ? 210 p_pi->vl_arb_low_cap : IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; 211 if ((status = vlarb_update_table_block(sm, p, port_num, 212 force_update, 213 &qcfg->vlarb_low[0], 214 len, 0, 215 mad_list)) != IB_SUCCESS) 216 return status; 217 } 218 if (p_pi->vl_arb_low_cap > IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK) { 219 len = p_pi->vl_arb_low_cap % IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; 220 if ((status = vlarb_update_table_block(sm, p, port_num, 221 force_update, 222 &qcfg->vlarb_low[1], 223 len, 1, 224 mad_list)) != IB_SUCCESS) 225 return status; 226 } 227 if (p_pi->vl_arb_high_cap > 0) { 228 len = p_pi->vl_arb_high_cap < IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK ? 229 p_pi->vl_arb_high_cap : IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; 230 if ((status = vlarb_update_table_block(sm, p, port_num, 231 force_update, 232 &qcfg->vlarb_high[0], 233 len, 2, 234 mad_list)) != IB_SUCCESS) 235 return status; 236 } 237 if (p_pi->vl_arb_high_cap > IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK) { 238 len = p_pi->vl_arb_high_cap % IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; 239 if ((status = vlarb_update_table_block(sm, p, port_num, 240 force_update, 241 &qcfg->vlarb_high[1], 242 len, 3, 243 mad_list)) != IB_SUCCESS) 244 return status; 245 } 246 247 return status; 248 } 249 250 static ib_api_status_t sl2vl_update_table(osm_sm_t * sm, osm_physp_t * p, 251 uint8_t in_port, uint32_t attr_mod, 252 unsigned force_update, 253 const ib_slvl_table_t * sl2vl_table, 254 cl_qlist_t *mad_list) 255 { 256 ib_slvl_table_t tbl, *p_tbl; 257 unsigned vl_mask; 258 uint8_t vl1, vl2; 259 int i; 260 qos_mad_item_t *p_mad; 261 262 vl_mask = (1 << (ib_port_info_get_op_vls(&p->port_info) - 1)) - 1; 263 264 for (i = 0; i < IB_MAX_NUM_VLS / 2; i++) { 265 vl1 = sl2vl_table->raw_vl_by_sl[i] >> 4; 266 vl2 = sl2vl_table->raw_vl_by_sl[i] & 0xf; 267 if (vl1 != 15) 268 vl1 &= vl_mask; 269 if (vl2 != 15) 270 vl2 &= vl_mask; 271 tbl.raw_vl_by_sl[i] = (vl1 << 4) | vl2; 272 } 273 274 p_tbl = osm_physp_get_slvl_tbl(p, in_port); 275 276 if (!force_update && !memcmp(p_tbl, &tbl, sizeof(tbl))) 277 return IB_SUCCESS; 278 279 p_mad = osm_qos_mad_create(sm, p, sizeof(tbl), (uint8_t *) & tbl, 280 IB_MAD_ATTR_SLVL_TABLE, attr_mod); 281 if (!p_mad) 282 return IB_INSUFFICIENT_MEMORY; 283 284 /* 285 * Zero the stored SL2VL block, so in case the MAD will 286 * end up with error, we will resend it in the next sweep. 287 */ 288 memset(p_tbl, 0, sizeof(tbl)); 289 290 cl_qlist_insert_tail(mad_list, &p_mad->list_item); 291 return IB_SUCCESS; 292 } 293 294 static int qos_extports_setup(osm_sm_t * sm, osm_node_t *node, 295 const struct qos_config *qcfg, 296 cl_qlist_t *port_mad_list) 297 298 { 299 osm_physp_t *p0, *p; 300 unsigned force_update; 301 unsigned num_ports = osm_node_get_num_physp(node); 302 struct osm_routing_engine *re = sm->p_subn->p_osm->routing_engine_used; 303 int ret = 0; 304 unsigned in, out; 305 uint8_t op_vl, common_op_vl = 0, max_num = 0; 306 uint8_t op_vl_arr[15]; 307 308 /* 309 * Do nothing unless the most recent routing attempt was successful. 310 */ 311 if (!re) 312 return ret; 313 314 for (out = 1; out < num_ports; out++) { 315 p = osm_node_get_physp_ptr(node, out); 316 if (!p) 317 continue; 318 if (ib_port_info_get_port_state(&p->port_info) == IB_LINK_DOWN) 319 continue; 320 force_update = p->need_update || sm->p_subn->need_update; 321 p->vl_high_limit = qcfg->vl_high_limit; 322 if (vlarb_update(sm, p, p->port_num, force_update, qcfg, 323 port_mad_list)) 324 ret = -1; 325 } 326 327 p0 = osm_node_get_physp_ptr(node, 0); 328 if (!(p0->port_info.capability_mask & IB_PORT_CAP_HAS_SL_MAP)) 329 return ret; 330 331 if (ib_switch_info_get_opt_sl2vlmapping(&node->sw->switch_info) && 332 sm->p_subn->opt.use_optimized_slvl && !re->update_sl2vl) { 333 334 /* we should find the op_vl that is used by majority of ports */ 335 memset(&op_vl_arr[0], 0, sizeof(op_vl_arr)); 336 p0 = osm_node_get_physp_ptr(node, 1); 337 338 for (out = 1; out < num_ports; out++) { 339 p = osm_node_get_physp_ptr(node, out); 340 if (!p) 341 continue; 342 if (ib_port_info_get_port_state(&p->port_info) == 343 IB_LINK_DOWN) 344 continue; 345 op_vl = ib_port_info_get_op_vls(&p->port_info); 346 op_vl_arr[op_vl]++; 347 if (op_vl_arr[op_vl] > max_num){ 348 max_num = op_vl_arr[op_vl]; 349 common_op_vl = op_vl; 350 /* remember the port with most common op_vl */ 351 p0 = p; 352 } 353 354 } 355 if (!p0) 356 return -1; 357 force_update = node->sw->need_update || sm->p_subn->need_update; 358 if (sl2vl_update_table(sm, p0, p0->port_num, 0x30000, force_update, 359 &qcfg->sl2vl, port_mad_list)) 360 ret = -1; 361 /* 362 * Overwrite default ALL configuration if port's 363 * op_vl is different. 364 */ 365 for (out = 1; out < num_ports; out++) { 366 p = osm_node_get_physp_ptr(node, out); 367 if (!p) 368 continue; 369 if (ib_port_info_get_port_state(&p->port_info) == 370 IB_LINK_DOWN) 371 continue; 372 373 force_update = p->need_update || force_update; 374 if (ib_port_info_get_op_vls(&p->port_info) != 375 common_op_vl && 376 sl2vl_update_table(sm, p, p->port_num, 0x20000 | out, 377 force_update, &qcfg->sl2vl, 378 port_mad_list)) 379 ret = -1; 380 } 381 return ret; 382 } 383 384 /* non optimized sl2vl configuration */ 385 out = ib_switch_info_is_enhanced_port0(&node->sw->switch_info) ? 0 : 1; 386 for (; out < num_ports; out++) { 387 p = osm_node_get_physp_ptr(node, out); 388 if (!p) 389 continue; 390 if (ib_port_info_get_port_state(&p->port_info) == IB_LINK_DOWN) 391 continue; 392 force_update = p->need_update || sm->p_subn->need_update; 393 /* go over all in ports */ 394 for (in = 0; in < num_ports; in++) { 395 const ib_slvl_table_t *port_sl2vl = &qcfg->sl2vl; 396 ib_slvl_table_t routing_sl2vl; 397 398 if (re->update_sl2vl) { 399 routing_sl2vl = *port_sl2vl; 400 re->update_sl2vl(re->context, 401 p, in, out, &routing_sl2vl); 402 port_sl2vl = &routing_sl2vl; 403 } 404 if (sl2vl_update_table(sm, p, in, in << 8 | out, 405 force_update, port_sl2vl, 406 port_mad_list)) 407 ret = -1; 408 } 409 } 410 411 return ret; 412 } 413 414 static int qos_endport_setup(osm_sm_t * sm, osm_physp_t * p, 415 const struct qos_config *qcfg, int vlarb_only, 416 cl_qlist_t *port_mad_list) 417 { 418 unsigned force_update = p->need_update || sm->p_subn->need_update; 419 struct osm_routing_engine *re = sm->p_subn->p_osm->routing_engine_used; 420 const ib_slvl_table_t *port_sl2vl = &qcfg->sl2vl; 421 ib_slvl_table_t routing_sl2vl; 422 423 p->vl_high_limit = qcfg->vl_high_limit; 424 if (vlarb_update(sm, p, 0, force_update, qcfg, port_mad_list)) 425 return -1; 426 if (vlarb_only) 427 return 0; 428 429 if (!(p->port_info.capability_mask & IB_PORT_CAP_HAS_SL_MAP)) 430 return 0; 431 432 if (re && re->update_sl2vl) { 433 routing_sl2vl = *port_sl2vl; 434 re->update_sl2vl(re->context, p, 0, 0, &routing_sl2vl); 435 port_sl2vl = &routing_sl2vl; 436 } 437 if (sl2vl_update_table(sm, p, 0, 0, force_update, port_sl2vl, 438 port_mad_list)) 439 return -1; 440 441 return 0; 442 } 443 444 int osm_qos_setup(osm_opensm_t * p_osm) 445 { 446 struct qos_config ca_config, sw0_config, swe_config, rtr_config; 447 struct qos_config *cfg; 448 cl_qmap_t *p_tbl; 449 cl_map_item_t *p_next; 450 osm_port_t *p_port; 451 osm_node_t *p_node; 452 int ret = 0; 453 int vlarb_only; 454 qos_mad_list_t *p_list, *p_list_next; 455 qos_mad_item_t *p_port_mad; 456 cl_qlist_t qos_mad_list; 457 458 if (!p_osm->subn.opt.qos) 459 return 0; 460 461 OSM_LOG_ENTER(&p_osm->log); 462 463 qos_build_config(&ca_config, &p_osm->subn.opt.qos_ca_options, 464 &p_osm->subn.opt.qos_options); 465 qos_build_config(&sw0_config, &p_osm->subn.opt.qos_sw0_options, 466 &p_osm->subn.opt.qos_options); 467 qos_build_config(&swe_config, &p_osm->subn.opt.qos_swe_options, 468 &p_osm->subn.opt.qos_options); 469 qos_build_config(&rtr_config, &p_osm->subn.opt.qos_rtr_options, 470 &p_osm->subn.opt.qos_options); 471 472 cl_qlist_init(&qos_mad_list); 473 474 cl_plock_excl_acquire(&p_osm->lock); 475 476 /* read QoS policy config file */ 477 osm_qos_parse_policy_file(&p_osm->subn); 478 p_tbl = &p_osm->subn.port_guid_tbl; 479 p_next = cl_qmap_head(p_tbl); 480 while (p_next != cl_qmap_end(p_tbl)) { 481 vlarb_only = 0; 482 p_port = (osm_port_t *) p_next; 483 p_next = cl_qmap_next(p_next); 484 485 p_list = (qos_mad_list_t *) malloc(sizeof(*p_list)); 486 if (!p_list) { 487 cl_plock_release(&p_osm->lock); 488 return -1; 489 } 490 491 memset(p_list, 0, sizeof(*p_list)); 492 493 cl_qlist_init(&p_list->port_mad_list); 494 495 p_node = p_port->p_node; 496 if (p_node->sw) { 497 if (qos_extports_setup(&p_osm->sm, p_node, &swe_config, 498 &p_list->port_mad_list)) { 499 cl_plock_release(&p_osm->lock); 500 ret = -1; 501 } 502 503 /* skip base port 0 */ 504 if (!ib_switch_info_is_enhanced_port0 505 (&p_node->sw->switch_info)) 506 goto Continue; 507 508 if (ib_switch_info_get_opt_sl2vlmapping(&p_node->sw->switch_info) && 509 p_osm->sm.p_subn->opt.use_optimized_slvl && 510 !memcmp(&swe_config.sl2vl, &sw0_config.sl2vl, 511 sizeof(swe_config.sl2vl))) 512 vlarb_only = 1; 513 514 cfg = &sw0_config; 515 } else if (osm_node_get_type(p_node) == IB_NODE_TYPE_ROUTER) 516 cfg = &rtr_config; 517 else 518 cfg = &ca_config; 519 520 if (qos_endport_setup(&p_osm->sm, p_port->p_physp, cfg, 521 vlarb_only, &p_list->port_mad_list)) { 522 cl_plock_release(&p_osm->lock); 523 ret = -1; 524 } 525 Continue: 526 /* if MAD list is not empty, add it to the global MAD list */ 527 if (cl_qlist_count(&p_list->port_mad_list)) { 528 cl_qlist_insert_tail(&qos_mad_list, &p_list->list_item); 529 } else { 530 free(p_list); 531 } 532 } 533 while (cl_qlist_count(&qos_mad_list)) { 534 p_list_next = (qos_mad_list_t *) cl_qlist_head(&qos_mad_list); 535 while (p_list_next != 536 (qos_mad_list_t *) cl_qlist_end(&qos_mad_list)) { 537 p_list = p_list_next; 538 p_list_next = (qos_mad_list_t *) 539 cl_qlist_next(&p_list->list_item); 540 /* next MAD to send*/ 541 p_port_mad = (qos_mad_item_t *) 542 cl_qlist_remove_head(&p_list->port_mad_list); 543 osm_send_req_mad(&p_osm->sm, p_port_mad->p_madw); 544 osm_qos_mad_delete(&p_port_mad); 545 /* remove the QoS MAD from global MAD list */ 546 if (cl_qlist_count(&p_list->port_mad_list) == 0) { 547 cl_qlist_remove_item(&qos_mad_list, &p_list->list_item); 548 free(p_list); 549 } 550 } 551 } 552 553 cl_plock_release(&p_osm->lock); 554 OSM_LOG_EXIT(&p_osm->log); 555 556 return ret; 557 } 558 559 /* 560 * QoS config stuff 561 */ 562 static int parse_one_unsigned(const char *str, char delim, unsigned *val) 563 { 564 char *end; 565 *val = strtoul(str, &end, 0); 566 if (*end) 567 end++; 568 return (int)(end - str); 569 } 570 571 static int parse_vlarb_entry(const char *str, ib_vl_arb_element_t * e) 572 { 573 unsigned val; 574 const char *p = str; 575 p += parse_one_unsigned(p, ':', &val); 576 e->vl = val % 15; 577 p += parse_one_unsigned(p, ',', &val); 578 e->weight = (uint8_t) val; 579 return (int)(p - str); 580 } 581 582 static int parse_sl2vl_entry(const char *str, uint8_t * raw) 583 { 584 unsigned val1, val2; 585 const char *p = str; 586 p += parse_one_unsigned(p, ',', &val1); 587 p += parse_one_unsigned(p, ',', &val2); 588 *raw = (val1 << 4) | (val2 & 0xf); 589 return (int)(p - str); 590 } 591 592 static void qos_build_config(struct qos_config *cfg, osm_qos_options_t * opt, 593 osm_qos_options_t * dflt) 594 { 595 int i; 596 const char *p; 597 598 memset(cfg, 0, sizeof(*cfg)); 599 600 if (opt->max_vls > 0) 601 cfg->max_vls = opt->max_vls; 602 else { 603 if (dflt->max_vls > 0) 604 cfg->max_vls = dflt->max_vls; 605 else 606 cfg->max_vls = OSM_DEFAULT_QOS_MAX_VLS; 607 } 608 609 if (opt->high_limit >= 0) 610 cfg->vl_high_limit = (uint8_t) opt->high_limit; 611 else { 612 if (dflt->high_limit >= 0) 613 cfg->vl_high_limit = (uint8_t) dflt->high_limit; 614 else 615 cfg->vl_high_limit = (uint8_t) OSM_DEFAULT_QOS_HIGH_LIMIT; 616 } 617 618 if (opt->vlarb_high) 619 p = opt->vlarb_high; 620 else { 621 if (dflt->vlarb_high) 622 p = dflt->vlarb_high; 623 else 624 p = OSM_DEFAULT_QOS_VLARB_HIGH; 625 } 626 for (i = 0; i < 2 * IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; i++) { 627 p += parse_vlarb_entry(p, 628 &cfg->vlarb_high[i / 629 IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK]. 630 vl_entry[i % 631 IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK]); 632 } 633 634 if (opt->vlarb_low) 635 p = opt->vlarb_low; 636 else { 637 if (dflt->vlarb_low) 638 p = dflt->vlarb_low; 639 else 640 p = OSM_DEFAULT_QOS_VLARB_LOW; 641 } 642 for (i = 0; i < 2 * IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; i++) { 643 p += parse_vlarb_entry(p, 644 &cfg->vlarb_low[i / 645 IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK]. 646 vl_entry[i % 647 IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK]); 648 } 649 650 p = opt->sl2vl ? opt->sl2vl : dflt->sl2vl; 651 if (opt->sl2vl) 652 p = opt->sl2vl; 653 else { 654 if (dflt->sl2vl) 655 p = dflt->sl2vl; 656 else 657 p = OSM_DEFAULT_QOS_SL2VL; 658 } 659 for (i = 0; i < IB_MAX_NUM_VLS / 2; i++) 660 p += parse_sl2vl_entry(p, &cfg->sl2vl.raw_vl_by_sl[i]); 661 } 662