/********************************************************************** * Clear all the counters from the db **********************************************************************/ void perfmgr_db_clear_counters(perfmgr_db_t * db) { cl_plock_excl_acquire(&db->lock); cl_qmap_apply_func(&db->pc_data, clear_counters, (void *)db); cl_plock_release(&db->lock); #if 0 if (db->db_impl->clear_counters) db->db_impl->clear_counters(db->db_data); #endif }
perfmgr_db_err_t perfmgr_db_update_name(perfmgr_db_t * db, uint64_t node_guid, char *name) { db_node_t *node = NULL; cl_plock_excl_acquire(&db->lock); node = get(db, node_guid); if (node) snprintf(node->node_name, sizeof(node->node_name), "%s", name); cl_plock_release(&db->lock); return (PERFMGR_EVENT_DB_SUCCESS); }
perfmgr_db_err_t perfmgr_db_mark_active(perfmgr_db_t *db, uint64_t guid, boolean_t active) { db_node_t *node = NULL; cl_plock_excl_acquire(&db->lock); node = get(db, guid); if (node) node->active = active; cl_plock_release(&db->lock); return (PERFMGR_EVENT_DB_SUCCESS); }
/* * SA DB Loader */ static osm_mgrp_t *load_mcgroup(osm_opensm_t * p_osm, ib_net16_t mlid, ib_member_rec_t * p_mcm_rec, unsigned well_known) { ib_net64_t comp_mask; osm_mgrp_t *p_mgrp; cl_plock_excl_acquire(&p_osm->lock); p_mgrp = osm_get_mgrp_by_mgid(&p_osm->subn, &p_mcm_rec->mgid); if (p_mgrp) { if (p_mgrp->mlid == mlid) { OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "mgrp %04x is already here.", cl_ntoh16(mlid)); goto _out; } OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "mlid %04x is already used by another MC group. Will " "request clients reregistration.\n", cl_ntoh16(mlid)); p_mgrp = NULL; goto _out; } comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_RATE | IB_MCR_COMPMASK_RATE_SEL; if (!(p_mgrp = osm_mcmr_rcv_find_or_create_new_mgrp(&p_osm->sa, comp_mask, p_mcm_rec)) || p_mgrp->mlid != mlid) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "cannot create MC group with mlid 0x%04x and mgid " "0x%016" PRIx64 ":0x%016" PRIx64 "\n", cl_ntoh16(mlid), cl_ntoh64(p_mcm_rec->mgid.unicast.prefix), cl_ntoh64(p_mcm_rec->mgid.unicast.interface_id)); p_mgrp = NULL; } else if (well_known) p_mgrp->well_known = TRUE; _out: cl_plock_release(&p_osm->lock); return p_mgrp; }
perfmgr_db_err_t perfmgr_db_clear_prev_dc(perfmgr_db_t * db, uint64_t guid, uint8_t port) { db_node_t *node = NULL; perfmgr_db_data_cnt_reading_t *previous = NULL; perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS; cl_plock_excl_acquire(&db->lock); node = get(db, guid); if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS) goto Exit; previous = &node->ports[port].dc_previous; memset(previous, 0, sizeof(*previous)); node->ports[port].dc_previous.time = time(NULL); Exit: cl_plock_release(&db->lock); return rc; }
perfmgr_db_err_t perfmgr_db_create_entry(perfmgr_db_t * db, uint64_t guid, boolean_t esp0, uint8_t num_ports, char *name) { perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS; cl_plock_excl_acquire(&db->lock); if (!get(db, guid)) { db_node_t *pc_node = malloc_node(guid, esp0, num_ports, name); if (!pc_node) { rc = PERFMGR_EVENT_DB_NOMEM; goto Exit; } if (insert(db, pc_node)) { free_node(pc_node); rc = PERFMGR_EVENT_DB_FAIL; goto Exit; } } Exit: cl_plock_release(&db->lock); return rc; }
static int load_infr(osm_opensm_t * p_osm, ib_inform_info_record_t * iir, osm_mad_addr_t * addr) { osm_infr_t infr, *p_infr; int ret = 0; infr.h_bind = p_osm->sa.mad_ctrl.h_bind; infr.sa = &p_osm->sa; /* other possible way to restore mad_addr partially is to extract qpn from InformInfo and to find lid by gid */ infr.report_addr = *addr; infr.inform_record = *iir; cl_plock_excl_acquire(&p_osm->lock); if (osm_infr_get_by_rec(&p_osm->subn, &p_osm->log, &infr)) { OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "InformInfo Record already exists\n"); goto _out; } if (!(p_infr = osm_infr_new(&infr))) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "cannot allocate new infr struct\n"); ret = -1; goto _out; } OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "adding InformInfo Record...\n"); osm_infr_insert_to_db(&p_osm->subn, &p_osm->log, p_infr); _out: cl_plock_release(&p_osm->lock); return ret; }
static int load_svcr(osm_opensm_t * p_osm, ib_service_record_t * sr, uint32_t modified_time, uint32_t lease_period) { osm_svcr_t *p_svcr; int ret = 0; cl_plock_excl_acquire(&p_osm->lock); if (osm_svcr_get_by_rid(&p_osm->subn, &p_osm->log, sr)) { OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "ServiceRecord already exists\n"); goto _out; } if (!(p_svcr = osm_svcr_new(sr))) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "cannot allocate new service struct\n"); ret = -1; goto _out; } p_svcr->modified_time = modified_time; p_svcr->lease_period = lease_period; OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "adding ServiceRecord...\n"); osm_svcr_insert_to_db(&p_osm->subn, &p_osm->log, p_svcr); if (lease_period != 0xffffffff) cl_timer_trim(&p_osm->sa.sr_timer, 1000); _out: cl_plock_release(&p_osm->lock); return ret; }
/********************************************************************* Received a Set(InformInfo) MAD **********************************************************************/ static void osm_infr_rcv_process_set_method(IN osm_sa_t * sa, IN osm_madw_t * const p_madw) { ib_sa_mad_t *p_sa_mad; ib_inform_info_t *p_recvd_inform_info; osm_infr_t inform_info_rec; /* actual inform record to be stored for reports */ osm_infr_t *p_infr; ib_net32_t qpn; uint8_t resp_time_val; ib_api_status_t res; OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_recvd_inform_info = (ib_inform_info_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); #if 0 if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG)) osm_dump_inform_info(sa->p_log, p_recvd_inform_info, OSM_LOG_DEBUG); #endif /* Grab the lock */ cl_plock_excl_acquire(sa->p_lock); /* define the inform record */ inform_info_rec.inform_record.inform_info = *p_recvd_inform_info; /* following C13-32.1.2 Tbl 120: we only copy the source address vector */ inform_info_rec.report_addr = p_madw->mad_addr; /* we will need to know the mad srvc to send back through */ inform_info_rec.h_bind = p_madw->h_bind; inform_info_rec.sa = sa; /* update the subscriber GID according to mad address */ res = osm_get_gid_by_mad_addr(sa->p_log, sa->p_subn, &p_madw->mad_addr, &inform_info_rec.inform_record. subscriber_gid); if (res != IB_SUCCESS) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4308 " "Subscribe Request from unknown LID: %u\n", cl_ntoh16(p_madw->mad_addr.dest_lid)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* HACK: enum is always 0 (currently) */ inform_info_rec.inform_record.subscriber_enum = 0; /* Subscribe values above 1 are undefined */ if (p_recvd_inform_info->subscribe > 1) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4308 " "Invalid subscribe: %d\n", p_recvd_inform_info->subscribe); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* * MODIFICATIONS DONE ON INCOMING REQUEST: * * QPN: * Internally we keep the QPN field of the InformInfo updated * so we can simply compare it in the record - when finding such. */ if (p_recvd_inform_info->subscribe) { ib_inform_info_set_qpn(&inform_info_rec.inform_record. inform_info, inform_info_rec.report_addr.addr_type. gsi.remote_qp); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Subscribe Request with QPN: 0x%06X\n", cl_ntoh32(inform_info_rec.report_addr.addr_type.gsi. remote_qp)); } else { ib_inform_info_get_qpn_resp_time(p_recvd_inform_info->g_or_v. generic.qpn_resp_time_val, &qpn, &resp_time_val); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "UnSubscribe Request with QPN: 0x%06X\n", cl_ntoh32(qpn)); } /* If record exists with matching InformInfo */ p_infr = osm_infr_get_by_rec(sa->p_subn, sa->p_log, &inform_info_rec); /* check to see if the request was for subscribe */ if (p_recvd_inform_info->subscribe) { /* validate the request for a new or update InformInfo */ if (__validate_infr(sa, &inform_info_rec) != TRUE) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4305: " "Failed to validate a new inform object\n"); /* o13-13.1.1: we need to set the subscribe bit to 0 */ p_recvd_inform_info->subscribe = 0; osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* ok - we can try and create a new entry */ if (p_infr == NULL) { /* Create the instance of the osm_infr_t object */ p_infr = osm_infr_new(&inform_info_rec); if (p_infr == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4306: " "Failed to create a new inform object\n"); /* o13-13.1.1: we need to set the subscribe bit to 0 */ p_recvd_inform_info->subscribe = 0; osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES); goto Exit; } /* Add this new osm_infr_t object to subnet object */ osm_infr_insert_to_db(sa->p_subn, sa->p_log, p_infr); } else /* Update the old instance of the osm_infr_t object */ p_infr->inform_record = inform_info_rec.inform_record; /* We got an UnSubscribe request */ } else if (p_infr == NULL) { cl_plock_release(sa->p_lock); /* No Such Item - So Error */ OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4307: " "Failed to UnSubscribe to non existing inform object\n"); /* o13-13.1.1: we need to set the subscribe bit to 0 */ p_recvd_inform_info->subscribe = 0; osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } else /* Delete this object from the subnet list of informs */ osm_infr_remove_from_db(sa->p_subn, sa->p_log, p_infr); cl_plock_release(sa->p_lock); /* send the success response */ __osm_infr_rcv_respond(sa, p_madw); Exit: OSM_LOG_EXIT(sa->p_log); }
osm_signal_t osm_qos_setup(osm_opensm_t * p_osm) { struct qos_config ca_config, sw0_config, swe_config, rtr_config; struct qos_config *cfg; cl_qmap_t *p_tbl; cl_map_item_t *p_next; osm_port_t *p_port; uint32_t num_physp; osm_physp_t *p_physp; osm_node_t *p_node; ib_api_status_t status; unsigned force_update; uint8_t i; if (!p_osm->subn.opt.qos) return OSM_SIGNAL_DONE; OSM_LOG_ENTER(&p_osm->log); qos_build_config(&ca_config, &p_osm->subn.opt.qos_ca_options, &p_osm->subn.opt.qos_options); qos_build_config(&sw0_config, &p_osm->subn.opt.qos_sw0_options, &p_osm->subn.opt.qos_options); qos_build_config(&swe_config, &p_osm->subn.opt.qos_swe_options, &p_osm->subn.opt.qos_options); qos_build_config(&rtr_config, &p_osm->subn.opt.qos_rtr_options, &p_osm->subn.opt.qos_options); cl_plock_excl_acquire(&p_osm->lock); /* read QoS policy config file */ osm_qos_parse_policy_file(&p_osm->subn); p_tbl = &p_osm->subn.port_guid_tbl; p_next = cl_qmap_head(p_tbl); while (p_next != cl_qmap_end(p_tbl)) { p_port = (osm_port_t *) p_next; p_next = cl_qmap_next(p_next); p_node = p_port->p_node; if (p_node->sw) { num_physp = osm_node_get_num_physp(p_node); for (i = 1; i < num_physp; i++) { p_physp = osm_node_get_physp_ptr(p_node, i); if (!p_physp) continue; force_update = p_physp->need_update || p_osm->subn.need_update; status = qos_physp_setup(&p_osm->log, &p_osm->sm, p_port, p_physp, i, force_update, &swe_config); } /* skip base port 0 */ if (!ib_switch_info_is_enhanced_port0 (&p_node->sw->switch_info)) continue; cfg = &sw0_config; } else if (osm_node_get_type(p_node) == IB_NODE_TYPE_ROUTER) cfg = &rtr_config; else cfg = &ca_config; p_physp = p_port->p_physp; if (!p_physp) continue; force_update = p_physp->need_update || p_osm->subn.need_update; status = qos_physp_setup(&p_osm->log, &p_osm->sm, p_port, p_physp, 0, force_update, cfg); } cl_plock_release(&p_osm->lock); OSM_LOG_EXIT(&p_osm->log); return OSM_SIGNAL_DONE; }
/********************************************************************** * perfmgr_db_data_cnt_reading_t functions **********************************************************************/ perfmgr_db_err_t perfmgr_db_add_dc_reading(perfmgr_db_t * db, uint64_t guid, uint8_t port, perfmgr_db_data_cnt_reading_t * reading, int ietf_sup) { db_port_t *p_port = NULL; db_node_t *node = NULL; perfmgr_db_data_cnt_reading_t *previous = NULL; perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS; osm_epi_dc_event_t epi_dc_data; cl_plock_excl_acquire(&db->lock); node = get(db, guid); if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS) goto Exit; mark_port_valid(node, port); p_port = &node->ports[port]; previous = &node->ports[port].dc_previous; debug_dump_dc_reading(db, guid, port, p_port, reading); epi_dc_data.time_diff_s = reading->time - previous->time; osm_epi_create_port_id(&epi_dc_data.port_id, guid, port, node->node_name); /* calculate changes from previous reading */ epi_dc_data.xmit_data = reading->xmit_data - previous->xmit_data; p_port->dc_total.xmit_data += epi_dc_data.xmit_data; epi_dc_data.rcv_data = reading->rcv_data - previous->rcv_data; p_port->dc_total.rcv_data += epi_dc_data.rcv_data; epi_dc_data.xmit_pkts = reading->xmit_pkts - previous->xmit_pkts; p_port->dc_total.xmit_pkts += epi_dc_data.xmit_pkts; epi_dc_data.rcv_pkts = reading->rcv_pkts - previous->rcv_pkts; p_port->dc_total.rcv_pkts += epi_dc_data.rcv_pkts; if (ietf_sup) { epi_dc_data.unicast_xmit_pkts = reading->unicast_xmit_pkts - previous->unicast_xmit_pkts; p_port->dc_total.unicast_xmit_pkts += epi_dc_data.unicast_xmit_pkts; epi_dc_data.unicast_rcv_pkts = reading->unicast_rcv_pkts - previous->unicast_rcv_pkts; p_port->dc_total.unicast_rcv_pkts += epi_dc_data.unicast_rcv_pkts; epi_dc_data.multicast_xmit_pkts = reading->multicast_xmit_pkts - previous->multicast_xmit_pkts; p_port->dc_total.multicast_xmit_pkts += epi_dc_data.multicast_xmit_pkts; epi_dc_data.multicast_rcv_pkts = reading->multicast_rcv_pkts - previous->multicast_rcv_pkts; p_port->dc_total.multicast_rcv_pkts += epi_dc_data.multicast_rcv_pkts; } p_port->dc_previous = *reading; /* mark the time this total was updated */ p_port->dc_total.time = reading->time; osm_opensm_report_event(db->perfmgr->osm, OSM_EVENT_ID_PORT_DATA_COUNTERS, &epi_dc_data); Exit: cl_plock_release(&db->lock); return rc; }
/********************************************************************** * perfmgr_db_err_reading_t functions **********************************************************************/ perfmgr_db_err_t perfmgr_db_add_err_reading(perfmgr_db_t * db, uint64_t guid, uint8_t port, perfmgr_db_err_reading_t * reading) { db_port_t *p_port = NULL; db_node_t *node = NULL; perfmgr_db_err_reading_t *previous = NULL; perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS; osm_epi_pe_event_t epi_pe_data; cl_plock_excl_acquire(&db->lock); node = get(db, guid); if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS) goto Exit; mark_port_valid(node, port); p_port = &(node->ports[port]); previous = &(node->ports[port].err_previous); debug_dump_err_reading(db, guid, port, p_port, reading); epi_pe_data.time_diff_s = (reading->time - previous->time); osm_epi_create_port_id(&epi_pe_data.port_id, guid, port, node->node_name); /* calculate changes from previous reading */ epi_pe_data.symbol_err_cnt = (reading->symbol_err_cnt - previous->symbol_err_cnt); p_port->err_total.symbol_err_cnt += epi_pe_data.symbol_err_cnt; epi_pe_data.link_err_recover = (reading->link_err_recover - previous->link_err_recover); p_port->err_total.link_err_recover += epi_pe_data.link_err_recover; epi_pe_data.link_downed = (reading->link_downed - previous->link_downed); p_port->err_total.link_downed += epi_pe_data.link_downed; epi_pe_data.rcv_err = (reading->rcv_err - previous->rcv_err); p_port->err_total.rcv_err += epi_pe_data.rcv_err; epi_pe_data.rcv_rem_phys_err = (reading->rcv_rem_phys_err - previous->rcv_rem_phys_err); p_port->err_total.rcv_rem_phys_err += epi_pe_data.rcv_rem_phys_err; epi_pe_data.rcv_switch_relay_err = (reading->rcv_switch_relay_err - previous->rcv_switch_relay_err); p_port->err_total.rcv_switch_relay_err += epi_pe_data.rcv_switch_relay_err; epi_pe_data.xmit_discards = (reading->xmit_discards - previous->xmit_discards); p_port->err_total.xmit_discards += epi_pe_data.xmit_discards; epi_pe_data.xmit_constraint_err = (reading->xmit_constraint_err - previous->xmit_constraint_err); p_port->err_total.xmit_constraint_err += epi_pe_data.xmit_constraint_err; epi_pe_data.rcv_constraint_err = (reading->rcv_constraint_err - previous->rcv_constraint_err); p_port->err_total.rcv_constraint_err += epi_pe_data.rcv_constraint_err; epi_pe_data.link_integrity = (reading->link_integrity - previous->link_integrity); p_port->err_total.link_integrity += epi_pe_data.link_integrity; epi_pe_data.buffer_overrun = (reading->buffer_overrun - previous->buffer_overrun); p_port->err_total.buffer_overrun += epi_pe_data.buffer_overrun; epi_pe_data.vl15_dropped = (reading->vl15_dropped - previous->vl15_dropped); p_port->err_total.vl15_dropped += epi_pe_data.vl15_dropped; epi_pe_data.xmit_wait = (reading->xmit_wait - previous->xmit_wait); p_port->err_total.xmit_wait += epi_pe_data.xmit_wait; p_port->err_previous = *reading; /* mark the time this total was updated */ p_port->err_total.time = reading->time; osm_opensm_report_event(db->perfmgr->osm, OSM_EVENT_ID_PORT_ERRORS, &epi_pe_data); Exit: cl_plock_release(&db->lock); return rc; }
int osm_qos_setup(osm_opensm_t * p_osm) { struct qos_config ca_config, sw0_config, swe_config, rtr_config; struct qos_config *cfg; cl_qmap_t *p_tbl; cl_map_item_t *p_next; osm_port_t *p_port; osm_node_t *p_node; int ret = 0; int vlarb_only; qos_mad_list_t *p_list, *p_list_next; qos_mad_item_t *p_port_mad; cl_qlist_t qos_mad_list; if (!p_osm->subn.opt.qos) return 0; OSM_LOG_ENTER(&p_osm->log); qos_build_config(&ca_config, &p_osm->subn.opt.qos_ca_options, &p_osm->subn.opt.qos_options); qos_build_config(&sw0_config, &p_osm->subn.opt.qos_sw0_options, &p_osm->subn.opt.qos_options); qos_build_config(&swe_config, &p_osm->subn.opt.qos_swe_options, &p_osm->subn.opt.qos_options); qos_build_config(&rtr_config, &p_osm->subn.opt.qos_rtr_options, &p_osm->subn.opt.qos_options); cl_qlist_init(&qos_mad_list); cl_plock_excl_acquire(&p_osm->lock); /* read QoS policy config file */ osm_qos_parse_policy_file(&p_osm->subn); p_tbl = &p_osm->subn.port_guid_tbl; p_next = cl_qmap_head(p_tbl); while (p_next != cl_qmap_end(p_tbl)) { vlarb_only = 0; p_port = (osm_port_t *) p_next; p_next = cl_qmap_next(p_next); p_list = (qos_mad_list_t *) malloc(sizeof(*p_list)); if (!p_list) return -1; memset(p_list, 0, sizeof(*p_list)); cl_qlist_init(&p_list->port_mad_list); p_node = p_port->p_node; if (p_node->sw) { if (qos_extports_setup(&p_osm->sm, p_node, &swe_config, &p_list->port_mad_list)) ret = -1; /* skip base port 0 */ if (!ib_switch_info_is_enhanced_port0 (&p_node->sw->switch_info)) goto Continue; if (ib_switch_info_get_opt_sl2vlmapping(&p_node->sw->switch_info) && p_osm->sm.p_subn->opt.use_optimized_slvl && !memcmp(&swe_config.sl2vl, &sw0_config.sl2vl, sizeof(swe_config.sl2vl))) vlarb_only = 1; cfg = &sw0_config; } else if (osm_node_get_type(p_node) == IB_NODE_TYPE_ROUTER) cfg = &rtr_config; else cfg = &ca_config; if (qos_endport_setup(&p_osm->sm, p_port->p_physp, cfg, vlarb_only, &p_list->port_mad_list)) ret = -1; Continue: /* if MAD list is not empty, add it to the global MAD list */ if (cl_qlist_count(&p_list->port_mad_list)) { cl_qlist_insert_tail(&qos_mad_list, &p_list->list_item); } else { free(p_list); } } while (cl_qlist_count(&qos_mad_list)) { p_list_next = (qos_mad_list_t *) cl_qlist_head(&qos_mad_list); while (p_list_next != (qos_mad_list_t *) cl_qlist_end(&qos_mad_list)) { p_list = p_list_next; p_list_next = (qos_mad_list_t *) cl_qlist_next(&p_list->list_item); /* next MAD to send*/ p_port_mad = (qos_mad_item_t *) cl_qlist_remove_head(&p_list->port_mad_list); osm_send_req_mad(&p_osm->sm, p_port_mad->p_madw); osm_qos_mad_delete(&p_port_mad); /* remove the QoS MAD from global MAD list */ if (cl_qlist_count(&p_list->port_mad_list) == 0) { cl_qlist_remove_item(&qos_mad_list, &p_list->list_item); free(p_list); } } } cl_plock_release(&p_osm->lock); OSM_LOG_EXIT(&p_osm->log); return ret; }