diff --git a/debian/libibmad5.symbols b/debian/libibmad5.symbols index 1863b24cc..cc7f399dd 100644 --- a/debian/libibmad5.symbols +++ b/debian/libibmad5.symbols @@ -156,3 +156,6 @@ libibmad.so.5 libibmad5 #MINVER# smp_set_via@IBMAD_1.3 1.3.11 str2drpath@IBMAD_1.3 1.3.11 xdump@IBMAD_1.3 1.3.11 + mad_rpc_open_port2@IBMAD_1.5 5.5.56 + mad_rpc_close_port2@IBMAD_1.5 5.5.56 + diff --git a/debian/libibumad3.symbols b/debian/libibumad3.symbols index 9b6e74682..42a8956a4 100644 --- a/debian/libibumad3.symbols +++ b/debian/libibumad3.symbols @@ -44,3 +44,6 @@ libibumad.so.3 libibumad3 #MINVER# umad_sort_ca_device_list@IBUMAD_1.2 3.2.30 umad_status@IBUMAD_1.0 1.3.9 umad_unregister@IBUMAD_1.0 1.3.9 + umad_get_smi_gsi_pairs@IBUMAD_1.4 3.4.56 + umad_get_smi_gsi_pair_by_ca_name@IBUMAD_1.4 3.4.56 + diff --git a/infiniband-diags/smpquery.c b/infiniband-diags/smpquery.c index 07d328c95..5726b0cc7 100644 --- a/infiniband-diags/smpquery.c +++ b/infiniband-diags/smpquery.c @@ -48,6 +48,7 @@ #include "ibdiag_common.h" static struct ibmad_port *srcport; +static struct ibmad_ports_pair *srcports; static op_fn_t node_desc, node_info, port_info, switch_info, pkey_table, sl2vl_table, vlarb_table, guid_info, mlnx_ext_port_info, port_info_extended; @@ -475,17 +476,19 @@ int main(int argc, char **argv) if (!(fn = match_op(match_tbl, argv[0]))) IBEXIT("operation '%s' not supported", argv[0]); - srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3); - if (!srcport) + srcports = mad_rpc_open_port2(ibd_ca, ibd_ca_port, mgmt_classes, 3, 1); + if (!srcports) IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port); + srcport = srcports->smi.port; + smp_mkey_set(srcport, ibd_mkey); node_name_map = open_node_name_map(node_name_map_file); if (ibd_dest_type != IB_DEST_DRSLID) { - if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[1], - ibd_dest_type, ibd_sm_id, srcport) < 0) + if (resolve_portid_str(srcports->gsi.ca_name, ibd_ca_port, &portid, argv[1], + ibd_dest_type, ibd_sm_id, srcports->gsi.port) < 0) IBEXIT("can't resolve destination port %s", argv[1]); if ((err = fn(&portid, argv + 2, argc - 2))) IBEXIT("operation %s: %s", argv[0], err); @@ -494,13 +497,13 @@ int main(int argc, char **argv) memset(concat, 0, 64); snprintf(concat, sizeof(concat), "%s %s", argv[1], argv[2]); - if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, concat, + if (resolve_portid_str(srcports->smi.ca_name, ibd_ca_port, &portid, concat, ibd_dest_type, ibd_sm_id, srcport) < 0) IBEXIT("can't resolve destination port %s", concat); if ((err = fn(&portid, argv + 3, argc - 3))) IBEXIT("operation %s: %s", argv[0], err); } close_node_name_map(node_name_map); - mad_rpc_close_port(srcport); + mad_rpc_close_port2(srcports); exit(0); } diff --git a/libibmad/CMakeLists.txt b/libibmad/CMakeLists.txt index 5a0977101..27782f4cc 100644 --- a/libibmad/CMakeLists.txt +++ b/libibmad/CMakeLists.txt @@ -9,7 +9,7 @@ publish_internal_headers(util rdma_library(ibmad libibmad.map # See Documentation/versioning.md - 5 5.4.${PACKAGE_VERSION} + 5 5.5.${PACKAGE_VERSION} bm.c cc.c dump.c diff --git a/libibmad/libibmad.map b/libibmad/libibmad.map index dc9eb2051..7d150c003 100644 --- a/libibmad/libibmad.map +++ b/libibmad/libibmad.map @@ -161,3 +161,10 @@ IBMAD_1.4 { mad_dump_linkspeedexten2; mad_dump_linkspeedextsup2; } IBMAD_1.3; + +IBMAD_1.5 { + global: + mad_rpc_open_port2; + mad_rpc_close_port2; +} IBMAD_1.4; + diff --git a/libibmad/mad.h b/libibmad/mad.h index 0d26db757..99d3a5a06 100644 --- a/libibmad/mad.h +++ b/libibmad/mad.h @@ -1408,6 +1408,16 @@ typedef struct ib_bm_call { uint64_t bkey; } ib_bm_call_t; +typedef struct ibmad_ports_item { + struct ibmad_port *port; + char ca_name[20]; +} ibmad_ports_item_t; + +struct ibmad_ports_pair { + ibmad_ports_item_t smi; + ibmad_ports_item_t gsi; +}; + #define IB_MIN_UCAST_LID 1 #define IB_MAX_UCAST_LID (0xc000-1) #define IB_MIN_MCAST_LID 0xc000 @@ -1483,7 +1493,10 @@ int madrpc_set_retries(int retries); int madrpc_set_timeout(int timeout); struct ibmad_port *mad_rpc_open_port(char *dev_name, int dev_port, int *mgmt_classes, int num_classes); +struct ibmad_ports_pair *mad_rpc_open_port2(char *dev_name, int dev_port, + int *mgmt_classes, int num_classes, unsigned enforce_smi); void mad_rpc_close_port(struct ibmad_port *srcport); +void mad_rpc_close_port2(struct ibmad_ports_pair *srcport); /* * On redirection, the dport argument is updated with the redirection target, diff --git a/libibmad/rpc.c b/libibmad/rpc.c index 2a7801767..4e4462890 100644 --- a/libibmad/rpc.c +++ b/libibmad/rpc.c @@ -436,3 +436,152 @@ void mad_rpc_close_port(struct ibmad_port *port) umad_close_port(port->port_id); free(port); } + +static int get_smi_gsi_pair(const char *ca_name, int portnum, struct ibmad_ports_pair *ports_pair, + unsigned enforce_smi) +{ + struct umad_ca_pair ca_pair; + int smi_port_id = -1; + int gsi_port_id = -1; + int rc = -1; + rc = umad_get_smi_gsi_pair_by_ca_name(ca_name, portnum, &ca_pair, enforce_smi); + + if (rc < 0) { + IBWARN("Can't open UMAD port (%s) (%s:%d)", strerror(-rc), ca_name, portnum); + return rc; + } + smi_port_id = umad_open_port(ca_pair.smi_name, ca_pair.smi_preferred_port); + + if (smi_port_id < 0 && enforce_smi) { + IBWARN("Can't open SMI UMAD port (%s) (%s:%d)", strerror(-smi_port_id), ca_pair.smi_name, ca_pair.smi_preferred_port); + return smi_port_id; + } + + gsi_port_id = umad_open_port(ca_pair.gsi_name, ca_pair.gsi_preferred_port); + + if (gsi_port_id < 0) { + IBWARN("Can't open GSI UMAD port (%s) (%s:%d)", strerror(-gsi_port_id), ca_pair.gsi_name, ca_pair.gsi_preferred_port); + umad_close_port(smi_port_id); + return gsi_port_id; + } + + ports_pair->smi.port->port_id = smi_port_id; + ports_pair->gsi.port->port_id = gsi_port_id; + strncpy(ports_pair->smi.ca_name, ca_pair.smi_name, UMAD_CA_NAME_LEN); + strncpy(ports_pair->gsi.ca_name, ca_pair.gsi_name, UMAD_CA_NAME_LEN); + + return 0; +} + +static struct ibmad_port *get_port_for_class(struct ibmad_ports_pair *ports_pair, int mgmt_class, unsigned enforce_smi) +{ + if (mgmt_class != IB_SMI_CLASS && mgmt_class != IB_SMI_DIRECT_CLASS) { + if (ports_pair->gsi.port->port_id < 0) { + IBWARN("required port for GSI is invalid"); + return NULL; + } + return ports_pair->gsi.port; + } + + if (ports_pair->smi.port->port_id < 0) { + if (enforce_smi) { + IBWARN("required port for SMI is invalid"); + return NULL; + } + return ports_pair->gsi.port; + } + + return ports_pair->smi.port; +} + +struct ibmad_ports_pair *mad_rpc_open_port2(char *dev_name, int dev_port, + int *mgmt_classes, int num_classes, unsigned enforce_smi) +{ + struct ibmad_port *smi; + struct ibmad_port *gsi; + struct ibmad_ports_pair *ports_pair; + char *debug_level_env; + + if (num_classes >= MAX_CLASS) { + IBWARN("too many classes %d requested", num_classes); + errno = EINVAL; + return NULL; + } + + if (umad_init() < 0) { + IBWARN("can't init UMAD library"); + errno = ENODEV; + return NULL; + } + + debug_level_env = getenv("LIBIBMAD_DEBUG_LEVEL"); + if (debug_level_env) { + ibdebug = atoi(debug_level_env); + } + + smi = malloc(sizeof(*smi)); + if (!smi) { + errno = ENOMEM; + return NULL; + } + memset(smi, 0, sizeof(*smi)); + + gsi = malloc(sizeof(*gsi)); + if (!gsi) { + errno = ENOMEM; + return NULL; + } + memset(gsi, 0, sizeof(*gsi)); + + ports_pair = malloc(sizeof(*ports_pair)); + if (!ports_pair) { + errno = ENOMEM; + return NULL; + } + memset(ports_pair, 0, sizeof(*ports_pair)); + ports_pair->smi.port = smi; + ports_pair->gsi.port = gsi; + + if ((get_smi_gsi_pair(dev_name, dev_port, ports_pair, enforce_smi)) < 0) { + IBWARN("can't open UMAD port (%s:%d)", dev_name, dev_port); + if (!errno) + errno = EIO; + free(smi); + free(gsi); + free(ports_pair); + return NULL; + } + + memset(ports_pair->smi.port->class_agents, 0xff, sizeof ports_pair->smi.port->class_agents); + memset(ports_pair->gsi.port->class_agents, 0xff, sizeof ports_pair->gsi.port->class_agents); + while (num_classes--) { + uint8_t rmpp_version = 0; + int mgmt = *mgmt_classes++; + struct ibmad_port *p = get_port_for_class(ports_pair, mgmt, enforce_smi); + if (mgmt == IB_SA_CLASS) + rmpp_version = 1; + if (mgmt < 0 || mgmt >= MAX_CLASS || !p || + mad_register_client_via(mgmt, rmpp_version, p) < 0) { + IBWARN("client_register for mgmt %d failed", mgmt); + if (!errno) + errno = EINVAL; + umad_close_port(ports_pair->smi.port->port_id); + umad_close_port(ports_pair->gsi.port->port_id); + free(ports_pair->smi.port); + free(ports_pair->gsi.port); + free(ports_pair); + return NULL; + } + } + + return ports_pair; +} + +void mad_rpc_close_port2(struct ibmad_ports_pair *srcport) +{ + umad_close_port(srcport->smi.port->port_id); + umad_close_port(srcport->gsi.port->port_id); + free(srcport->smi.port); + free(srcport->gsi.port); + free(srcport); +} diff --git a/libibumad/CMakeLists.txt b/libibumad/CMakeLists.txt index 3ee12c83d..dcb030e16 100644 --- a/libibumad/CMakeLists.txt +++ b/libibumad/CMakeLists.txt @@ -10,7 +10,7 @@ publish_headers(infiniband rdma_library(ibumad libibumad.map # See Documentation/versioning.md - 3 3.3.${PACKAGE_VERSION} + 3 3.4.${PACKAGE_VERSION} sysfs.c umad.c umad_str.c diff --git a/libibumad/libibumad.map b/libibumad/libibumad.map index 694d1dd2a..0fb572f24 100644 --- a/libibumad/libibumad.map +++ b/libibumad/libibumad.map @@ -55,3 +55,10 @@ IBUMAD_1.3 { global: umad_open_smi_port; } IBUMAD_1.2; + +IBUMAD_1.4 { + global: + umad_get_smi_gsi_pairs; + umad_get_smi_gsi_pair_by_ca_name; +} IBUMAD_1.3; + diff --git a/libibumad/man/umad_get_smi_gsi_pair_by_ca_name.3 b/libibumad/man/umad_get_smi_gsi_pair_by_ca_name.3 new file mode 100644 index 000000000..6064b8e0a --- /dev/null +++ b/libibumad/man/umad_get_smi_gsi_pair_by_ca_name.3 @@ -0,0 +1,57 @@ +.. -*- rst -*- +.. Licensed under the OpenIB.org BSD license (FreeBSD Variant) - See COPYING.md + +umad_get_smi_gsi_pair_by_ca_name(3) +=================================== + +Retrieve SMI/GSI pair information based on device name and port number. + +Synopsis +-------- + +.. code-block:: c + + #include + + int umad_get_smi_gsi_pair_by_ca_name(const char *devname, uint8_t portnum, + struct umad_ca_pair *ca, unsigned enforce_smi); + +Description +----------- + +``umad_get_smi_gsi_pair_by_ca_name()`` fills the provided ``ca`` structure with the SMI and GSI pair information +for the specified device name and port number. + +The ``devname`` parameter specifies the name of the device, and ``portnum`` is the associated port number. + +``enforce_smi`` parameter if enabled, will look only for pairs that has both SMI and GSI interfaces. + +The ``struct umad_ca_pair`` is defined in ```` and includes the following members: + +.. code-block:: c + + struct umad_ca_pair { + char smi_name[UMAD_CA_NAME_LEN]; + /* Name of the SMI */ + uint32_t smi_preferred_port; + /* Preferred port for the SMI */ + char gsi_name[UMAD_CA_NAME_LEN]; + /* Name of the GSI */ + uint32_t gsi_preferred_port; + /* Preferred port for the GSI */ + }; + +The function populates this structure with the relevant data for the given ``devname`` and ``portnum``. + +Return Value +------------ + +``umad_get_smi_gsi_pair_by_ca_name()`` returns: + +- **0**: If the specified device and port are found and the structure is successfully populated. +- **1**: If no matching device or port is found. + +Authors +------- + +- Asaf Mazor diff --git a/libibumad/man/umad_get_smi_gsi_pairs.3 b/libibumad/man/umad_get_smi_gsi_pairs.3 new file mode 100644 index 000000000..ae746df19 --- /dev/null +++ b/libibumad/man/umad_get_smi_gsi_pairs.3 @@ -0,0 +1,50 @@ +.. -*- rst -*- +.. Licensed under the OpenIB.org BSD license (FreeBSD Variant) - See COPYING.md + +umad_get_smi_gsi_pairs(3) +========================= + +Get CAs as SMI/GSI pairs. + +Synopsis +-------- + +.. code-block:: c + + #include + + int umad_get_smi_gsi_pairs(struct umad_ca_pair cas[], size_t max); + +Description +----------- + +``umad_get_smi_gsi_pairs()`` fills a user-allocated array of ``struct umad_ca_pair``. +It fills up to ``max`` devices. + +The argument ``cas`` is an array of ``struct umad_ca_pair`` as specified in ````: + +.. code-block:: c + + struct umad_ca_pair { + char smi_name[UMAD_CA_NAME_LEN]; + /* Name of the SMI */ + uint32_t smi_preferred_port; + /* Preferred port for the SMI */ + char gsi_name[UMAD_CA_NAME_LEN]; + /* Name of the GSI */ + uint32_t gsi_preferred_port; + /* Preferred port for the GSI */ + }; + +The ``smi_preferred_port`` and ``gsi_preferred_port`` fields represent the first ports found active +for the corresponding SMI/GSI device. + +Return Value +------------ + +``umad_get_smi_gsi_pairs()`` returns the number of devices filled, or **-1** on error. + +Authors +------- + +- Asaf Mazor diff --git a/libibumad/umad.c b/libibumad/umad.c index 9de39c7ea..c951b9d00 100644 --- a/libibumad/umad.c +++ b/libibumad/umad.c @@ -34,6 +34,7 @@ #include +#include #include #include #include @@ -79,6 +80,16 @@ struct ib_user_mad_reg_req2 { uint8_t reserved[3]; }; +struct port_guid_port_count { + __be64 port_guid; + uint8_t count; +}; + +struct guid_ca_pairs_mapping { + __be64 port_guid; + struct umad_ca_pair *ca_pair; +}; + #define IBWARN(fmt, args...) fprintf(stderr, "ibwarn: [%d] %s: " fmt "\n", getpid(), __func__, ## args) #define TRACE if (umaddebug) IBWARN @@ -1354,3 +1365,292 @@ void umad_free_ca_device_list(struct umad_device_node *head) free(node); } } + +static struct umad_ca_pair *get_ca_pair_from_arr_by_guid(__be64 port_guid, + struct guid_ca_pairs_mapping mapping[], + size_t map_max, size_t *map_added, + struct umad_ca_pair devs[], + size_t devs_max, size_t *devs_added) +{ + struct umad_ca_pair *dev = NULL; + // attempt to find the port guid in the mapping + size_t i = 0; + + for (i = 0; i < *map_added; ++i) { + if (mapping[i].port_guid == port_guid) + return mapping[i].ca_pair; + } + + // attempt to add a new mapping/device + if (*map_added >= map_max || *devs_added >= devs_max) + return NULL; + + dev = &devs[*devs_added]; + mapping[*map_added].port_guid = port_guid; + mapping[*map_added].ca_pair = dev; + (*devs_added)++; + (*map_added)++; + + return dev; +} + +static uint8_t get_port_guid_count(__be64 guid, const struct port_guid_port_count counts[], + size_t max_guids) +{ + size_t i = 0; + + for (i = 0; i < max_guids; ++i) { + if (counts[i].port_guid == guid) + return counts[i].count; + } + + return 0; +} + + +static bool find_port_guid_count(struct port_guid_port_count counts[], size_t max, + __be64 port_guid, size_t *index) +{ + size_t i = 0; + + for (i = 0; i < max; ++i) { + if (counts[i].port_guid == 0) { + *index = i; + return false; + } + if (counts[i].port_guid == port_guid) { + *index = i; + return true; + } + } + + *index = max; + return false; +} + +static int count_ports_by_guid(char legacy_ca_names[][UMAD_CA_NAME_LEN], size_t num_cas, + struct port_guid_port_count counts[], size_t max) +{ + // how many unique port GUIDs were added + size_t num_of_guid = 0; + + memset(counts, 0, max * sizeof(struct port_guid_port_count)); + + size_t c_idx = 0; + + for (c_idx = 0; c_idx < num_cas; ++c_idx) { + umad_ca_t curr_ca; + + if (umad_get_ca(legacy_ca_names[c_idx], &curr_ca) < 0) + continue; + + size_t p_idx = 1; + + for (p_idx = 1; p_idx < (size_t)curr_ca.numports + 1; ++p_idx) { + umad_port_t *p_port = curr_ca.ports[p_idx]; + size_t count_idx = 0; + + if (!p_port) + continue; + + if (find_port_guid_count(counts, max, p_port->port_guid, &count_idx)) { + // port GUID already has a count struct + ++counts[count_idx].count; + } else { + // add a new count struct for this GUID. + // if the maximum amount was already added, do nothing. + if (count_idx != max) { + counts[count_idx].port_guid = p_port->port_guid; + counts[count_idx].count = 1; + ++num_of_guid; + } + } + } + + umad_release_ca(&curr_ca); + } + + return num_of_guid; +} + +int umad_get_smi_gsi_pairs(struct umad_ca_pair cas[], size_t max) +{ + size_t added_devices = 0, added_mappings = 0; + char legacy_ca_names[UMAD_MAX_DEVICES][UMAD_CA_NAME_LEN] = {}; + struct port_guid_port_count counts[UMAD_MAX_PORTS] = {}; + struct guid_ca_pairs_mapping mapping[UMAD_MAX_PORTS] = {}; + + memset(cas, 0, sizeof(struct umad_ca_pair) * max); + int cas_found = umad_get_cas_names(legacy_ca_names, UMAD_MAX_DEVICES); + + if (cas_found < 0) + return 0; + + count_ports_by_guid(legacy_ca_names, cas_found, counts, UMAD_MAX_PORTS); + + size_t c_idx = 0; + + for (c_idx = 0; c_idx < (size_t)cas_found; ++c_idx) { + umad_ca_t curr_ca; + + if (umad_get_ca(legacy_ca_names[c_idx], &curr_ca) < 0) + continue; + + size_t p_idx = 1; + + for (p_idx = 1; p_idx < (size_t)curr_ca.numports + 1; ++p_idx) { + umad_port_t *p_port = curr_ca.ports[p_idx]; + uint8_t guid_count = 0; + + if (!p_port) + continue; + + guid_count = get_port_guid_count(curr_ca.ports[p_idx]->port_guid, + counts, UMAD_MAX_PORTS); + struct umad_ca_pair *dev = get_ca_pair_from_arr_by_guid(p_port->port_guid, + mapping, UMAD_MAX_PORTS, + &added_mappings, cas, + max, &added_devices); + if (!dev) + continue; + if (guid_count > 1) { + // planarized port + char *dev_name = is_smi_disabled(p_port) ? dev->gsi_name : dev->smi_name; + strncpy(dev_name, curr_ca.ca_name, UMAD_CA_NAME_LEN); + break; + } else if (guid_count == 1) { + if (!is_smi_disabled(p_port)) + strncpy(dev->smi_name, curr_ca.ca_name, UMAD_CA_NAME_LEN); + strncpy(dev->gsi_name, curr_ca.ca_name, UMAD_CA_NAME_LEN); + break; + } else { + umad_release_ca(&curr_ca); + return -1; + } + } + + umad_release_ca(&curr_ca); + } + + return added_devices; +} + +static int umad_check_active(const umad_ca_t *ca, int prefered_portnum) +{ + if (!ca) + return 1; + + if (!ca->ports[prefered_portnum]) + return 1; + + int state = ca->ports[prefered_portnum]->state; + + return !(state > 1); +} + +static int umad_find_active(struct umad_ca_pair *ca_pair, const umad_ca_t *ca, bool is_gsi) +{ + size_t i = 1; + uint32_t *portnum_to_set = is_gsi ? + &ca_pair->gsi_preferred_port : + &ca_pair->smi_preferred_port; + + if (!ca_pair) + return 1; + + for (i = 1; i < (size_t)ca->numports + 1; ++i) { + if (!umad_check_active(ca, i)) { + *portnum_to_set = ca->ports[i]->portnum; + return 0; + } + } + + return 1; +} + +static int find_preferred_ports(struct umad_ca_pair *ca_pair, const umad_ca_t *ca, bool is_gsi, int portnum) +{ + if (portnum) { + uint32_t *port_to_set = is_gsi ? + &ca_pair->gsi_preferred_port : + &ca_pair->smi_preferred_port; + if (!umad_check_active(ca, portnum)) { + *port_to_set = portnum; + return umad_find_active(ca_pair, ca, !is_gsi); + } + return 1; + } + + return umad_find_active(ca_pair, ca, false) + + umad_find_active(ca_pair, ca, true); + +} + +int umad_get_smi_gsi_pair_by_ca_name(const char *name, uint8_t portnum, struct umad_ca_pair *ca_pair, + unsigned enforce_smi) +{ + int rc = 1; + size_t i = 0; + int num_cas = 0; + bool is_gsi = false; + + umad_ca_t ca; + struct umad_ca_pair cas_pair[UMAD_MAX_PORTS] = {}; + + if (!ca_pair) + return -1; + + memset(cas_pair, 0, sizeof(cas_pair)); + memset(ca_pair, 0, sizeof(*ca_pair)); + + num_cas = umad_get_smi_gsi_pairs(cas_pair, UMAD_MAX_PORTS); + + if (num_cas <= 0) + return num_cas; + + for (i = 0; i < (size_t)num_cas; ++i) { + if (enforce_smi && !cas_pair[i].smi_name[0]) + continue; + if (!cas_pair[i].gsi_name[0]) + continue; + + if (name) + // name doesn't match - keep searching + if (strncmp(cas_pair[i].gsi_name, name, UMAD_CA_NAME_LEN) + && strncmp(cas_pair[i].smi_name, name, UMAD_CA_NAME_LEN)) { + continue; + } + + // check that the device given by "name" has a port number "portnum" + // (if name doesn't exist, assume SMI port is given) + // (if enforce_smi is false assume GSI in case no SMI present) + is_gsi = (!enforce_smi && !cas_pair[i].smi_name[0]) || + (name && !strncmp(name, cas_pair[i].gsi_name, UMAD_CA_NAME_LEN)); + + if (umad_get_ca(is_gsi ? cas_pair[i].gsi_name : cas_pair[i].smi_name, &ca) < 0) + continue; + + if (portnum) { + if (!ca.ports[portnum]) { + umad_release_ca(&ca); + continue; + } + } + + // fill candidate + *ca_pair = cas_pair[i]; + rc = find_preferred_ports(ca_pair, &ca, is_gsi, portnum); + umad_release_ca(&ca); + + if (!rc) + break; + } + + if (rc) { + errno = ENODEV; + return -errno; + } + + return rc; +} + diff --git a/libibumad/umad.h b/libibumad/umad.h index 195216e1b..e900d8ea2 100644 --- a/libibumad/umad.h +++ b/libibumad/umad.h @@ -169,6 +169,14 @@ typedef struct umad_ca { umad_port_t *ports[UMAD_CA_MAX_PORTS]; } umad_ca_t; +struct umad_ca_pair { + char smi_name[UMAD_CA_NAME_LEN]; + uint32_t smi_preferred_port; + char gsi_name[UMAD_CA_NAME_LEN]; + uint32_t gsi_preferred_port; +}; + + struct umad_device_node { struct umad_device_node *next; /* next umad device node */ const char *ca_name; /* ca name */ @@ -237,6 +245,9 @@ int umad_register2(int port_fd, struct umad_reg_attr *attr, int umad_debug(int level); void umad_addr_dump(ib_mad_addr_t * addr); void umad_dump(void *umad); +int umad_get_smi_gsi_pairs(struct umad_ca_pair cas[], size_t max); +int umad_get_smi_gsi_pair_by_ca_name(const char *devname, uint8_t portnum, + struct umad_ca_pair *ca_pair, unsigned enforce_smi); static inline void *umad_alloc(int num, size_t size) { /* alloc array of umad buffers */