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