]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ofed/opensm/opensm/osm_qos.c
MFV r353623: 10473 zfs(1M) missing cross-reference to zfs-program(1M)
[FreeBSD/FreeBSD.git] / contrib / ofed / opensm / opensm / osm_qos.c
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 }