xref: /spdk/examples/vmd/led/led.c (revision c6c1234de9e0015e670dd0b51bf6ce39ee0e07bd)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2019 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/stdinc.h"
7 #include "spdk/log.h"
8 #include "spdk/likely.h"
9 #include "spdk/env.h"
10 #include "spdk/vmd.h"
11 
12 int g_status;
13 
14 enum app_action {
15 	APP_ACTION_SET,
16 	APP_ACTION_GET,
17 	APP_ACTION_NOP,
18 };
19 
20 struct app_opts {
21 	const char		*app_name;
22 	struct spdk_pci_addr	pci_addr;
23 	bool			all_devices;
24 	enum app_action		action;
25 	enum spdk_vmd_led_state	led_state;
26 };
27 
28 struct app_opts g_opts = {
29 	.all_devices = true,
30 	.action = APP_ACTION_GET,
31 	.led_state = SPDK_VMD_LED_STATE_UNKNOWN,
32 };
33 
34 static const char *g_led_states[] = {
35 	[SPDK_VMD_LED_STATE_OFF]	= "off",
36 	[SPDK_VMD_LED_STATE_IDENTIFY]	= "identify",
37 	[SPDK_VMD_LED_STATE_FAULT]	= "fault",
38 	[SPDK_VMD_LED_STATE_REBUILD]	= "rebuild",
39 	[SPDK_VMD_LED_STATE_UNKNOWN]	= "unknown",
40 };
41 
42 static void
43 usage(void)
44 {
45 	printf("Usage: %s [-d] [-s STATE] [-r TRADDR]\n", g_opts.app_name);
46 	printf("\n");
47 	printf("Options:\n");
48 	printf("	-d		enables debug logs from the VMD module\n");
49 	printf("	-s STATE	sets the state of the LEDs. Available states are:\n");
50 	printf("			off, identify, fault, rebuild\n");
51 	printf("	-r TRADDR	uses device identified by TRADDR\n");
52 	printf("	-h		shows this help\n");
53 }
54 
55 static int
56 parse_args(int argc, char **argv)
57 {
58 	int led_state;
59 	int op;
60 
61 	g_opts.app_name = argv[0];
62 
63 	while ((op = getopt(argc, argv, "dhr:s:")) != -1) {
64 		switch (op) {
65 		case 'r':
66 			if (spdk_pci_addr_parse(&g_opts.pci_addr, optarg)) {
67 				fprintf(stderr, "Unable to parse PCI address: %s\n", optarg);
68 				return -EINVAL;
69 			}
70 
71 			g_opts.all_devices = false;
72 			break;
73 
74 		case 'd':
75 #ifdef DEBUG
76 			spdk_log_set_print_level(SPDK_LOG_DEBUG);
77 			spdk_log_set_flag("vmd");
78 			break;
79 #else
80 			fprintf(stderr, "%s must be rebuilt with --enable-debug for the -d flag\n",
81 				argv[0]);
82 			return -EINVAL;
83 #endif
84 		case 's':
85 			for (led_state = SPDK_VMD_LED_STATE_OFF;
86 			     led_state <= SPDK_VMD_LED_STATE_REBUILD;
87 			     led_state++) {
88 				if (strcmp(optarg, g_led_states[led_state]) == 0) {
89 					g_opts.led_state = (enum spdk_vmd_led_state)led_state;
90 					break;
91 				}
92 			}
93 
94 			if (g_opts.led_state == SPDK_VMD_LED_STATE_UNKNOWN) {
95 				fprintf(stderr, "Invalid LED state\n");
96 				return -EINVAL;
97 			}
98 
99 			g_opts.action = APP_ACTION_SET;
100 			break;
101 
102 		case 'h':
103 			g_opts.action = APP_ACTION_NOP;
104 			usage();
105 			break;
106 
107 		default:
108 			return -EINVAL;
109 		}
110 	}
111 
112 	return 0;
113 }
114 
115 static void
116 led_device_action(void *ctx, struct spdk_pci_device *pci_device)
117 {
118 	enum spdk_vmd_led_state led_state;
119 	char addr_buf[128];
120 	int rc;
121 
122 	if (strcmp(spdk_pci_device_get_type(pci_device), "vmd") != 0) {
123 		return;
124 	}
125 
126 	if (!g_opts.all_devices &&
127 	    spdk_pci_addr_compare(&g_opts.pci_addr, &pci_device->addr) != 0) {
128 		return;
129 	}
130 
131 	rc = spdk_pci_addr_fmt(addr_buf, sizeof(addr_buf), &pci_device->addr);
132 	if (rc != 0) {
133 		fprintf(stderr, "Failed to format VMD's PCI address\n");
134 		g_status = 1;
135 		return;
136 	}
137 
138 	if (g_opts.action == APP_ACTION_GET) {
139 		rc = spdk_vmd_get_led_state(pci_device, &led_state);
140 		if (spdk_unlikely(rc != 0)) {
141 			fprintf(stderr, "Failed to retrieve the state of the LED on %s\n",
142 				addr_buf);
143 			g_status = 1;
144 			return;
145 		}
146 
147 		printf("%s: %s\n", addr_buf, g_led_states[led_state]);
148 	} else {
149 		rc = spdk_vmd_set_led_state(pci_device, g_opts.led_state);
150 		if (spdk_unlikely(rc != 0)) {
151 			fprintf(stderr, "Failed to set LED state on %s\n", addr_buf);
152 			g_status = 1;
153 			return;
154 		}
155 	}
156 }
157 
158 int
159 main(int argc, char **argv)
160 {
161 	struct spdk_env_opts opts;
162 	int rc;
163 
164 	if (parse_args(argc, argv) != 0) {
165 		usage();
166 		return 1;
167 	}
168 
169 	if (g_opts.action == APP_ACTION_NOP) {
170 		return 0;
171 	}
172 
173 	opts.opts_size = sizeof(opts);
174 	spdk_env_opts_init(&opts);
175 	opts.name = "led";
176 
177 	if (spdk_env_init(&opts) < 0) {
178 		fprintf(stderr, "Unable to initialize SPDK environment\n");
179 		return 1;
180 	}
181 
182 	rc = spdk_vmd_init();
183 	if (rc) {
184 		fprintf(stderr, "Unable to initialize VMD subsystem\n");
185 		spdk_env_fini();
186 		return 1;
187 	}
188 
189 	spdk_pci_for_each_device(NULL, led_device_action);
190 
191 	spdk_vmd_fini();
192 
193 	spdk_env_fini();
194 	return g_status;
195 }
196