1 /* 2 * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 */ 32 #define _GNU_SOURCE 33 #include <config.h> 34 35 #include <stdio.h> 36 #include <infiniband/endian.h> 37 #include <getopt.h> 38 #include <string.h> 39 40 #include <infiniband/verbs.h> 41 42 static const char *event_name_str(enum ibv_event_type event_type) 43 { 44 switch (event_type) { 45 case IBV_EVENT_DEVICE_FATAL: 46 return "IBV_EVENT_DEVICE_FATAL"; 47 case IBV_EVENT_PORT_ACTIVE: 48 return "IBV_EVENT_PORT_ACTIVE"; 49 case IBV_EVENT_PORT_ERR: 50 return "IBV_EVENT_PORT_ERR"; 51 case IBV_EVENT_LID_CHANGE: 52 return "IBV_EVENT_LID_CHANGE"; 53 case IBV_EVENT_PKEY_CHANGE: 54 return "IBV_EVENT_PKEY_CHANGE"; 55 case IBV_EVENT_SM_CHANGE: 56 return "IBV_EVENT_SM_CHANGE"; 57 case IBV_EVENT_CLIENT_REREGISTER: 58 return "IBV_EVENT_CLIENT_REREGISTER"; 59 case IBV_EVENT_GID_CHANGE: 60 return "IBV_EVENT_GID_CHANGE"; 61 62 case IBV_EVENT_CQ_ERR: 63 case IBV_EVENT_QP_FATAL: 64 case IBV_EVENT_QP_REQ_ERR: 65 case IBV_EVENT_QP_ACCESS_ERR: 66 case IBV_EVENT_COMM_EST: 67 case IBV_EVENT_SQ_DRAINED: 68 case IBV_EVENT_PATH_MIG: 69 case IBV_EVENT_PATH_MIG_ERR: 70 case IBV_EVENT_SRQ_ERR: 71 case IBV_EVENT_SRQ_LIMIT_REACHED: 72 case IBV_EVENT_QP_LAST_WQE_REACHED: 73 default: 74 return "unexpected"; 75 } 76 } 77 78 static void usage(const char *argv0) 79 { 80 printf("Usage:\n"); 81 printf(" %s start an asyncwatch process\n", argv0); 82 printf("\n"); 83 printf("Options:\n"); 84 printf(" -d, --ib-dev=<dev> use IB device <dev> (default first device found)\n"); 85 printf(" -h, --help print a help text and exit\n"); 86 } 87 88 int main(int argc, char *argv[]) 89 { 90 struct ibv_device **dev_list; 91 struct ibv_context *context; 92 struct ibv_async_event event; 93 char *ib_devname = NULL; 94 int i = 0; 95 96 /* Force line-buffering in case stdout is redirected */ 97 setvbuf(stdout, NULL, _IOLBF, 0); 98 99 while (1) { 100 int ret = 1; 101 int c; 102 static struct option long_options[] = { 103 { .name = "ib-dev", .has_arg = 1, .val = 'd' }, 104 { .name = "help", .has_arg = 0, .val = 'h' }, 105 {} 106 }; 107 108 c = getopt_long(argc, argv, "d:h", long_options, NULL); 109 if (c == -1) 110 break; 111 switch (c) { 112 case 'd': 113 ib_devname = strdupa(optarg); 114 break; 115 case 'h': 116 ret = 0; 117 SWITCH_FALLTHROUGH; 118 default: 119 usage(argv[0]); 120 return ret; 121 } 122 } 123 dev_list = ibv_get_device_list(NULL); 124 if (!dev_list) { 125 perror("Failed to get IB devices list"); 126 return 1; 127 } 128 if (ib_devname) { 129 for (; dev_list[i]; ++i) { 130 if (!strcmp(ibv_get_device_name(dev_list[i]), ib_devname)) 131 break; 132 } 133 } 134 135 if (!dev_list[i]) { 136 fprintf(stderr, "IB device %s not found\n", 137 ib_devname ? ib_devname : ""); 138 return 1; 139 } 140 141 context = ibv_open_device(dev_list[i]); 142 if (!context) { 143 fprintf(stderr, "Couldn't get context for %s\n", 144 ibv_get_device_name(dev_list[i])); 145 return 1; 146 } 147 148 printf("%s: async event FD %d\n", 149 ibv_get_device_name(dev_list[i]), context->async_fd); 150 151 while (1) { 152 if (ibv_get_async_event(context, &event)) 153 return 1; 154 155 printf(" event_type %s (%d), port %d\n", 156 event_name_str(event.event_type), 157 event.event_type, event.element.port_num); 158 159 ibv_ack_async_event(&event); 160 } 161 162 return 0; 163 } 164