1219820Sjeff/* 2219820Sjeff * Copyright (c) 2005 Cisco Systems. All rights reserved. 3219820Sjeff * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. 4219820Sjeff * 5219820Sjeff * This software is available to you under a choice of one of two 6219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 7219820Sjeff * General Public License (GPL) Version 2, available from the file 8219820Sjeff * COPYING in the main directory of this source tree, or the 9219820Sjeff * OpenIB.org BSD license below: 10219820Sjeff * 11219820Sjeff * Redistribution and use in source and binary forms, with or 12219820Sjeff * without modification, are permitted provided that the following 13219820Sjeff * conditions are met: 14219820Sjeff * 15219820Sjeff * - Redistributions of source code must retain the above 16219820Sjeff * copyright notice, this list of conditions and the following 17219820Sjeff * disclaimer. 18219820Sjeff * 19219820Sjeff * - Redistributions in binary form must reproduce the above 20219820Sjeff * copyright notice, this list of conditions and the following 21219820Sjeff * disclaimer in the documentation and/or other materials 22219820Sjeff * provided with the distribution. 23219820Sjeff * 24219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31219820Sjeff * SOFTWARE. 32219820Sjeff */ 33219820Sjeff 34331769Shselasky#include <config.h> 35219820Sjeff 36219820Sjeff#include <stdio.h> 37219820Sjeff#include <stdlib.h> 38219820Sjeff#include <unistd.h> 39219820Sjeff#include <string.h> 40219820Sjeff#include <getopt.h> 41331769Shselasky#include <infiniband/endian.h> 42331769Shselasky#include <inttypes.h> 43219820Sjeff 44219820Sjeff#include <infiniband/verbs.h> 45219820Sjeff#include <infiniband/driver.h> 46219820Sjeff 47219820Sjeffstatic int verbose; 48219820Sjeff 49219820Sjeffstatic int null_gid(union ibv_gid *gid) 50219820Sjeff{ 51219820Sjeff return !(gid->raw[8] | gid->raw[9] | gid->raw[10] | gid->raw[11] | 52219820Sjeff gid->raw[12] | gid->raw[13] | gid->raw[14] | gid->raw[15]); 53219820Sjeff} 54219820Sjeff 55331769Shselaskystatic const char *guid_str(__be64 _node_guid, char *str) 56219820Sjeff{ 57331769Shselasky uint64_t node_guid = be64toh(_node_guid); 58219820Sjeff sprintf(str, "%04x:%04x:%04x:%04x", 59219820Sjeff (unsigned) (node_guid >> 48) & 0xffff, 60219820Sjeff (unsigned) (node_guid >> 32) & 0xffff, 61219820Sjeff (unsigned) (node_guid >> 16) & 0xffff, 62219820Sjeff (unsigned) (node_guid >> 0) & 0xffff); 63219820Sjeff return str; 64219820Sjeff} 65219820Sjeff 66219820Sjeffstatic const char *transport_str(enum ibv_transport_type transport) 67219820Sjeff{ 68219820Sjeff switch (transport) { 69331769Shselasky case IBV_TRANSPORT_IB: return "InfiniBand"; 70331769Shselasky case IBV_TRANSPORT_IWARP: return "iWARP"; 71331769Shselasky case IBV_TRANSPORT_USNIC: return "usNIC"; 72331769Shselasky case IBV_TRANSPORT_USNIC_UDP: return "usNIC UDP"; 73331769Shselasky default: return "invalid transport"; 74219820Sjeff } 75219820Sjeff} 76219820Sjeff 77219820Sjeffstatic const char *port_state_str(enum ibv_port_state pstate) 78219820Sjeff{ 79219820Sjeff switch (pstate) { 80219820Sjeff case IBV_PORT_DOWN: return "PORT_DOWN"; 81219820Sjeff case IBV_PORT_INIT: return "PORT_INIT"; 82219820Sjeff case IBV_PORT_ARMED: return "PORT_ARMED"; 83219820Sjeff case IBV_PORT_ACTIVE: return "PORT_ACTIVE"; 84219820Sjeff default: return "invalid state"; 85219820Sjeff } 86219820Sjeff} 87219820Sjeff 88219820Sjeffstatic const char *port_phy_state_str(uint8_t phys_state) 89219820Sjeff{ 90219820Sjeff switch (phys_state) { 91219820Sjeff case 1: return "SLEEP"; 92219820Sjeff case 2: return "POLLING"; 93219820Sjeff case 3: return "DISABLED"; 94219820Sjeff case 4: return "PORT_CONFIGURATION TRAINNING"; 95219820Sjeff case 5: return "LINK_UP"; 96219820Sjeff case 6: return "LINK_ERROR_RECOVERY"; 97219820Sjeff case 7: return "PHY TEST"; 98219820Sjeff default: return "invalid physical state"; 99219820Sjeff } 100219820Sjeff} 101219820Sjeff 102219820Sjeffstatic const char *atomic_cap_str(enum ibv_atomic_cap atom_cap) 103219820Sjeff{ 104219820Sjeff switch (atom_cap) { 105219820Sjeff case IBV_ATOMIC_NONE: return "ATOMIC_NONE"; 106219820Sjeff case IBV_ATOMIC_HCA: return "ATOMIC_HCA"; 107219820Sjeff case IBV_ATOMIC_GLOB: return "ATOMIC_GLOB"; 108219820Sjeff default: return "invalid atomic capability"; 109219820Sjeff } 110219820Sjeff} 111219820Sjeff 112219820Sjeffstatic const char *mtu_str(enum ibv_mtu max_mtu) 113219820Sjeff{ 114219820Sjeff switch (max_mtu) { 115219820Sjeff case IBV_MTU_256: return "256"; 116219820Sjeff case IBV_MTU_512: return "512"; 117219820Sjeff case IBV_MTU_1024: return "1024"; 118219820Sjeff case IBV_MTU_2048: return "2048"; 119219820Sjeff case IBV_MTU_4096: return "4096"; 120219820Sjeff default: return "invalid MTU"; 121219820Sjeff } 122219820Sjeff} 123219820Sjeff 124219820Sjeffstatic const char *width_str(uint8_t width) 125219820Sjeff{ 126219820Sjeff switch (width) { 127219820Sjeff case 1: return "1"; 128219820Sjeff case 2: return "4"; 129219820Sjeff case 4: return "8"; 130219820Sjeff case 8: return "12"; 131347858Shselasky case 16: return "2"; 132219820Sjeff default: return "invalid width"; 133219820Sjeff } 134219820Sjeff} 135219820Sjeff 136219820Sjeffstatic const char *speed_str(uint8_t speed) 137219820Sjeff{ 138219820Sjeff switch (speed) { 139219820Sjeff case 1: return "2.5 Gbps"; 140219820Sjeff case 2: return "5.0 Gbps"; 141331769Shselasky 142331769Shselasky case 4: /* fall through */ 143331769Shselasky case 8: return "10.0 Gbps"; 144331769Shselasky 145331769Shselasky case 16: return "14.0 Gbps"; 146331769Shselasky case 32: return "25.0 Gbps"; 147347858Shselasky case 64: return "50.0 Gbps"; 148219820Sjeff default: return "invalid speed"; 149219820Sjeff } 150219820Sjeff} 151219820Sjeff 152219820Sjeffstatic const char *vl_str(uint8_t vl_num) 153219820Sjeff{ 154219820Sjeff switch (vl_num) { 155219820Sjeff case 1: return "1"; 156219820Sjeff case 2: return "2"; 157219820Sjeff case 3: return "4"; 158219820Sjeff case 4: return "8"; 159219820Sjeff case 5: return "15"; 160219820Sjeff default: return "invalid value"; 161219820Sjeff } 162219820Sjeff} 163219820Sjeff 164219820Sjeffstatic int print_all_port_gids(struct ibv_context *ctx, uint8_t port_num, int tbl_len) 165219820Sjeff{ 166219820Sjeff union ibv_gid gid; 167219820Sjeff int rc = 0; 168219820Sjeff int i; 169219820Sjeff 170219820Sjeff for (i = 0; i < tbl_len; i++) { 171219820Sjeff rc = ibv_query_gid(ctx, port_num, i, &gid); 172219820Sjeff if (rc) { 173219820Sjeff fprintf(stderr, "Failed to query gid to port %d, index %d\n", 174219820Sjeff port_num, i); 175219820Sjeff return rc; 176219820Sjeff } 177219820Sjeff if (!null_gid(&gid)) 178219820Sjeff printf("\t\t\tGID[%3d]:\t\t%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", 179219820Sjeff i, 180219820Sjeff gid.raw[ 0], gid.raw[ 1], 181219820Sjeff gid.raw[ 2], gid.raw[ 3], 182219820Sjeff gid.raw[ 4], gid.raw[ 5], 183219820Sjeff gid.raw[ 6], gid.raw[ 7], 184219820Sjeff gid.raw[ 8], gid.raw[ 9], 185219820Sjeff gid.raw[10], gid.raw[11], 186219820Sjeff gid.raw[12], gid.raw[13], 187219820Sjeff gid.raw[14], gid.raw[15]); 188219820Sjeff } 189219820Sjeff return rc; 190219820Sjeff} 191219820Sjeff 192219820Sjeffstatic const char *link_layer_str(uint8_t link_layer) 193219820Sjeff{ 194219820Sjeff switch (link_layer) { 195219820Sjeff case IBV_LINK_LAYER_UNSPECIFIED: 196219820Sjeff case IBV_LINK_LAYER_INFINIBAND: 197331769Shselasky return "InfiniBand"; 198219820Sjeff case IBV_LINK_LAYER_ETHERNET: 199219820Sjeff return "Ethernet"; 200219820Sjeff default: 201219820Sjeff return "Unknown"; 202219820Sjeff } 203219820Sjeff} 204219820Sjeff 205331769Shselaskystatic void print_device_cap_flags(uint32_t dev_cap_flags) 206331769Shselasky{ 207331769Shselasky uint32_t unknown_flags = ~(IBV_DEVICE_RESIZE_MAX_WR | 208331769Shselasky IBV_DEVICE_BAD_PKEY_CNTR | 209331769Shselasky IBV_DEVICE_BAD_QKEY_CNTR | 210331769Shselasky IBV_DEVICE_RAW_MULTI | 211331769Shselasky IBV_DEVICE_AUTO_PATH_MIG | 212331769Shselasky IBV_DEVICE_CHANGE_PHY_PORT | 213331769Shselasky IBV_DEVICE_UD_AV_PORT_ENFORCE | 214331769Shselasky IBV_DEVICE_CURR_QP_STATE_MOD | 215331769Shselasky IBV_DEVICE_SHUTDOWN_PORT | 216331769Shselasky IBV_DEVICE_INIT_TYPE | 217331769Shselasky IBV_DEVICE_PORT_ACTIVE_EVENT | 218331769Shselasky IBV_DEVICE_SYS_IMAGE_GUID | 219331769Shselasky IBV_DEVICE_RC_RNR_NAK_GEN | 220331769Shselasky IBV_DEVICE_SRQ_RESIZE | 221331769Shselasky IBV_DEVICE_N_NOTIFY_CQ | 222331769Shselasky IBV_DEVICE_MEM_WINDOW | 223331769Shselasky IBV_DEVICE_UD_IP_CSUM | 224331769Shselasky IBV_DEVICE_XRC | 225331769Shselasky IBV_DEVICE_MEM_MGT_EXTENSIONS | 226331769Shselasky IBV_DEVICE_MEM_WINDOW_TYPE_2A | 227331769Shselasky IBV_DEVICE_MEM_WINDOW_TYPE_2B | 228331769Shselasky IBV_DEVICE_RC_IP_CSUM | 229331769Shselasky IBV_DEVICE_RAW_IP_CSUM | 230331769Shselasky IBV_DEVICE_MANAGED_FLOW_STEERING); 231331769Shselasky 232331769Shselasky if (dev_cap_flags & IBV_DEVICE_RESIZE_MAX_WR) 233331769Shselasky printf("\t\t\t\t\tRESIZE_MAX_WR\n"); 234331769Shselasky if (dev_cap_flags & IBV_DEVICE_BAD_PKEY_CNTR) 235331769Shselasky printf("\t\t\t\t\tBAD_PKEY_CNTR\n"); 236331769Shselasky if (dev_cap_flags & IBV_DEVICE_BAD_QKEY_CNTR) 237331769Shselasky printf("\t\t\t\t\tBAD_QKEY_CNTR\n"); 238331769Shselasky if (dev_cap_flags & IBV_DEVICE_RAW_MULTI) 239331769Shselasky printf("\t\t\t\t\tRAW_MULTI\n"); 240331769Shselasky if (dev_cap_flags & IBV_DEVICE_AUTO_PATH_MIG) 241331769Shselasky printf("\t\t\t\t\tAUTO_PATH_MIG\n"); 242331769Shselasky if (dev_cap_flags & IBV_DEVICE_CHANGE_PHY_PORT) 243331769Shselasky printf("\t\t\t\t\tCHANGE_PHY_PORT\n"); 244331769Shselasky if (dev_cap_flags & IBV_DEVICE_UD_AV_PORT_ENFORCE) 245331769Shselasky printf("\t\t\t\t\tUD_AV_PORT_ENFORCE\n"); 246331769Shselasky if (dev_cap_flags & IBV_DEVICE_CURR_QP_STATE_MOD) 247331769Shselasky printf("\t\t\t\t\tCURR_QP_STATE_MOD\n"); 248331769Shselasky if (dev_cap_flags & IBV_DEVICE_SHUTDOWN_PORT) 249331769Shselasky printf("\t\t\t\t\tSHUTDOWN_PORT\n"); 250331769Shselasky if (dev_cap_flags & IBV_DEVICE_INIT_TYPE) 251331769Shselasky printf("\t\t\t\t\tINIT_TYPE\n"); 252331769Shselasky if (dev_cap_flags & IBV_DEVICE_PORT_ACTIVE_EVENT) 253331769Shselasky printf("\t\t\t\t\tPORT_ACTIVE_EVENT\n"); 254331769Shselasky if (dev_cap_flags & IBV_DEVICE_SYS_IMAGE_GUID) 255331769Shselasky printf("\t\t\t\t\tSYS_IMAGE_GUID\n"); 256331769Shselasky if (dev_cap_flags & IBV_DEVICE_RC_RNR_NAK_GEN) 257331769Shselasky printf("\t\t\t\t\tRC_RNR_NAK_GEN\n"); 258331769Shselasky if (dev_cap_flags & IBV_DEVICE_SRQ_RESIZE) 259331769Shselasky printf("\t\t\t\t\tSRQ_RESIZE\n"); 260331769Shselasky if (dev_cap_flags & IBV_DEVICE_N_NOTIFY_CQ) 261331769Shselasky printf("\t\t\t\t\tN_NOTIFY_CQ\n"); 262331769Shselasky if (dev_cap_flags & IBV_DEVICE_MEM_WINDOW) 263331769Shselasky printf("\t\t\t\t\tMEM_WINDOW\n"); 264331769Shselasky if (dev_cap_flags & IBV_DEVICE_UD_IP_CSUM) 265331769Shselasky printf("\t\t\t\t\tUD_IP_CSUM\n"); 266331769Shselasky if (dev_cap_flags & IBV_DEVICE_XRC) 267331769Shselasky printf("\t\t\t\t\tXRC\n"); 268331769Shselasky if (dev_cap_flags & IBV_DEVICE_MEM_MGT_EXTENSIONS) 269331769Shselasky printf("\t\t\t\t\tMEM_MGT_EXTENSIONS\n"); 270331769Shselasky if (dev_cap_flags & IBV_DEVICE_MEM_WINDOW_TYPE_2A) 271331769Shselasky printf("\t\t\t\t\tMEM_WINDOW_TYPE_2A\n"); 272331769Shselasky if (dev_cap_flags & IBV_DEVICE_MEM_WINDOW_TYPE_2B) 273331769Shselasky printf("\t\t\t\t\tMEM_WINDOW_TYPE_2B\n"); 274331769Shselasky if (dev_cap_flags & IBV_DEVICE_RC_IP_CSUM) 275331769Shselasky printf("\t\t\t\t\tRC_IP_CSUM\n"); 276331769Shselasky if (dev_cap_flags & IBV_DEVICE_RAW_IP_CSUM) 277331769Shselasky printf("\t\t\t\t\tRAW_IP_CSUM\n"); 278331769Shselasky if (dev_cap_flags & IBV_DEVICE_MANAGED_FLOW_STEERING) 279331769Shselasky printf("\t\t\t\t\tMANAGED_FLOW_STEERING\n"); 280331769Shselasky if (dev_cap_flags & unknown_flags) 281331769Shselasky printf("\t\t\t\t\tUnknown flags: 0x%" PRIX32 "\n", 282331769Shselasky dev_cap_flags & unknown_flags); 283331769Shselasky} 284331769Shselasky 285331769Shselaskystatic void print_odp_trans_caps(uint32_t trans) 286331769Shselasky{ 287331769Shselasky uint32_t unknown_transport_caps = ~(IBV_ODP_SUPPORT_SEND | 288331769Shselasky IBV_ODP_SUPPORT_RECV | 289331769Shselasky IBV_ODP_SUPPORT_WRITE | 290331769Shselasky IBV_ODP_SUPPORT_READ | 291331769Shselasky IBV_ODP_SUPPORT_ATOMIC); 292331769Shselasky 293331769Shselasky if (!trans) { 294331769Shselasky printf("\t\t\t\t\tNO SUPPORT\n"); 295331769Shselasky } else { 296331769Shselasky if (trans & IBV_ODP_SUPPORT_SEND) 297331769Shselasky printf("\t\t\t\t\tSUPPORT_SEND\n"); 298331769Shselasky if (trans & IBV_ODP_SUPPORT_RECV) 299331769Shselasky printf("\t\t\t\t\tSUPPORT_RECV\n"); 300331769Shselasky if (trans & IBV_ODP_SUPPORT_WRITE) 301331769Shselasky printf("\t\t\t\t\tSUPPORT_WRITE\n"); 302331769Shselasky if (trans & IBV_ODP_SUPPORT_READ) 303331769Shselasky printf("\t\t\t\t\tSUPPORT_READ\n"); 304331769Shselasky if (trans & IBV_ODP_SUPPORT_ATOMIC) 305331769Shselasky printf("\t\t\t\t\tSUPPORT_ATOMIC\n"); 306331769Shselasky if (trans & unknown_transport_caps) 307331769Shselasky printf("\t\t\t\t\tUnknown flags: 0x%" PRIX32 "\n", 308331769Shselasky trans & unknown_transport_caps); 309331769Shselasky } 310331769Shselasky} 311331769Shselasky 312331769Shselaskystatic void print_odp_caps(const struct ibv_odp_caps *caps) 313331769Shselasky{ 314331769Shselasky uint64_t unknown_general_caps = ~(IBV_ODP_SUPPORT); 315331769Shselasky 316331769Shselasky /* general odp caps */ 317331769Shselasky printf("\tgeneral_odp_caps:\n"); 318331769Shselasky if (caps->general_caps & IBV_ODP_SUPPORT) 319331769Shselasky printf("\t\t\t\t\tODP_SUPPORT\n"); 320331769Shselasky if (caps->general_caps & unknown_general_caps) 321331769Shselasky printf("\t\t\t\t\tUnknown flags: 0x%" PRIX64 "\n", 322331769Shselasky caps->general_caps & unknown_general_caps); 323331769Shselasky 324331769Shselasky /* RC transport */ 325331769Shselasky printf("\trc_odp_caps:\n"); 326331769Shselasky print_odp_trans_caps(caps->per_transport_caps.rc_odp_caps); 327331769Shselasky printf("\tuc_odp_caps:\n"); 328331769Shselasky print_odp_trans_caps(caps->per_transport_caps.uc_odp_caps); 329331769Shselasky printf("\tud_odp_caps:\n"); 330331769Shselasky print_odp_trans_caps(caps->per_transport_caps.ud_odp_caps); 331331769Shselasky} 332331769Shselasky 333331769Shselaskystatic void print_device_cap_flags_ex(uint64_t device_cap_flags_ex) 334331769Shselasky{ 335331769Shselasky uint64_t ex_flags = device_cap_flags_ex & 0xffffffff00000000ULL; 336331769Shselasky uint64_t unknown_flags = ~(IBV_DEVICE_RAW_SCATTER_FCS); 337331769Shselasky 338331769Shselasky if (ex_flags & IBV_DEVICE_RAW_SCATTER_FCS) 339331769Shselasky printf("\t\t\t\t\tRAW_SCATTER_FCS\n"); 340331769Shselasky if (ex_flags & unknown_flags) 341331769Shselasky printf("\t\t\t\t\tUnknown flags: 0x%" PRIX64 "\n", 342331769Shselasky ex_flags & unknown_flags); 343331769Shselasky} 344331769Shselasky 345331769Shselaskystatic void print_tso_caps(const struct ibv_tso_caps *caps) 346331769Shselasky{ 347331769Shselasky uint32_t unknown_general_caps = ~(1 << IBV_QPT_RAW_PACKET | 348331769Shselasky 1 << IBV_QPT_UD); 349331769Shselasky printf("\ttso_caps:\n"); 350331769Shselasky printf("\tmax_tso:\t\t\t%d\n", caps->max_tso); 351331769Shselasky 352331769Shselasky if (caps->max_tso) { 353331769Shselasky printf("\tsupported_qp:\n"); 354331769Shselasky if (ibv_is_qpt_supported(caps->supported_qpts, IBV_QPT_RAW_PACKET)) 355331769Shselasky printf("\t\t\t\t\tSUPPORT_RAW_PACKET\n"); 356331769Shselasky if (ibv_is_qpt_supported(caps->supported_qpts, IBV_QPT_UD)) 357331769Shselasky printf("\t\t\t\t\tSUPPORT_UD\n"); 358331769Shselasky if (caps->supported_qpts & unknown_general_caps) 359331769Shselasky printf("\t\t\t\t\tUnknown flags: 0x%" PRIX32 "\n", 360331769Shselasky caps->supported_qpts & unknown_general_caps); 361331769Shselasky } 362331769Shselasky} 363331769Shselasky 364331769Shselaskystatic void print_rss_caps(const struct ibv_rss_caps *caps) 365331769Shselasky{ 366331769Shselasky uint32_t unknown_general_caps = ~(1 << IBV_QPT_RAW_PACKET | 367331769Shselasky 1 << IBV_QPT_UD); 368331769Shselasky printf("\trss_caps:\n"); 369331769Shselasky printf("\t\tmax_rwq_indirection_tables:\t\t\t%u\n", caps->max_rwq_indirection_tables); 370331769Shselasky printf("\t\tmax_rwq_indirection_table_size:\t\t\t%u\n", caps->max_rwq_indirection_table_size); 371331769Shselasky printf("\t\trx_hash_function:\t\t\t\t0x%x\n", caps->rx_hash_function); 372331769Shselasky printf("\t\trx_hash_fields_mask:\t\t\t\t0x%" PRIX64 "\n", caps->rx_hash_fields_mask); 373331769Shselasky 374331769Shselasky if (caps->supported_qpts) { 375331769Shselasky printf("\t\tsupported_qp:\n"); 376331769Shselasky if (ibv_is_qpt_supported(caps->supported_qpts, IBV_QPT_RAW_PACKET)) 377331769Shselasky printf("\t\t\t\t\tSUPPORT_RAW_PACKET\n"); 378331769Shselasky if (ibv_is_qpt_supported(caps->supported_qpts, IBV_QPT_UD)) 379331769Shselasky printf("\t\t\t\t\tSUPPORT_UD\n"); 380331769Shselasky if (caps->supported_qpts & unknown_general_caps) 381331769Shselasky printf("\t\t\t\t\tUnknown flags: 0x%" PRIX32 "\n", 382331769Shselasky caps->supported_qpts & unknown_general_caps); 383331769Shselasky } 384331769Shselasky} 385331769Shselasky 386331769Shselaskystatic void print_packet_pacing_caps(const struct ibv_packet_pacing_caps *caps) 387331769Shselasky{ 388331769Shselasky uint32_t unknown_general_caps = ~(1 << IBV_QPT_RAW_PACKET | 389331769Shselasky 1 << IBV_QPT_UD); 390331769Shselasky printf("\tpacket_pacing_caps:\n"); 391331769Shselasky printf("\t\tqp_rate_limit_min:\t%ukbps\n", caps->qp_rate_limit_min); 392331769Shselasky printf("\t\tqp_rate_limit_max:\t%ukbps\n", caps->qp_rate_limit_max); 393331769Shselasky 394331769Shselasky if (caps->qp_rate_limit_max) { 395331769Shselasky printf("\t\tsupported_qp:\n"); 396331769Shselasky if (ibv_is_qpt_supported(caps->supported_qpts, IBV_QPT_RAW_PACKET)) 397331769Shselasky printf("\t\t\t\t\tSUPPORT_RAW_PACKET\n"); 398331769Shselasky if (ibv_is_qpt_supported(caps->supported_qpts, IBV_QPT_UD)) 399331769Shselasky printf("\t\t\t\t\tSUPPORT_UD\n"); 400331769Shselasky if (caps->supported_qpts & unknown_general_caps) 401331769Shselasky printf("\t\t\t\t\tUnknown flags: 0x%" PRIX32 "\n", 402331769Shselasky caps->supported_qpts & unknown_general_caps); 403331769Shselasky } 404331769Shselasky} 405331769Shselasky 406331769Shselaskystatic void print_raw_packet_caps(uint32_t raw_packet_caps) 407331769Shselasky{ 408331769Shselasky printf("\traw packet caps:\n"); 409331769Shselasky if (raw_packet_caps & IBV_RAW_PACKET_CAP_CVLAN_STRIPPING) 410331769Shselasky printf("\t\t\t\t\tC-VLAN stripping offload\n"); 411331769Shselasky if (raw_packet_caps & IBV_RAW_PACKET_CAP_SCATTER_FCS) 412331769Shselasky printf("\t\t\t\t\tScatter FCS offload\n"); 413331769Shselasky if (raw_packet_caps & IBV_RAW_PACKET_CAP_IP_CSUM) 414331769Shselasky printf("\t\t\t\t\tIP csum offload\n"); 415331769Shselasky} 416331769Shselasky 417219820Sjeffstatic int print_hca_cap(struct ibv_device *ib_dev, uint8_t ib_port) 418219820Sjeff{ 419219820Sjeff struct ibv_context *ctx; 420331769Shselasky struct ibv_device_attr_ex device_attr; 421219820Sjeff struct ibv_port_attr port_attr; 422219820Sjeff int rc = 0; 423219820Sjeff uint8_t port; 424219820Sjeff char buf[256]; 425219820Sjeff 426219820Sjeff ctx = ibv_open_device(ib_dev); 427219820Sjeff if (!ctx) { 428219820Sjeff fprintf(stderr, "Failed to open device\n"); 429219820Sjeff rc = 1; 430219820Sjeff goto cleanup; 431219820Sjeff } 432331769Shselasky if (ibv_query_device_ex(ctx, NULL, &device_attr)) { 433331769Shselasky fprintf(stderr, "Failed to query device props\n"); 434219820Sjeff rc = 2; 435219820Sjeff goto cleanup; 436219820Sjeff } 437331769Shselasky if (ib_port && ib_port > device_attr.orig_attr.phys_port_cnt) { 438331769Shselasky fprintf(stderr, "Invalid port requested for device\n"); 439331769Shselasky /* rc = 3 is taken by failure to clean up */ 440331769Shselasky rc = 4; 441331769Shselasky goto cleanup; 442331769Shselasky } 443219820Sjeff 444219820Sjeff printf("hca_id:\t%s\n", ibv_get_device_name(ib_dev)); 445219820Sjeff printf("\ttransport:\t\t\t%s (%d)\n", 446219820Sjeff transport_str(ib_dev->transport_type), ib_dev->transport_type); 447331769Shselasky if (strlen(device_attr.orig_attr.fw_ver)) 448331769Shselasky printf("\tfw_ver:\t\t\t\t%s\n", device_attr.orig_attr.fw_ver); 449331769Shselasky printf("\tnode_guid:\t\t\t%s\n", guid_str(device_attr.orig_attr.node_guid, buf)); 450331769Shselasky printf("\tsys_image_guid:\t\t\t%s\n", guid_str(device_attr.orig_attr.sys_image_guid, buf)); 451331769Shselasky printf("\tvendor_id:\t\t\t0x%04x\n", device_attr.orig_attr.vendor_id); 452331769Shselasky printf("\tvendor_part_id:\t\t\t%d\n", device_attr.orig_attr.vendor_part_id); 453331769Shselasky printf("\thw_ver:\t\t\t\t0x%X\n", device_attr.orig_attr.hw_ver); 454219820Sjeff 455219820Sjeff if (ibv_read_sysfs_file(ib_dev->ibdev_path, "board_id", buf, sizeof buf) > 0) 456219820Sjeff printf("\tboard_id:\t\t\t%s\n", buf); 457219820Sjeff 458331769Shselasky printf("\tphys_port_cnt:\t\t\t%d\n", device_attr.orig_attr.phys_port_cnt); 459219820Sjeff 460219820Sjeff if (verbose) { 461219820Sjeff printf("\tmax_mr_size:\t\t\t0x%llx\n", 462331769Shselasky (unsigned long long) device_attr.orig_attr.max_mr_size); 463219820Sjeff printf("\tpage_size_cap:\t\t\t0x%llx\n", 464331769Shselasky (unsigned long long) device_attr.orig_attr.page_size_cap); 465331769Shselasky printf("\tmax_qp:\t\t\t\t%d\n", device_attr.orig_attr.max_qp); 466331769Shselasky printf("\tmax_qp_wr:\t\t\t%d\n", device_attr.orig_attr.max_qp_wr); 467331769Shselasky printf("\tdevice_cap_flags:\t\t0x%08x\n", device_attr.orig_attr.device_cap_flags); 468331769Shselasky print_device_cap_flags(device_attr.orig_attr.device_cap_flags); 469331769Shselasky printf("\tmax_sge:\t\t\t%d\n", device_attr.orig_attr.max_sge); 470331769Shselasky printf("\tmax_sge_rd:\t\t\t%d\n", device_attr.orig_attr.max_sge_rd); 471331769Shselasky printf("\tmax_cq:\t\t\t\t%d\n", device_attr.orig_attr.max_cq); 472331769Shselasky printf("\tmax_cqe:\t\t\t%d\n", device_attr.orig_attr.max_cqe); 473331769Shselasky printf("\tmax_mr:\t\t\t\t%d\n", device_attr.orig_attr.max_mr); 474331769Shselasky printf("\tmax_pd:\t\t\t\t%d\n", device_attr.orig_attr.max_pd); 475331769Shselasky printf("\tmax_qp_rd_atom:\t\t\t%d\n", device_attr.orig_attr.max_qp_rd_atom); 476331769Shselasky printf("\tmax_ee_rd_atom:\t\t\t%d\n", device_attr.orig_attr.max_ee_rd_atom); 477331769Shselasky printf("\tmax_res_rd_atom:\t\t%d\n", device_attr.orig_attr.max_res_rd_atom); 478331769Shselasky printf("\tmax_qp_init_rd_atom:\t\t%d\n", device_attr.orig_attr.max_qp_init_rd_atom); 479331769Shselasky printf("\tmax_ee_init_rd_atom:\t\t%d\n", device_attr.orig_attr.max_ee_init_rd_atom); 480219820Sjeff printf("\tatomic_cap:\t\t\t%s (%d)\n", 481331769Shselasky atomic_cap_str(device_attr.orig_attr.atomic_cap), device_attr.orig_attr.atomic_cap); 482331769Shselasky printf("\tmax_ee:\t\t\t\t%d\n", device_attr.orig_attr.max_ee); 483331769Shselasky printf("\tmax_rdd:\t\t\t%d\n", device_attr.orig_attr.max_rdd); 484331769Shselasky printf("\tmax_mw:\t\t\t\t%d\n", device_attr.orig_attr.max_mw); 485331769Shselasky printf("\tmax_raw_ipv6_qp:\t\t%d\n", device_attr.orig_attr.max_raw_ipv6_qp); 486331769Shselasky printf("\tmax_raw_ethy_qp:\t\t%d\n", device_attr.orig_attr.max_raw_ethy_qp); 487331769Shselasky printf("\tmax_mcast_grp:\t\t\t%d\n", device_attr.orig_attr.max_mcast_grp); 488331769Shselasky printf("\tmax_mcast_qp_attach:\t\t%d\n", device_attr.orig_attr.max_mcast_qp_attach); 489219820Sjeff printf("\tmax_total_mcast_qp_attach:\t%d\n", 490331769Shselasky device_attr.orig_attr.max_total_mcast_qp_attach); 491331769Shselasky printf("\tmax_ah:\t\t\t\t%d\n", device_attr.orig_attr.max_ah); 492331769Shselasky printf("\tmax_fmr:\t\t\t%d\n", device_attr.orig_attr.max_fmr); 493331769Shselasky if (device_attr.orig_attr.max_fmr) 494331769Shselasky printf("\tmax_map_per_fmr:\t\t%d\n", device_attr.orig_attr.max_map_per_fmr); 495331769Shselasky printf("\tmax_srq:\t\t\t%d\n", device_attr.orig_attr.max_srq); 496331769Shselasky if (device_attr.orig_attr.max_srq) { 497331769Shselasky printf("\tmax_srq_wr:\t\t\t%d\n", device_attr.orig_attr.max_srq_wr); 498331769Shselasky printf("\tmax_srq_sge:\t\t\t%d\n", device_attr.orig_attr.max_srq_sge); 499219820Sjeff } 500331769Shselasky printf("\tmax_pkeys:\t\t\t%d\n", device_attr.orig_attr.max_pkeys); 501331769Shselasky printf("\tlocal_ca_ack_delay:\t\t%d\n", device_attr.orig_attr.local_ca_ack_delay); 502331769Shselasky 503331769Shselasky print_odp_caps(&device_attr.odp_caps); 504331769Shselasky if (device_attr.completion_timestamp_mask) 505331769Shselasky printf("\tcompletion timestamp_mask:\t\t\t0x%016" PRIx64 "\n", 506331769Shselasky device_attr.completion_timestamp_mask); 507331769Shselasky else 508331769Shselasky printf("\tcompletion_timestamp_mask not supported\n"); 509331769Shselasky 510331769Shselasky if (device_attr.hca_core_clock) 511331769Shselasky printf("\thca_core_clock:\t\t\t%" PRIu64 "kHZ\n", device_attr.hca_core_clock); 512331769Shselasky else 513331769Shselasky printf("\tcore clock not supported\n"); 514331769Shselasky 515331769Shselasky if (device_attr.raw_packet_caps) 516331769Shselasky print_raw_packet_caps(device_attr.raw_packet_caps); 517331769Shselasky 518331769Shselasky printf("\tdevice_cap_flags_ex:\t\t0x%" PRIX64 "\n", device_attr.device_cap_flags_ex); 519331769Shselasky print_device_cap_flags_ex(device_attr.device_cap_flags_ex); 520331769Shselasky print_tso_caps(&device_attr.tso_caps); 521331769Shselasky print_rss_caps(&device_attr.rss_caps); 522331769Shselasky printf("\tmax_wq_type_rq:\t\t\t%u\n", device_attr.max_wq_type_rq); 523331769Shselasky print_packet_pacing_caps(&device_attr.packet_pacing_caps); 524219820Sjeff } 525219820Sjeff 526331769Shselasky for (port = 1; port <= device_attr.orig_attr.phys_port_cnt; ++port) { 527219820Sjeff /* if in the command line the user didn't ask for info about this port */ 528219820Sjeff if ((ib_port) && (port != ib_port)) 529219820Sjeff continue; 530219820Sjeff 531219820Sjeff rc = ibv_query_port(ctx, port, &port_attr); 532219820Sjeff if (rc) { 533219820Sjeff fprintf(stderr, "Failed to query port %u props\n", port); 534219820Sjeff goto cleanup; 535219820Sjeff } 536219820Sjeff printf("\t\tport:\t%d\n", port); 537219820Sjeff printf("\t\t\tstate:\t\t\t%s (%d)\n", 538219820Sjeff port_state_str(port_attr.state), port_attr.state); 539219820Sjeff printf("\t\t\tmax_mtu:\t\t%s (%d)\n", 540219820Sjeff mtu_str(port_attr.max_mtu), port_attr.max_mtu); 541219820Sjeff printf("\t\t\tactive_mtu:\t\t%s (%d)\n", 542219820Sjeff mtu_str(port_attr.active_mtu), port_attr.active_mtu); 543219820Sjeff printf("\t\t\tsm_lid:\t\t\t%d\n", port_attr.sm_lid); 544219820Sjeff printf("\t\t\tport_lid:\t\t%d\n", port_attr.lid); 545219820Sjeff printf("\t\t\tport_lmc:\t\t0x%02x\n", port_attr.lmc); 546331769Shselasky printf("\t\t\tlink_layer:\t\t%s\n", 547331769Shselasky link_layer_str(port_attr.link_layer)); 548219820Sjeff 549219820Sjeff if (verbose) { 550219820Sjeff printf("\t\t\tmax_msg_sz:\t\t0x%x\n", port_attr.max_msg_sz); 551219820Sjeff printf("\t\t\tport_cap_flags:\t\t0x%08x\n", port_attr.port_cap_flags); 552219820Sjeff printf("\t\t\tmax_vl_num:\t\t%s (%d)\n", 553219820Sjeff vl_str(port_attr.max_vl_num), port_attr.max_vl_num); 554219820Sjeff printf("\t\t\tbad_pkey_cntr:\t\t0x%x\n", port_attr.bad_pkey_cntr); 555219820Sjeff printf("\t\t\tqkey_viol_cntr:\t\t0x%x\n", port_attr.qkey_viol_cntr); 556219820Sjeff printf("\t\t\tsm_sl:\t\t\t%d\n", port_attr.sm_sl); 557219820Sjeff printf("\t\t\tpkey_tbl_len:\t\t%d\n", port_attr.pkey_tbl_len); 558219820Sjeff printf("\t\t\tgid_tbl_len:\t\t%d\n", port_attr.gid_tbl_len); 559219820Sjeff printf("\t\t\tsubnet_timeout:\t\t%d\n", port_attr.subnet_timeout); 560219820Sjeff printf("\t\t\tinit_type_reply:\t%d\n", port_attr.init_type_reply); 561219820Sjeff printf("\t\t\tactive_width:\t\t%sX (%d)\n", 562219820Sjeff width_str(port_attr.active_width), port_attr.active_width); 563219820Sjeff printf("\t\t\tactive_speed:\t\t%s (%d)\n", 564219820Sjeff speed_str(port_attr.active_speed), port_attr.active_speed); 565331769Shselasky if (ib_dev->transport_type == IBV_TRANSPORT_IB) 566331769Shselasky printf("\t\t\tphys_state:\t\t%s (%d)\n", 567331769Shselasky port_phy_state_str(port_attr.phys_state), port_attr.phys_state); 568219820Sjeff 569219820Sjeff if (print_all_port_gids(ctx, port, port_attr.gid_tbl_len)) 570219820Sjeff goto cleanup; 571219820Sjeff } 572219820Sjeff printf("\n"); 573219820Sjeff } 574219820Sjeffcleanup: 575219820Sjeff if (ctx) 576219820Sjeff if (ibv_close_device(ctx)) { 577219820Sjeff fprintf(stderr, "Failed to close device"); 578219820Sjeff rc = 3; 579219820Sjeff } 580219820Sjeff return rc; 581219820Sjeff} 582219820Sjeff 583219820Sjeffstatic void usage(const char *argv0) 584219820Sjeff{ 585219820Sjeff printf("Usage: %s print the ca attributes\n", argv0); 586219820Sjeff printf("\n"); 587219820Sjeff printf("Options:\n"); 588219820Sjeff printf(" -d, --ib-dev=<dev> use IB device <dev> (default first device found)\n"); 589219820Sjeff printf(" -i, --ib-port=<port> use port <port> of IB device (default all ports)\n"); 590219820Sjeff printf(" -l, --list print only the IB devices names\n"); 591219820Sjeff printf(" -v, --verbose print all the attributes of the IB device(s)\n"); 592219820Sjeff} 593219820Sjeff 594219820Sjeffint main(int argc, char *argv[]) 595219820Sjeff{ 596219820Sjeff char *ib_devname = NULL; 597219820Sjeff int ret = 0; 598219820Sjeff struct ibv_device **dev_list, **orig_dev_list; 599219820Sjeff int num_of_hcas; 600219820Sjeff int ib_port = 0; 601219820Sjeff 602219820Sjeff /* parse command line options */ 603219820Sjeff while (1) { 604219820Sjeff int c; 605219820Sjeff static struct option long_options[] = { 606219820Sjeff { .name = "ib-dev", .has_arg = 1, .val = 'd' }, 607219820Sjeff { .name = "ib-port", .has_arg = 1, .val = 'i' }, 608219820Sjeff { .name = "list", .has_arg = 0, .val = 'l' }, 609219820Sjeff { .name = "verbose", .has_arg = 0, .val = 'v' }, 610331769Shselasky { } 611219820Sjeff }; 612219820Sjeff 613219820Sjeff c = getopt_long(argc, argv, "d:i:lv", long_options, NULL); 614219820Sjeff if (c == -1) 615219820Sjeff break; 616219820Sjeff 617219820Sjeff switch (c) { 618219820Sjeff case 'd': 619219820Sjeff ib_devname = strdup(optarg); 620219820Sjeff break; 621219820Sjeff 622219820Sjeff case 'i': 623219820Sjeff ib_port = strtol(optarg, NULL, 0); 624331769Shselasky if (ib_port <= 0) { 625219820Sjeff usage(argv[0]); 626219820Sjeff return 1; 627219820Sjeff } 628219820Sjeff break; 629219820Sjeff 630219820Sjeff case 'v': 631219820Sjeff verbose = 1; 632219820Sjeff break; 633219820Sjeff 634219820Sjeff case 'l': 635219820Sjeff dev_list = orig_dev_list = ibv_get_device_list(&num_of_hcas); 636219820Sjeff if (!dev_list) { 637219820Sjeff perror("Failed to get IB devices list"); 638219820Sjeff return -1; 639219820Sjeff } 640219820Sjeff 641219820Sjeff printf("%d HCA%s found:\n", num_of_hcas, 642219820Sjeff num_of_hcas != 1 ? "s" : ""); 643219820Sjeff 644219820Sjeff while (*dev_list) { 645219820Sjeff printf("\t%s\n", ibv_get_device_name(*dev_list)); 646219820Sjeff ++dev_list; 647219820Sjeff } 648219820Sjeff 649219820Sjeff printf("\n"); 650219820Sjeff 651219820Sjeff ibv_free_device_list(orig_dev_list); 652219820Sjeff 653219820Sjeff return 0; 654219820Sjeff 655219820Sjeff default: 656219820Sjeff usage(argv[0]); 657219820Sjeff return -1; 658219820Sjeff } 659219820Sjeff } 660219820Sjeff 661219820Sjeff dev_list = orig_dev_list = ibv_get_device_list(NULL); 662219820Sjeff if (!dev_list) { 663219820Sjeff perror("Failed to get IB devices list"); 664219820Sjeff return -1; 665219820Sjeff } 666219820Sjeff 667219820Sjeff if (ib_devname) { 668219820Sjeff while (*dev_list) { 669219820Sjeff if (!strcmp(ibv_get_device_name(*dev_list), ib_devname)) 670219820Sjeff break; 671219820Sjeff ++dev_list; 672219820Sjeff } 673219820Sjeff 674219820Sjeff if (!*dev_list) { 675219820Sjeff fprintf(stderr, "IB device '%s' wasn't found\n", ib_devname); 676219820Sjeff return -1; 677219820Sjeff } 678219820Sjeff 679219820Sjeff ret |= print_hca_cap(*dev_list, ib_port); 680219820Sjeff } else { 681219820Sjeff if (!*dev_list) { 682219820Sjeff fprintf(stderr, "No IB devices found\n"); 683219820Sjeff return -1; 684219820Sjeff } 685219820Sjeff 686219820Sjeff while (*dev_list) { 687219820Sjeff ret |= print_hca_cap(*dev_list, ib_port); 688219820Sjeff ++dev_list; 689219820Sjeff } 690219820Sjeff } 691219820Sjeff 692219820Sjeff if (ib_devname) 693219820Sjeff free(ib_devname); 694219820Sjeff 695219820Sjeff ibv_free_device_list(orig_dev_list); 696219820Sjeff 697219820Sjeff return ret; 698219820Sjeff} 699