1219820Sjeff/*
2219820Sjeff * Copyright (c) 2005 Topspin Communications.  All rights reserved.
3219820Sjeff *
4219820Sjeff * This software is available to you under a choice of one of two
5219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
6219820Sjeff * General Public License (GPL) Version 2, available from the file
7219820Sjeff * COPYING in the main directory of this source tree, or the
8219820Sjeff * OpenIB.org BSD license below:
9219820Sjeff *
10219820Sjeff *     Redistribution and use in source and binary forms, with or
11219820Sjeff *     without modification, are permitted provided that the following
12219820Sjeff *     conditions are met:
13219820Sjeff *
14219820Sjeff *      - Redistributions of source code must retain the above
15219820Sjeff *        copyright notice, this list of conditions and the following
16219820Sjeff *        disclaimer.
17219820Sjeff *
18219820Sjeff *      - Redistributions in binary form must reproduce the above
19219820Sjeff *        copyright notice, this list of conditions and the following
20219820Sjeff *        disclaimer in the documentation and/or other materials
21219820Sjeff *        provided with the distribution.
22219820Sjeff *
23219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30219820Sjeff * SOFTWARE.
31219820Sjeff */
32331769Shselasky#define _GNU_SOURCE
33331769Shselasky#include <config.h>
34219820Sjeff
35219820Sjeff#include <stdio.h>
36331769Shselasky#include <infiniband/endian.h>
37331769Shselasky#include <getopt.h>
38331769Shselasky#include <string.h>
39219820Sjeff
40219820Sjeff#include <infiniband/verbs.h>
41219820Sjeff
42219820Sjeffstatic const char *event_name_str(enum ibv_event_type event_type)
43219820Sjeff{
44219820Sjeff	switch (event_type) {
45219820Sjeff	case IBV_EVENT_DEVICE_FATAL:
46219820Sjeff		return "IBV_EVENT_DEVICE_FATAL";
47219820Sjeff	case IBV_EVENT_PORT_ACTIVE:
48219820Sjeff		return "IBV_EVENT_PORT_ACTIVE";
49219820Sjeff	case IBV_EVENT_PORT_ERR:
50219820Sjeff		return "IBV_EVENT_PORT_ERR";
51219820Sjeff	case IBV_EVENT_LID_CHANGE:
52219820Sjeff		return "IBV_EVENT_LID_CHANGE";
53219820Sjeff	case IBV_EVENT_PKEY_CHANGE:
54219820Sjeff		return "IBV_EVENT_PKEY_CHANGE";
55219820Sjeff	case IBV_EVENT_SM_CHANGE:
56219820Sjeff		return "IBV_EVENT_SM_CHANGE";
57219820Sjeff	case IBV_EVENT_CLIENT_REREGISTER:
58219820Sjeff		return "IBV_EVENT_CLIENT_REREGISTER";
59219820Sjeff	case IBV_EVENT_GID_CHANGE:
60219820Sjeff		return "IBV_EVENT_GID_CHANGE";
61219820Sjeff
62219820Sjeff	case IBV_EVENT_CQ_ERR:
63219820Sjeff	case IBV_EVENT_QP_FATAL:
64219820Sjeff	case IBV_EVENT_QP_REQ_ERR:
65219820Sjeff	case IBV_EVENT_QP_ACCESS_ERR:
66219820Sjeff	case IBV_EVENT_COMM_EST:
67219820Sjeff	case IBV_EVENT_SQ_DRAINED:
68219820Sjeff	case IBV_EVENT_PATH_MIG:
69219820Sjeff	case IBV_EVENT_PATH_MIG_ERR:
70219820Sjeff	case IBV_EVENT_SRQ_ERR:
71219820Sjeff	case IBV_EVENT_SRQ_LIMIT_REACHED:
72219820Sjeff	case IBV_EVENT_QP_LAST_WQE_REACHED:
73219820Sjeff	default:
74219820Sjeff		return "unexpected";
75219820Sjeff	}
76219820Sjeff}
77219820Sjeff
78331769Shselaskystatic void usage(const char *argv0)
79331769Shselasky{
80331769Shselasky	printf("Usage:\n");
81331769Shselasky	printf("  %s            start an asyncwatch process\n", argv0);
82331769Shselasky	printf("\n");
83331769Shselasky	printf("Options:\n");
84331769Shselasky	printf("  -d, --ib-dev=<dev>     use IB device <dev> (default first device found)\n");
85331769Shselasky	printf("  -h, --help             print a help text and exit\n");
86331769Shselasky}
87331769Shselasky
88219820Sjeffint main(int argc, char *argv[])
89219820Sjeff{
90219820Sjeff	struct ibv_device **dev_list;
91219820Sjeff	struct ibv_context *context;
92219820Sjeff	struct ibv_async_event event;
93331769Shselasky	char   *ib_devname = NULL;
94331769Shselasky	int i = 0;
95219820Sjeff
96219820Sjeff	/* Force line-buffering in case stdout is redirected */
97219820Sjeff	setvbuf(stdout, NULL, _IOLBF, 0);
98219820Sjeff
99331769Shselasky	while (1) {
100331769Shselasky		int ret = 1;
101331769Shselasky		int c;
102331769Shselasky		static struct option long_options[] = {
103331769Shselasky			{ .name = "ib-dev",    .has_arg = 1, .val = 'd' },
104331769Shselasky			{ .name = "help",      .has_arg = 0, .val = 'h' },
105331769Shselasky			{}
106331769Shselasky		};
107331769Shselasky
108331769Shselasky		c = getopt_long(argc, argv, "d:h", long_options, NULL);
109331769Shselasky		if (c == -1)
110331769Shselasky			break;
111331769Shselasky		switch (c) {
112331769Shselasky		case 'd':
113331769Shselasky			ib_devname = strdupa(optarg);
114331769Shselasky			break;
115331769Shselasky		case 'h':
116331769Shselasky			ret = 0;
117331769Shselasky			SWITCH_FALLTHROUGH;
118331769Shselasky		default:
119331769Shselasky			usage(argv[0]);
120331769Shselasky			return ret;
121331769Shselasky		}
122331769Shselasky	}
123219820Sjeff	dev_list = ibv_get_device_list(NULL);
124219820Sjeff	if (!dev_list) {
125219820Sjeff		perror("Failed to get IB devices list");
126219820Sjeff		return 1;
127219820Sjeff	}
128331769Shselasky	if (ib_devname) {
129331769Shselasky		for (; dev_list[i]; ++i) {
130331769Shselasky			if (!strcmp(ibv_get_device_name(dev_list[i]), ib_devname))
131331769Shselasky				break;
132331769Shselasky		}
133331769Shselasky	}
134219820Sjeff
135331769Shselasky	if (!dev_list[i]) {
136331769Shselasky		fprintf(stderr, "IB device %s not found\n",
137331769Shselasky			ib_devname ? ib_devname : "");
138219820Sjeff		return 1;
139219820Sjeff	}
140219820Sjeff
141331769Shselasky	context = ibv_open_device(dev_list[i]);
142219820Sjeff	if (!context) {
143219820Sjeff		fprintf(stderr, "Couldn't get context for %s\n",
144331769Shselasky			ibv_get_device_name(dev_list[i]));
145219820Sjeff		return 1;
146219820Sjeff	}
147219820Sjeff
148219820Sjeff	printf("%s: async event FD %d\n",
149331769Shselasky	       ibv_get_device_name(dev_list[i]), context->async_fd);
150219820Sjeff
151219820Sjeff	while (1) {
152219820Sjeff		if (ibv_get_async_event(context, &event))
153219820Sjeff			return 1;
154219820Sjeff
155219820Sjeff		printf("  event_type %s (%d), port %d\n",
156219820Sjeff		       event_name_str(event.event_type),
157219820Sjeff		       event.event_type, event.element.port_num);
158219820Sjeff
159219820Sjeff		ibv_ack_async_event(&event);
160219820Sjeff	}
161219820Sjeff
162219820Sjeff	return 0;
163219820Sjeff}
164