/** ========================================================================= * Resolve local CA characteristics using the umad layer rather than using * ib_resolve_self_via which requires SMP queries on the local port. */ int resolve_self(char *ca_name, uint8_t ca_port, ib_portid_t *portid, int *portnum, ibmad_gid_t *gid) { umad_port_t port; uint64_t prefix, guid; int rc; if (!(portid || portnum || gid)) return (-1); if ((rc = umad_get_port(ca_name, ca_port, &port)) < 0) return rc; if (portid) { memset(portid, 0, sizeof(*portid)); portid->lid = port.base_lid; portid->sl = port.sm_sl; } if (portnum) *portnum = port.portnum; if (gid) { memset(gid, 0, sizeof(*gid)); prefix = cl_hton64(port.gid_prefix); guid = cl_hton64(port.port_guid); mad_encode_field(*gid, IB_GID_PREFIX_F, &prefix); mad_encode_field(*gid, IB_GID_GUID_F, &guid); } umad_release_port(&port); return 0; }
/** ========================================================================= * Cache the pkeys associated with the port passed into the port object. * * @param port * @return 0 on success +ERRNO on failure */ static int cache_port_details(struct oib_port *port) { int err = 0; if ((err = oib_lock_sem(&port->umad_port_cache_lock)) != 0) { OUTPUT_ERROR("Cannot cache pkeys, failed to acquire lock (err: %d)\n", err); return EIO; } if (port->umad_port_cache_valid) { umad_release_port(&port->umad_port_cache); } port->umad_port_cache.pkeys_size = 0; port->umad_port_cache_valid = 0; if (umad_get_port(port->hfi_name, port->hfi_port_num, &port->umad_port_cache) < 0) { OUTPUT_ERROR ("can't get UMAD port information (%s:%d)\n", port->hfi_name, port->hfi_port_num); err = EIO; goto fail; } if (!port->umad_port_cache.pkeys) { OUTPUT_ERROR ("no UMAD pkeys for (%s:%d)\n", port->hfi_name, port->hfi_port_num); err = EIO; goto fail2; } /* NOTE the umad interface returns network byte order here; fix it */ port->umad_port_cache.port_guid = ntoh64(port->umad_port_cache.port_guid); port->umad_port_cache.gid_prefix = ntoh64(port->umad_port_cache.gid_prefix); port->umad_port_cache_valid = 1; oib_unlock_sem(&port->umad_port_cache_lock); return 0; fail2: umad_release_port(&port->umad_port_cache); port->umad_port_cache.pkeys_size = 0; port->umad_port_cache_valid = 0; fail: oib_unlock_sem(&port->umad_port_cache_lock); return err; }
/***************************************************************************** Update lids of vendor umad_port. *****************************************************************************/ static ib_api_status_t update_umad_port(osm_vendor_t * p_vend) { umad_port_t port; if (umad_get_port(p_vend->umad_port.ca_name, p_vend->umad_port.portnum, &port) < 0) return IB_ERROR; p_vend->umad_port.base_lid = port.base_lid; p_vend->umad_port.sm_lid = port.sm_lid; umad_release_port(&port); return IB_SUCCESS; }
/** ========================================================================= * Resolve the SM portid using the umad layer rather than using * ib_resolve_smlid_via which requires a PortInfo query on the local port. */ int resolve_sm_portid(char *ca_name, uint8_t portnum, ib_portid_t *sm_id) { umad_port_t port; int rc; if (!sm_id) return (-1); if ((rc = umad_get_port(ca_name, portnum, &port)) < 0) return rc; memset(sm_id, 0, sizeof(*sm_id)); sm_id->lid = port.sm_lid; sm_id->sl = port.sm_sl; umad_release_port(&port); return 0; }
static int port_is_opa(char *hfi_name, int port_num) { int fd; int rc; int pkey_index; uint32_t aid; uint8_t base_version; umad_port_t umad_port; if (umad_get_port(hfi_name, port_num, &umad_port) != 0) return 0; pkey_index = find_pkey_from_umad_port(&umad_port, 0x7fff); umad_release_port(&umad_port); if (pkey_index < 0) return 0; if ((fd = umad_open_port(hfi_name, port_num)) < 0) return 0; if (register_ib_smi_dr(fd, &aid) != 0) { rc = 0; goto close; } base_version = get_base_version_from_ni(fd, aid, pkey_index); umad_unregister(fd, (int)aid); rc = (base_version == 0x80); close: umad_close_port(fd); return rc; }
/** ========================================================================= */ int oib_open_port(struct oib_port **port, char *hfi_name, uint8_t port_num) { int i,j; int err; struct oib_port *rc; if (init_sub_lib()) return (EIO); if ((rc = calloc(1, sizeof(*rc))) == NULL) return (ENOMEM); if ((rc->umad_fd = umad_open_port(hfi_name, port_num)) < 0) { OUTPUT_ERROR ("can't open UMAD port (%s:%d)\n", hfi_name, port_num); err = EIO; goto free_rc; } if (!port_is_opa(hfi_name, port_num)) { umad_close_port(rc->umad_fd); if (hfi_name) { OUTPUT_ERROR ("Port is not OPA (%s:%d)\n", hfi_name, port_num); err = EIO; goto free_rc; } /* hfi was wild carded, attempt to open the first OPA HFI */ rc->umad_fd = open_first_opa_hfi(port_num, rc->hfi_name, sizeof(rc->hfi_name)); if (rc->umad_fd < 0) { OUTPUT_ERROR ("OPA port not found (%d)\n", port_num); err = EIO; goto free_rc; } } else if (!hfi_name) { /* get the actual name from a null hfi_name */ umad_port_t umad_port; if (umad_get_port(NULL, port_num, &umad_port) < 0) { OUTPUT_ERROR ("Failed to get umad port name (<null>:%d)\n", port_num); err = EIO; goto close_port; } snprintf(rc->hfi_name, sizeof(rc->hfi_name), "%s", umad_port.ca_name); umad_release_port(&umad_port); } else { snprintf(rc->hfi_name, sizeof(rc->hfi_name), "%s", hfi_name); } rc->hfi_port_num = port_num; rc->num_userspace_recv_buf = DEFAULT_USERSPACE_RECV_BUF; rc->num_userspace_send_buf = DEFAULT_USERSPACE_SEND_BUF; for (i = 0; i < OIB_MAX_CLASS_VERSION; i++) { for (j = 0; j < OIB_MAX_CLASS; j++) { rc->umad_agents[i][j] = OIB_INVALID_AGENTID; } } if (sem_init(&rc->umad_port_cache_lock,0,1) != 0) { OUTPUT_ERROR("failed to init umad_port_cache_lock\n"); err = EIO; goto close_port; } if ((err = open_verbs_ctx(rc)) != 0) goto destroy_cache_lock; if ((err = cache_port_details(rc)) != 0) goto close_verbs; if ((err = start_port_thread(rc)) != 0) goto release_cache; rc->hfi_num = oib_get_hfiNum(rc->hfi_name); LIST_INIT(&rc->pending_reg_msg_head); *port = rc; return (0); release_cache: umad_release_port(&rc->umad_port_cache); close_verbs: close_verbs_ctx(rc); destroy_cache_lock: sem_destroy(&rc->umad_port_cache_lock); close_port: umad_close_port(rc->umad_fd); free_rc: free(rc); return (err); }