From 559eedb36212f65d9ea6ffafee30cc31467141f76180095a001f61d06b21cafc Mon Sep 17 00:00:00 2001 From: Dirk Mueller Date: Thu, 18 May 2023 11:44:43 +0000 Subject: [PATCH] Accepting request 1087724 from home:nicholasyang:branches:Base:System - Update to version 0.97: Enhancements ledctl: add support to empty slots blinking ledmon license change to LGPLv2 ledctl: Add SES get/set/list slot support Update NPEM wait command Remove exclusionary language ledmon: Define ONESHOT_NORMAL for VMD Bug fixes ipmi: avoid error messages on non-dell platforms vmdssd: define normal pattern ledctl: clear unsupported params from config block.c: get_block_device_from_sysfs_path modification fix ibpi_value lists getter amd_ipmi: Allow to _enable_smbus_control ledmon.c: allocate memory for ignore sysfs: add only vmd devices to slots_list Rename --controller parameter Slots list implementations and fixes - Drop no longer needed patches: * 0001-Ledctl-slots-management-94.patch * 0002-add-Dell-15G-servers.patch * 0003-ipmi-avoid-error-messages-on-non-dell-platforms-112.patch OBS-URL: https://build.opensuse.org/request/show/1087724 OBS-URL: https://build.opensuse.org/package/show/Base:System/ledmon?expand=0&rev=49 --- 0001-Ledctl-slots-management-94.patch | 1365 ----------------- 0002-add-Dell-15G-servers.patch | 56 - ...r-messages-on-non-dell-platforms-112.patch | 26 - ledmon-0.96.tar.gz | 3 - ledmon-0.97.tar.gz | 3 + ledmon.changes | 32 + ledmon.spec | 11 +- 7 files changed, 39 insertions(+), 1457 deletions(-) delete mode 100644 0001-Ledctl-slots-management-94.patch delete mode 100644 0002-add-Dell-15G-servers.patch delete mode 100644 0003-ipmi-avoid-error-messages-on-non-dell-platforms-112.patch delete mode 100644 ledmon-0.96.tar.gz create mode 100644 ledmon-0.97.tar.gz diff --git a/0001-Ledctl-slots-management-94.patch b/0001-Ledctl-slots-management-94.patch deleted file mode 100644 index 56ed475..0000000 --- a/0001-Ledctl-slots-management-94.patch +++ /dev/null @@ -1,1365 +0,0 @@ -From a56e8bf096c04ea0c76ca026e07402f05ce58ca4 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Kinga=20Ta=C5=84ska?= -Date: Tue, 14 Jun 2022 12:11:45 +0200 -Subject: [PATCH 1/2] Ledctl - slots management (#94) - -* ledctl: add commands to support empty slots blinking -* ledctl: --get-slot implementation for vmd -* ledctl: --list-slots implementation for vmd -* ledctl: --set-slot implementation for vmd -* ledctl: --get-slot implementation for npem -* ledctl: --list-slots implementation for npem -* ledctl: --set-slot implementation for npem - -Add new interface which allows to read or modify led state for devices -by controller's slots. It allows to manage empty slots in cases where: -- drive is not connected. -- drive is connected, but non-standard driver is used (uio, vfio). - -Slot identifier will used to manage led state. Following commands are added: ---get-slot ---list-slots ---set-slot -Support for VMD and NPEM is added. - -Signed-off-by: Kinga Tanska ---- - doc/ledctl.pod | 36 ++++++ - src/Makefile.am | 2 +- - src/block.c | 12 ++ - src/block.h | 15 ++- - src/ledctl.c | 329 ++++++++++++++++++++++++++++++++++++++++++++++-- - src/npem.c | 145 ++++++++++++++++++--- - src/npem.h | 28 +++++ - src/pci_slot.c | 102 ++++++++++++++- - src/pci_slot.h | 35 +++++- - src/slot.h | 63 ++++++++++ - src/sysfs.c | 1 - - src/sysfs.h | 4 +- - src/utils.c | 49 +++++++- - src/utils.h | 15 ++- - src/vmdssd.c | 63 +++++----- - src/vmdssd.h | 11 +- - 16 files changed, 833 insertions(+), 77 deletions(-) - create mode 100644 src/slot.h - -diff --git a/doc/ledctl.pod b/doc/ledctl.pod -index 774d04b2b0e2..a0da95e4c734 100644 ---- a/doc/ledctl.pod -+++ b/doc/ledctl.pod -@@ -324,6 +324,42 @@ Displays version of ledctl and information about the license and exits. - Prints information (system path and type) of all controllers detected by - ledmon and exits. - -+=item B<-P> or B<--list-slots> B<--controller>=I -+ -+Prints all slots for the controller. Slot definition depends on the controller -+and is unique across all controllers of the same type. -+ -+Definitions for supported controllers are described below: -+ -+=over -+ -+=item -+ -+VMD - PCI Express Hot Plug Controller Driver slot number -+ -+=item -+ -+NPEM - PCI Express Downstream Port address -+ -+=back -+ -+Command returns a list of all slots for the controller with current state and -+attached device name (if any). I is type of controller -+(vmd, NPEM) that should be scanned here. -+ -+=item B<-G> or B<--get-slot> B<--controller>=I B<--device>=I -+ -+Displays slot details of given device. I is devnode of selected drive. -+ -+=item B<-G> or B<--get-slot> B<--controller>=I B<--slot>=I -+ -+Displays details of given slot. I is unique slot identifier. -+ -+=item B<-S> or B<--set-slot> B<--controller>=I B<--slot>=I B<--state>=I -+ -+Changes led state for given slot. I is type of the controller. -+I is unique slot identifier. I is led pattern. -+ - =item B<-x> or B<--listed-only> - - With this option ledctl will change state only on devices listed in CLI. The -diff --git a/src/Makefile.am b/src/Makefile.am -index f7786206a510..34311a2699a7 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -26,7 +26,7 @@ COMMON_SRCS = ahci.c block.c cntrl.c config_file.c enclosure.c list.c \ - vmdssd.h ipmi.h amd.h amd_ipmi.h npem.h - - LEDMON_SRCS = ledmon.c pidfile.c $(COMMON_SRCS) --LEDCTL_SRCS = ledctl.c $(COMMON_SRCS) -+LEDCTL_SRCS = ledctl.c slot.h $(COMMON_SRCS) - - - sbin_PROGRAMS = ledmon ledctl -diff --git a/src/block.c b/src/block.c -index c61c577cb2c8..3d1815cb11a3 100644 ---- a/src/block.c -+++ b/src/block.c -@@ -215,6 +215,18 @@ struct _host_type *block_get_host(struct cntrl_device *cntrl, int host_id) - return hosts; - } - -+struct block_device *get_block_device_from_sysfs_path(char *sub_path) -+{ -+ struct block_device *device; -+ -+ list_for_each(sysfs_get_block_devices(), device) { -+ if (strstr(device->sysfs_path, sub_path)) -+ return device; -+ } -+ -+ return NULL; -+} -+ - /* - * Allocates a new block device structure. See block.h for details. - */ -diff --git a/src/block.h b/src/block.h -index 820f2d72325e..00b9fd73a19d 100644 ---- a/src/block.h -+++ b/src/block.h -@@ -1,6 +1,6 @@ - /* - * Intel(R) Enclosure LED Utilities -- * Copyright (C) 2009-2018 Intel Corporation. -+ * Copyright (C) 2009-2022 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, -@@ -25,6 +25,7 @@ - #include "time.h" - #include "list.h" - #include "raid.h" -+#include "status.h" - - struct block_device; - -@@ -227,4 +228,16 @@ struct _host_type *block_get_host(struct cntrl_device *cntrl, int host_id); - int block_compare(const struct block_device *bd_old, - const struct block_device *bd_new); - -+/** -+ * @brief Finds block device which name contains sub-path. -+ * -+ * This function scans block devices and checks their sysfs path -+ * to find any which contains PCI address specified for device in path. -+ * -+ * @param[in] sub_path Sub path. -+ * -+ * @return first block device containing sub-path if any, otherwise NULL. -+ */ -+struct block_device *get_block_device_from_sysfs_path(char *sub_path); -+ - #endif /* _BLOCK_H_INCLUDED_ */ -diff --git a/src/ledctl.c b/src/ledctl.c -index caedc1a4834d..c20986230739 100644 ---- a/src/ledctl.c -+++ b/src/ledctl.c -@@ -42,12 +42,13 @@ - #include "cntrl.h" - #include "config.h" - #include "config_file.h" --#include "ibpi.h" -+#include "slot.h" - #include "list.h" -+#include "npem.h" -+#include "pci_slot.h" - #include "scsi.h" - #include "status.h" - #include "sysfs.h" --#include "utils.h" - - /** - * @brief An IBPI state structure. -@@ -69,6 +70,73 @@ struct ibpi_state { - */ - static struct list ibpi_list; - -+/** -+ * @brief Pointer to a get slot function. -+ * -+ * The pointer to a function which will print slot details. -+ * -+ * @param[in] device Name of the device. -+ * @param[in] slot Unique identifier of the slot. -+ * @param[in] res Pointer to slot response. -+ * -+ * @return STATUS_SUCCESS if successful, otherwise a valid status_t status code. -+ */ -+typedef status_t (*get_slot_t) (char *device, char *slot, struct slot_response *res); -+ -+/** -+ * @brief Pointer to a set slot function. -+ * -+ * The pointer to a function which will set slot details. -+ * -+ * @param[in] slot Unique identifier of the slot. -+ * @param[in] state IBPI state based on slot request. -+ * -+ * @return STATUS_SUCCESS if successful, otherwise a valid status_t status code. -+ */ -+typedef status_t (*set_slot_t) (char *slot, enum ibpi_pattern state); -+ -+/** -+ * @brief slot request parametres -+ * -+ * This structure contains all possible parameters for slot related commands. -+ */ -+struct slot_request { -+ /** -+ * Option given in the request. -+ */ -+ int chosen_opt; -+ -+ /** -+ * Name of the device. -+ */ -+ char device[PATH_MAX]; -+ -+ /** -+ * Unique slot identifier. -+ */ -+ char slot[PATH_MAX]; -+ -+ /** -+ * Type of the controller. -+ */ -+ enum cntrl_type cntrl; -+ -+ /** -+ * IBPI state. -+ */ -+ enum ibpi_pattern state; -+ -+ /** -+ * Pointer to the get slot function. -+ */ -+ get_slot_t get_slot_fn; -+ -+ /** -+ * Pointer to the set slot function. -+ */ -+ set_slot_t set_slot_fn; -+}; -+ - /** - * @brief IBPI pattern names. - * -@@ -76,7 +144,7 @@ static struct list ibpi_list; - * this entries to translate enumeration type values into the string. - */ - const char *ibpi_str[] = { -- [IBPI_PATTERN_UNKNOWN] = "", -+ [IBPI_PATTERN_UNKNOWN] = "UNKNOWN", - [IBPI_PATTERN_NORMAL] = "NORMAL", - [IBPI_PATTERN_ONESHOT_NORMAL] = "", - [IBPI_PATTERN_DEGRADED] = "ICA", -@@ -112,6 +180,13 @@ static int possible_params[] = { - OPT_VERSION, - OPT_LIST_CTRL, - OPT_LISTED_ONLY, -+ OPT_LIST_SLOTS, -+ OPT_GET_SLOT, -+ OPT_SET_SLOT, -+ OPT_CONTROLLER, -+ OPT_DEVICE, -+ OPT_SLOT, -+ OPT_STATE, - OPT_ALL, - OPT_DEBUG, - OPT_ERROR, -@@ -126,6 +201,43 @@ static const int possible_params_size = sizeof(possible_params) - - static int listed_only; - -+enum cntrl_type get_cntrl_type(const char *cntrl) -+{ -+ if (strcasecmp(cntrl, "vmd") == 0) -+ return CNTRL_TYPE_VMD; -+ else if (strcasecmp(cntrl, "npem") == 0) -+ return CNTRL_TYPE_NPEM; -+ return CNTRL_TYPE_UNKNOWN; -+} -+ -+/** -+ * @brief Determines a slot functions based on controller. -+ * -+ * This function determines slot functions based on -+ * controller type. -+ * -+ * @param[in] ctrl_type Controller type. -+ * @param[in] slot_req Pointer to the slot request. -+ * -+ * @return This function does not return a value. -+ */ -+static void _get_slot_ctrl_fn(enum cntrl_type ctrl_type, struct slot_request *slot_req) -+{ -+ switch (ctrl_type) { -+ case CNTRL_TYPE_VMD: -+ slot_req->get_slot_fn = pci_get_slot; -+ slot_req->set_slot_fn = pci_set_slot; -+ break; -+ case CNTRL_TYPE_NPEM: -+ slot_req->get_slot_fn = npem_get_slot; -+ slot_req->set_slot_fn = npem_set_slot; -+ break; -+ default: -+ log_debug("Slot functions could not be set because the controller type %s does not " -+ "support slots managing.", ctrl_type); -+ } -+} -+ - static void ibpi_state_fini(struct ibpi_state *p) - { - list_clear(&p->block_list); -@@ -186,16 +298,25 @@ static void _ledctl_help(void) - progname); - printf("Mandatory arguments for long options are mandatory for short options, too.\n\n"); - print_opt("--listed-only", "-x", -- "Ledctl will change state only for given devices."); -+ "Ledctl will change state only for given devices."); - print_opt("--list-controllers", "-L", -- "Displays list of controllers detected by ledmon."); -+ "Displays list of controllers detected by ledmon."); -+ print_opt("--list-slots --controller CONTROLLER", "-P -c CONTROLLER", -+ "List slots under the controller, their led states, slot numbers and " -+ "devnodes connected."); -+ print_opt("--get-slot --controller CONTROLLER --device DEVNODE / --slot SLOT", -+ "-G -c CONTROLLER -d DEVNODE / -p SLOT", -+ "Prints slot information, its led state, slot number and devnode."); -+ print_opt("--set-slot --controller CONTROLLER --slot SLOT --state STATE", -+ "-S -c CONTROLLER -p SLOT -s STATE", "Sets given state for chosen slot " -+ "under the controller."); - print_opt("--log=PATH", "-l PATH", -- "Use local log file instead /var/log/ledctl.log."); -+ "Use local log file instead /var/log/ledctl.log."); - print_opt("--help", "-h", "Displays this help text."); - print_opt("--version", "-v", -- "Displays version and license information."); -+ "Displays version and license information."); - print_opt("--log-level=VALUE", "-l VALUE", -- "Allows user to set ledctl verbose level in logs."); -+ "Allows user to set ledctl verbose level in logs."); - printf("\nPatterns:\n" - "\tCommon patterns are:\n" - "\t\tlocate, locate_off, normal, off, degraded, rebuild,\n" "" -@@ -555,6 +676,156 @@ static status_t _cmdline_parse_non_root(int argc, char *argv[]) - return status; - } - -+/** -+ * @brief Inits slot request structure with initial values. -+ * -+ * @param[in] slot_req structure with slot request -+ * -+ * @return This function does not return a value. -+ */ -+static void slot_request_init(struct slot_request *slot_req) -+{ -+ memset(slot_req, 0, sizeof(struct slot_request)); -+ -+ slot_req->chosen_opt = OPT_NULL_ELEMENT; -+ slot_req->state = IBPI_PATTERN_UNKNOWN; -+} -+ -+/** -+ * @brief Inits slot response structure with initial values. -+ * -+ * @param[in] slot_res structure with slot response -+ * -+ * @return This function does not return a value. -+ */ -+static void slot_response_init(struct slot_response *slot_res) -+{ -+ memset(slot_res, 0, sizeof(struct slot_response)); -+ -+ slot_res->state = IBPI_PATTERN_UNKNOWN; -+} -+ -+/** -+ * @brief Verifies slot request parameters. -+ * -+ * @param[in] slot_req structure with slot request -+ * -+ * @return STATUS_SUCCESS if successful, otherwise a valid status_t status code. -+ */ -+static status_t slot_verify_request(struct slot_request *slot_req) -+{ -+ if (slot_req->cntrl == CNTRL_TYPE_UNKNOWN) { -+ log_error("Invalid controller in the request."); -+ return STATUS_INVALID_CONTROLLER; -+ } -+ if (slot_req->chosen_opt == OPT_SET_SLOT && slot_req->state == IBPI_PATTERN_UNKNOWN) { -+ log_error("Invalid IBPI state in the request."); -+ return STATUS_INVALID_STATE; -+ } -+ if (!slot_req->get_slot_fn && !slot_req->set_slot_fn) { -+ log_error("The controller type %s doesn't support slot functionality.", -+ slot_req->cntrl); -+ return STATUS_INVALID_CONTROLLER; -+ } -+ if (slot_req->device[0] && slot_req->slot[0]) { -+ log_error("Device and slot parameters are exclusive."); -+ return STATUS_DATA_ERROR; -+ } -+ -+ return STATUS_SUCCESS; -+} -+ -+static status_t get_state_for_slot(char *slot, struct slot_request *slot_req) -+{ -+ struct slot_response slot_res; -+ status_t status = STATUS_SUCCESS; -+ -+ slot_response_init(&slot_res); -+ status = slot_req->get_slot_fn(NULL, slot, &slot_res); -+ if (status == STATUS_SUCCESS) -+ print_slot_state(&slot_res); -+ -+ return status; -+} -+ -+/** -+ * @brief List slots connected to given controller -+ * -+ * This function scans all available slots connected to given controller -+ * and prints their led states and names of the connected devices (if exist). -+ * -+ * @param[in] slot_req Structure with slot request. -+ * -+ * @return STATUS_SUCCESS if successful, otherwise a valid status_t status code. -+ */ -+static status_t list_slots(struct slot_request *slot_req) -+{ -+ status_t status = STATUS_SUCCESS; -+ -+ switch (slot_req->cntrl) { -+ case CNTRL_TYPE_VMD: -+ { -+ struct pci_slot *slot; -+ -+ list_for_each(sysfs_get_pci_slots(), slot) -+ status = get_state_for_slot(slot->sysfs_path, slot_req); -+ return status; -+ } -+ case CNTRL_TYPE_NPEM: -+ { -+ struct cntrl_device *ctrl_dev; -+ -+ list_for_each(sysfs_get_cntrl_devices(), ctrl_dev) { -+ if (ctrl_dev->cntrl_type != CNTRL_TYPE_NPEM) -+ continue; -+ status = get_state_for_slot(ctrl_dev->sysfs_path, slot_req); -+ } -+ return status; -+ } -+ default: -+ return STATUS_NOT_SUPPORTED; -+ } -+} -+ -+/** -+ * @brief Executes proper slot mode function. -+ * -+ * @param[in] slot_req Structure with slot request. -+ * -+ * @return STATUS_SUCCESS if successful, otherwise a valid status_t status code. -+ */ -+status_t slot_execute(struct slot_request *slot_req) -+{ -+ struct slot_response slot_res; -+ status_t status = STATUS_SUCCESS; -+ -+ slot_response_init(&slot_res); -+ -+ switch (slot_req->chosen_opt) { -+ case OPT_LIST_SLOTS: -+ return list_slots(slot_req); -+ case OPT_SET_SLOT: -+ status = slot_req->get_slot_fn(slot_req->device, slot_req->slot, &slot_res); -+ if (slot_res.state == slot_req->state) { -+ log_warning("Led state: %s is already set for the slot.", -+ ibpi2str(slot_req->state)); -+ return STATUS_SUCCESS; -+ } -+ if (status != STATUS_SUCCESS) -+ return status; -+ status = slot_req->set_slot_fn(slot_res.slot, slot_req->state); -+ if (status != STATUS_SUCCESS) -+ return status; -+ case OPT_GET_SLOT: -+ status = slot_req->get_slot_fn(slot_req->device, slot_req->slot, &slot_res); -+ if (status == STATUS_SUCCESS) -+ print_slot_state(&slot_res); -+ return status; -+ default: -+ return STATUS_NOT_SUPPORTED; -+ } -+} -+ - /** - * @brief Command line parser - options. - * -@@ -567,7 +838,7 @@ static status_t _cmdline_parse_non_root(int argc, char *argv[]) - * - * @return STATUS_SUCCESS if successful, otherwise a valid status_t status code. - */ --static status_t _cmdline_parse(int argc, char *argv[]) -+static status_t _cmdline_parse(int argc, char *argv[], struct slot_request *req) - { - int opt, opt_index = -1; - status_t status = STATUS_SUCCESS; -@@ -614,6 +885,34 @@ static status_t _cmdline_parse(int argc, char *argv[]) - sysfs_reset(); - exit(EXIT_SUCCESS); - } -+ case 'G': -+ req->chosen_opt = OPT_GET_SLOT; -+ break; -+ case 'P': -+ req->chosen_opt = OPT_LIST_SLOTS; -+ break; -+ case 'S': -+ req->chosen_opt = OPT_SET_SLOT; -+ break; -+ case 'c': -+ req->cntrl = get_cntrl_type(optarg); -+ _get_slot_ctrl_fn(req->cntrl, req); -+ break; -+ case 's': -+ { -+ struct ibpi_state *state = _ibpi_state_get(optarg); -+ -+ if (state) -+ req->state = state->ibpi; -+ free(state); -+ break; -+ } -+ case 'd': -+ strncpy(req->device, optarg, PATH_MAX - 1); -+ break; -+ case 'p': -+ strncpy(req->slot, optarg, PATH_MAX - 1); -+ break; - case ':': - case '?': - default: -@@ -712,6 +1011,7 @@ static status_t _init_ledctl_conf(void) - int main(int argc, char *argv[]) - { - status_t status; -+ struct slot_request slot_req; - - setup_options(&longopt, &shortopt, possible_params, - possible_params_size); -@@ -732,7 +1032,9 @@ int main(int argc, char *argv[]) - return status; - if (on_exit(_ledctl_fini, progname)) - exit(STATUS_ONEXIT_ERROR); -- if (_cmdline_parse(argc, argv)) -+ slot_request_init(&slot_req); -+ status = _cmdline_parse(argc, argv, &slot_req); -+ if (status != STATUS_SUCCESS) - exit(STATUS_CMDLINE_ERROR); - free(shortopt); - free(longopt); -@@ -746,6 +1048,13 @@ int main(int argc, char *argv[]) - list_init(&ibpi_list, (item_free_t)ibpi_state_fini); - sysfs_init(); - sysfs_scan(); -+ if (slot_req.chosen_opt != OPT_NULL_ELEMENT) { -+ status = slot_verify_request(&slot_req); -+ if (status == STATUS_SUCCESS) -+ return slot_execute(&slot_req); -+ else -+ exit(status); -+ } - status = _cmdline_ibpi_parse(argc, argv); - if (status != STATUS_SUCCESS) { - log_debug("main(): _ibpi_parse() failed (status=%s).", -diff --git a/src/npem.c b/src/npem.c -index 4f836ee8571d..4b08966bd13a 100644 ---- a/src/npem.c -+++ b/src/npem.c -@@ -25,7 +25,9 @@ - - #include "config.h" - #include "cntrl.h" -+#include "list.h" - #include "npem.h" -+#include "sysfs.h" - #include "utils.h" - - #define PCI_EXT_CAP_ID_NPEM 0x29 /* Native PCIe Enclosure Management */ -@@ -57,19 +59,32 @@ - - #define PCI_NPEM_STATUS_CC 0x01 /* NPEM Command Completed */ - --const int ibpi_to_npem_capability[] = { -- [IBPI_PATTERN_NORMAL] = PCI_NPEM_OK_CAP, -- [IBPI_PATTERN_ONESHOT_NORMAL] = PCI_NPEM_OK_CAP, -- [IBPI_PATTERN_DEGRADED] = PCI_NPEM_CRA_CAP, -- [IBPI_PATTERN_HOTSPARE] = PCI_NPEM_HOT_SPARE_CAP, -- [IBPI_PATTERN_REBUILD] = PCI_NPEM_REBUILD_CAP, -- [IBPI_PATTERN_FAILED_ARRAY] = PCI_NPEM_FA_CAP, -- [IBPI_PATTERN_PFA] = PCI_NPEM_PFA_CAP, -- [IBPI_PATTERN_FAILED_DRIVE] = PCI_NPEM_FAIL_CAP, -- [IBPI_PATTERN_LOCATE] = PCI_NPEM_LOCATE_CAP, -- [IBPI_PATTERN_LOCATE_OFF] = PCI_NPEM_OK_CAP, -+const struct ibpi_value ibpi_to_npem_capability[] = { -+ {IBPI_PATTERN_NORMAL, PCI_NPEM_OK_CAP}, -+ {IBPI_PATTERN_ONESHOT_NORMAL, PCI_NPEM_OK_CAP}, -+ {IBPI_PATTERN_DEGRADED, PCI_NPEM_CRA_CAP}, -+ {IBPI_PATTERN_HOTSPARE, PCI_NPEM_HOT_SPARE_CAP}, -+ {IBPI_PATTERN_REBUILD, PCI_NPEM_REBUILD_CAP}, -+ {IBPI_PATTERN_FAILED_ARRAY, PCI_NPEM_FA_CAP}, -+ {IBPI_PATTERN_PFA, PCI_NPEM_PFA_CAP}, -+ {IBPI_PATTERN_FAILED_DRIVE, PCI_NPEM_FAIL_CAP}, -+ {IBPI_PATTERN_LOCATE, PCI_NPEM_LOCATE_CAP}, -+ {IBPI_PATTERN_LOCATE_OFF, PCI_NPEM_OK_CAP}, -+ {IBPI_PATTERN_UNKNOWN} - }; - -+static enum ibpi_pattern npem_capability_to_ibpi(const u32 reg) -+{ -+ const struct ibpi_value *tmp = ibpi_to_npem_capability; -+ -+ while (tmp->ibpi != IBPI_PATTERN_UNKNOWN) { -+ if (reg & tmp->value) -+ break; -+ tmp++; -+ } -+ return tmp->ibpi; -+} -+ - static struct pci_access *get_pci_access() - { - struct pci_access *pacc; -@@ -131,8 +146,10 @@ int is_npem_capable(const char *path) - struct pci_access *pacc = get_pci_access(); - struct pci_dev *pdev; - -- if (!pacc) -+ if (!pacc) { -+ log_error("NPEM: Unable to initialize pci access for %s\n", path); - return 0; -+ } - - pdev = get_pci_dev(pacc, path); - -@@ -215,7 +232,9 @@ int npem_write(struct block_device *device, enum ibpi_pattern ibpi) - } - - reg = read_npem_register(pdev, PCI_NPEM_CAP_REG); -- if ((reg & ibpi_to_npem_capability[ibpi]) == 0) { -+ u32 cap = (u32)get_value_for_ibpi(ibpi, ibpi_to_npem_capability); -+ -+ if ((reg & cap) == 0) { - log_debug("NPEM: Controller %s doesn't support %s pattern\n", - npem_cntrl->sysfs_path, ibpi_str[ibpi]); - ibpi = IBPI_PATTERN_NORMAL; -@@ -223,7 +242,8 @@ int npem_write(struct block_device *device, enum ibpi_pattern ibpi) - - reg = read_npem_register(pdev, PCI_NPEM_CTRL_REG); - val = (reg & PCI_NPEM_RESERVED); -- val = (val | PCI_NPEM_CAP | ibpi_to_npem_capability[ibpi]); -+ cap = (u32)get_value_for_ibpi(ibpi, ibpi_to_npem_capability); -+ val = (val | PCI_NPEM_CAP | cap); - - write_npem_register(pdev, PCI_NPEM_CTRL_REG, val); - if (npem_wait_command(pdev)) { -@@ -244,3 +264,100 @@ char *npem_get_path(const char *cntrl_path) - { - return str_dup(cntrl_path); - } -+ -+status_t npem_get_slot(char *device, char *slot_path, struct slot_response *slot_res) -+{ -+ struct pci_dev *pdev = NULL; -+ struct block_device *block_device = NULL; -+ struct pci_access *pacc = get_pci_access(); -+ status_t status = STATUS_SUCCESS; -+ char *path = NULL; -+ u32 reg; -+ -+ if (!pacc) { -+ log_error("NPEM: Unable to initialize pci access for %s\n", path); -+ return STATUS_NULL_POINTER; -+ } -+ -+ if (device && device[0] != '\0') { -+ block_device = get_block_device_from_sysfs_path(basename(device)); -+ if (block_device) -+ path = block_device->cntrl->sysfs_path; -+ } else if (slot_path && slot_path[0] != '\0') { -+ struct cntrl_device *ctrl_dev; -+ -+ list_for_each(sysfs_get_cntrl_devices(), ctrl_dev) { -+ if (ctrl_dev->cntrl_type != CNTRL_TYPE_NPEM) -+ continue; -+ if (strcmp(basename(ctrl_dev->sysfs_path), basename(slot_path)) != 0) -+ continue; -+ path = ctrl_dev->sysfs_path; -+ block_device = get_block_device_from_sysfs_path(path); -+ break; -+ } -+ } -+ -+ if (path) { -+ pdev = get_pci_dev(pacc, path); -+ } else { -+ log_debug("NPEM: unable to get sysfs path for the controller."); -+ pci_cleanup(pacc); -+ return STATUS_INVALID_PATH; -+ } -+ -+ if (!pdev) { -+ log_error("NPEM: Unable to get pci device for %s\n", path); -+ pci_cleanup(pacc); -+ return STATUS_NULL_POINTER; -+ } -+ -+ reg = read_npem_register(pdev, PCI_NPEM_CTRL_REG); -+ slot_res->state = npem_capability_to_ibpi(reg); -+ snprintf(slot_res->slot, PATH_MAX, "%s", path); -+ -+ if (block_device) -+ snprintf(slot_res->device, PATH_MAX, "/dev/%s", basename(block_device->sysfs_path)); -+ else -+ snprintf(slot_res->device, PATH_MAX, "(empty)"); -+ -+ pci_free_dev(pdev); -+ pci_cleanup(pacc); -+ return status; -+} -+ -+status_t npem_set_slot(char *slot_path, enum ibpi_pattern state) -+{ -+ struct pci_dev *pdev = NULL; -+ struct pci_access *pacc = get_pci_access(); -+ status_t status = STATUS_SUCCESS; -+ u32 val; -+ u32 reg; -+ u32 cap; -+ -+ if (!pacc) { -+ log_error("NPEM: Unable to initialize pci access for %s\n", slot_path); -+ return STATUS_NULL_POINTER; -+ } -+ -+ pdev = get_pci_dev(pacc, slot_path); -+ if (!pdev) { -+ log_error("NPEM: Unable to get pci device for %s\n", slot_path); -+ pci_cleanup(pacc); -+ return STATUS_NULL_POINTER; -+ } -+ -+ reg = read_npem_register(pdev, PCI_NPEM_CTRL_REG); -+ val = (reg & PCI_NPEM_RESERVED); -+ cap = (u32)get_value_for_ibpi(state, ibpi_to_npem_capability); -+ val = (val | PCI_NPEM_CAP | cap); -+ -+ write_npem_register(pdev, PCI_NPEM_CTRL_REG, val); -+ if (npem_wait_command(pdev)) { -+ log_error("NPEM: Write timeout for %s\n", slot_path); -+ status = STATUS_FILE_WRITE_ERROR; -+ } -+ -+ pci_free_dev(pdev); -+ pci_cleanup(pacc); -+ return status; -+} -diff --git a/src/npem.h b/src/npem.h -index 5fa3f11d0ba3..8f4dd7b96151 100644 ---- a/src/npem.h -+++ b/src/npem.h -@@ -21,9 +21,37 @@ - #define NPEM_H_INCLUDED_ - #include "block.h" - #include "ibpi.h" -+#include "slot.h" -+#include "status.h" - - int is_npem_capable(const char *path); - int npem_write(struct block_device *device, enum ibpi_pattern ibpi); - char *npem_get_path(const char *cntrl_path); - -+/** -+ * @brief Gets led state for slot. -+ * -+ * This function finds slot connected to given identifier -+ * and fills slot response related to the slot. -+ * -+ * @param[in] device Requested device name. -+ * @param[in] slot_num Requested identifier of the slot. -+ * @param[in] slot_res Pointer to the slot response. -+ * -+ * @return STATUS_SUCCESS if successful, otherwise a valid status_t status code. -+ */ -+status_t npem_get_slot(char *device, char *slot_num, struct slot_response *slot_res); -+ -+/** -+ * @brief Sets led state for slot. -+ * -+ * This function finds slot connected to given number or device name -+ * and set given led state. -+ * -+ * @param[in] slot_num Requested number of the slot. -+ * @param[in] state IBPI state based on slot request. -+ * -+ * @return STATUS_SUCCESS if successful, otherwise a valid status_t status code. -+ */ -+status_t npem_set_slot(char *slot_num, enum ibpi_pattern state); - #endif // NPEM_H_INCLUDED_ -diff --git a/src/pci_slot.c b/src/pci_slot.c -index b15e1947c043..1e03dbabe91d 100644 ---- a/src/pci_slot.c -+++ b/src/pci_slot.c -@@ -29,7 +29,9 @@ - - #include "config.h" - #include "pci_slot.h" -+#include "sysfs.h" - #include "utils.h" -+#include "vmdssd.h" - - /* - * Allocates memory for PCI hotplug slot structure and initializes fields of -@@ -44,12 +46,6 @@ struct pci_slot *pci_slot_init(const char *path) - return NULL; - result->sysfs_path = str_dup(path); - result->address = get_text(path, "address"); -- result->attention = get_int(path, -1, "attention"); -- -- if (result->attention == -1) { -- pci_slot_fini(result); -- return NULL; -- } - - return result; - } -@@ -66,3 +62,97 @@ void pci_slot_fini(struct pci_slot *slot) - free(slot); - } - } -+ -+/** -+ * @brief Finds PCI slot by number of the slot. -+ * -+ * @param[in] slot_number Number of the slot -+ * -+ * @return Struct with pci slot if successful, otherwise the function returns NULL pointer. -+ */ -+static struct pci_slot *find_pci_slot_by_number(char *slot_number) -+{ -+ struct pci_slot *slot = NULL; -+ char *temp; -+ -+ if (slot_number == NULL) -+ return NULL; -+ -+ list_for_each(sysfs_get_pci_slots(), slot) { -+ temp = basename(slot->sysfs_path); -+ if (temp && strncmp(temp, slot_number, PATH_MAX) == 0) -+ return slot; -+ } -+ return NULL; -+} -+ -+/** -+ * @brief Sets the slot response. -+ * -+ * @param[in] slot Struct with PCI slot parameters. -+ * -+ * @return STATUS_SUCCESS if successful, otherwise a valid status_t status code. -+ */ -+static status_t set_slot_response(struct pci_slot *slot, struct slot_response *slot_res) -+{ -+ struct block_device *bl_device; -+ status_t status = STATUS_SUCCESS; -+ int attention = get_int(slot->sysfs_path, -1, "attention"); -+ -+ if (attention == -1) -+ return STATUS_INVALID_STATE; -+ -+ slot_res->state = get_ibpi_for_value(attention, ibpi_to_attention); -+ snprintf(slot_res->slot, PATH_MAX, "%s", basename(slot->sysfs_path)); -+ -+ bl_device = get_block_device_from_sysfs_path(slot->address); -+ if (bl_device) -+ snprintf(slot_res->device, PATH_MAX, "/dev/%s", basename(bl_device->sysfs_path)); -+ else -+ snprintf(slot_res->device, PATH_MAX, "(empty)"); -+ -+ return status; -+} -+ -+status_t pci_get_slot(char *device, char *slot_path, struct slot_response *slot_res) -+{ -+ struct pci_slot *slot = NULL; -+ struct block_device *block_device = NULL; -+ -+ if (device && device[0] != '\0') { -+ char *sub_path = basename(device); -+ if (sub_path == NULL) { -+ log_error("Device name %s is invalid.", device); -+ return STATUS_DATA_ERROR; -+ } -+ -+ block_device = get_block_device_from_sysfs_path(sub_path + 1); -+ if (block_device == NULL) { -+ log_error("Device %s not found.", device); -+ return STATUS_DATA_ERROR; -+ } -+ slot = vmdssd_find_pci_slot(block_device->sysfs_path); -+ } else if (slot_path && slot_path[0] != '\0') { -+ slot = find_pci_slot_by_number(basename(slot_path)); -+ } -+ -+ if (slot == NULL) { -+ log_error("Specified slot was not found."); -+ return STATUS_DATA_ERROR; -+ } -+ -+ return set_slot_response(slot, slot_res); -+} -+ -+status_t pci_set_slot(char *slot_path, enum ibpi_pattern state) -+{ -+ struct pci_slot *slot = NULL; -+ -+ slot = find_pci_slot_by_number(basename(slot_path)); -+ if (slot == NULL) { -+ log_error("Slot %s not found.", slot_path); -+ return STATUS_NULL_POINTER; -+ } -+ -+ return vmdssd_write_attention_buf(slot, state); -+} -diff --git a/src/pci_slot.h b/src/pci_slot.h -index b971de3d89b7..9a181ce6057e 100644 ---- a/src/pci_slot.h -+++ b/src/pci_slot.h -@@ -20,6 +20,10 @@ - #ifndef PCI_SLOT_H_INCLUDED_ - #define PCI_SLOT_H_INCLUDED_ - -+#include "ibpi.h" -+#include "slot.h" -+#include "status.h" -+ - /** - * @brief PCI hotplug slot structure. - * -@@ -35,11 +39,6 @@ struct pci_slot { - * PCI hotplug slot address. - */ - char *address; -- -- /** -- * State of the Amber LED of the PCI slot. -- */ -- int attention; - }; - - /** -@@ -69,4 +68,30 @@ struct pci_slot *pci_slot_init(const char *path); - */ - void pci_slot_fini(struct pci_slot *slot); - -+/** -+ * @brief Gets led state for slot. -+ * -+ * This function finds slot connected to given identifier -+ * and fills slot response related to the slot. -+ * -+ * @param[in] device Requested device name. -+ * @param[in] slot_num Requested identifier of the slot. -+ * @param[in] slot_res Pointer to the slot response. -+ * -+ * @return STATUS_SUCCESS if successful, otherwise a valid status_t status code. -+ */ -+status_t pci_get_slot(char *device, char *slot_num, struct slot_response *slot_res); -+ -+/** -+ * @brief Sets led state for slot. -+ * -+ * This function finds slot connected to given number or device name -+ * and set given led state. -+ * -+ * @param[in] slot_num Requested number of the slot. -+ * @param[in] state IBPI state based on slot request. -+ * -+ * @return STATUS_SUCCESS if successful, otherwise a valid status_t status code. -+ */ -+status_t pci_set_slot(char *slot_num, enum ibpi_pattern state); - #endif // PCI_SLOT_H_INCLUDED_ -diff --git a/src/slot.h b/src/slot.h -new file mode 100644 -index 000000000000..82b2e9405b89 ---- /dev/null -+++ b/src/slot.h -@@ -0,0 +1,63 @@ -+/* -+ * Intel(R) Enclosure LED Utilities -+ * Copyright (C) 2022-2022 Intel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ */ -+ -+#ifndef SLOT_H_ -+#define SLOT_H_ -+ -+#include -+ -+#include "ibpi.h" -+#include "utils.h" -+ -+/** -+ * @brief slot response parameters -+ * -+ * This structure contains slot properties. -+ */ -+struct slot_response { -+ /** -+ * Name of the device. -+ */ -+ char device[PATH_MAX]; -+ -+ /** -+ * Unique slot identifier. -+ */ -+ char slot[PATH_MAX]; -+ -+ /** -+ * IBPI state. -+ */ -+ enum ibpi_pattern state; -+}; -+ -+/** -+ * @brief Print address, slot identifier and led state. -+ * -+ * @param[in] res Structure with slot response. -+ * -+ * @return This function does not return a value. -+ */ -+static inline void print_slot_state(struct slot_response *res) -+{ -+ printf("slot: %-15s led state: %-15s device: %-15s\n", -+ basename(res->slot), ibpi2str(res->state), res->device); -+} -+ -+#endif // SLOT_H_INCLUDED_ -diff --git a/src/sysfs.c b/src/sysfs.c -index 87e83391f328..f1f9caad05a3 100644 ---- a/src/sysfs.c -+++ b/src/sysfs.c -@@ -48,7 +48,6 @@ - */ - #define SYSFS_CLASS_BLOCK "/sys/block" - #define SYSFS_CLASS_ENCLOSURE "/sys/class/enclosure" --#define SYSFS_PCI_DEVICES "/sys/bus/pci/devices" - #define SYSFS_PCI_SLOTS "/sys/bus/pci/slots" - - /** -diff --git a/src/sysfs.h b/src/sysfs.h -index efebea840cee..ea0109f6aa33 100644 ---- a/src/sysfs.h -+++ b/src/sysfs.h -@@ -1,6 +1,6 @@ - /* - * Intel(R) Enclosure LED Utilities -- * Copyright (C) 2009-2018 Intel Corporation. -+ * Copyright (C) 2009-2022 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, -@@ -22,6 +22,8 @@ - - #include "status.h" - -+#define SYSFS_PCI_DEVICES "/sys/bus/pci/devices" -+ - /** - * @brief Initializes sysfs module. - * -diff --git a/src/utils.c b/src/utils.c -index 7f52194f5d1c..085cdb1d5c2f 100644 ---- a/src/utils.c -+++ b/src/utils.c -@@ -505,7 +505,7 @@ int get_log_fd(void) - - void print_opt(const char *long_opt, const char *short_opt, const char *desc) - { -- printf("%-20s%-10s%s\n", long_opt, short_opt, desc); -+ printf("%-70s%-40s%s\n", long_opt, short_opt, desc); - } - - /** -@@ -581,6 +581,13 @@ struct option longopt_all[] = { - [OPT_LIST_CTRL] = {"list-controllers", no_argument, NULL, 'L'}, - [OPT_LISTED_ONLY] = {"listed-only", no_argument, NULL, 'x'}, - [OPT_FOREGROUND] = {"foreground", no_argument, NULL, '\0'}, -+ [OPT_LIST_SLOTS] = {"list-slots", no_argument, NULL, 'P'}, -+ [OPT_GET_SLOT] = {"get-slot", no_argument, NULL, 'G'}, -+ [OPT_SET_SLOT] = {"set-slot", no_argument, NULL, 'S'}, -+ [OPT_CONTROLLER] = {"controller", required_argument, NULL, 'c'}, -+ [OPT_DEVICE] = {"device", required_argument, NULL, 'd'}, -+ [OPT_SLOT] = {"slot", required_argument, NULL, 'p'}, -+ [OPT_STATE] = {"state", required_argument, NULL, 's'}, - [OPT_NULL_ELEMENT] = {NULL, no_argument, NULL, '\0'} - }; - -@@ -699,3 +706,43 @@ const char *ibpi2str(enum ibpi_pattern ibpi) - - return ret; - } -+ -+/** -+ * @brief Returns value based on IBPI state -+ * -+ * @param[in] value Value for led state. -+ * @param[in] ibpi_values Array with defined IBPI states and values. -+ * -+ * @return Integer value which represents given IBPI state. -+ */ -+int get_value_for_ibpi(enum ibpi_pattern ibpi, const struct ibpi_value ibpi_values[]) -+{ -+ const struct ibpi_value *tmp = ibpi_values; -+ -+ while (tmp->ibpi != IBPI_PATTERN_UNKNOWN) { -+ if (tmp->ibpi == ibpi) -+ break; -+ tmp++; -+ } -+ return tmp->value; -+} -+ -+/** -+ * @brief Returns IBPI pattern based on value -+ * -+ * @param[in] value Value for led state. -+ * @param[in] ibpi_values Array with defined IBPI states and values. -+ * -+ * @return Enum with IBPI value, which represents given value. -+ */ -+enum ibpi_pattern get_ibpi_for_value(const int value, const struct ibpi_value ibpi_values[]) -+{ -+ const struct ibpi_value *tmp = ibpi_values; -+ -+ while (tmp->ibpi != IBPI_PATTERN_UNKNOWN) { -+ if (tmp->value == value) -+ break; -+ tmp++; -+ } -+ return tmp->ibpi; -+} -diff --git a/src/utils.h b/src/utils.h -index 3f5a77fc6f74..5ef3020e6dce 100644 ---- a/src/utils.h -+++ b/src/utils.h -@@ -1,6 +1,6 @@ - /* - * Intel(R) Enclosure LED Utilities -- * Copyright (C) 2009-2019 Intel Corporation. -+ * Copyright (C) 2009-2022 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, -@@ -59,6 +59,10 @@ struct log_level_info { - int priority; - }; - -+struct ibpi_value { -+ int ibpi, value; -+}; -+ - /** - */ - #define PREFIX_DEBUG " DEBUG: " -@@ -418,6 +422,13 @@ enum opt { - OPT_LIST_CTRL, - OPT_LISTED_ONLY, - OPT_FOREGROUND, -+ OPT_LIST_SLOTS, -+ OPT_GET_SLOT, -+ OPT_SET_SLOT, -+ OPT_CONTROLLER, -+ OPT_DEVICE, -+ OPT_SLOT, -+ OPT_STATE, - OPT_NULL_ELEMENT - }; - -@@ -428,5 +439,7 @@ int get_option_id(const char *optarg); - status_t set_verbose_level(int log_level); - - const char *ibpi2str(enum ibpi_pattern ibpi); -+int get_value_for_ibpi(enum ibpi_pattern ibpi, const struct ibpi_value ibpi_values[]); -+enum ibpi_pattern get_ibpi_for_value(const int value, const struct ibpi_value ibpi_values[]); - - #endif /* _UTILS_H_INCLUDED_ */ -diff --git a/src/vmdssd.c b/src/vmdssd.c -index 3c6d24bdc604..015d3489c276 100644 ---- a/src/vmdssd.c -+++ b/src/vmdssd.c -@@ -1,6 +1,6 @@ - /* - * Intel(R) Enclosure LED Utilities -- * Copyright (c) 2016-2019, Intel Corporation -+ * Copyright (c) 2016-2022, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, -@@ -37,6 +37,13 @@ - #define ATTENTION_REBUILD 0x5 /* (0101) Attention On, Power On */ - #define ATTENTION_FAILURE 0xD /* (1101) Attention On, Power Off */ - -+struct ibpi_value ibpi_to_attention[] = { -+ {IBPI_PATTERN_LOCATE, ATTENTION_LOCATE}, -+ {IBPI_PATTERN_FAILED_DRIVE, ATTENTION_FAILURE}, -+ {IBPI_PATTERN_REBUILD, ATTENTION_REBUILD}, -+ {IBPI_PATTERN_LOCATE_OFF, ATTENTION_OFF} -+}; -+ - #define SYSFS_PCIEHP "/sys/module/pciehp" - - static char *get_slot_from_syspath(char *path) -@@ -61,24 +68,6 @@ static char *get_slot_from_syspath(char *path) - return ret; - } - --static void get_ctrl(enum ibpi_pattern ibpi, uint16_t *new) --{ -- switch (ibpi) { -- case IBPI_PATTERN_LOCATE: -- *new = ATTENTION_LOCATE; -- break; -- case IBPI_PATTERN_FAILED_DRIVE: -- *new = ATTENTION_FAILURE; -- break; -- case IBPI_PATTERN_REBUILD: -- *new = ATTENTION_REBUILD; -- break; -- default: -- *new = ATTENTION_OFF; -- break; -- } --} -- - static int check_slot_module(const char *slot_path) - { - char module_path[PATH_MAX], real_module_path[PATH_MAX]; -@@ -120,11 +109,29 @@ struct pci_slot *vmdssd_find_pci_slot(char *device_path) - return slot; - } - --int vmdssd_write(struct block_device *device, enum ibpi_pattern ibpi) -+status_t vmdssd_write_attention_buf(struct pci_slot *slot, enum ibpi_pattern ibpi) - { - char attention_path[PATH_MAX]; - char buf[WRITE_BUFFER_SIZE]; - uint16_t val; -+ -+ log_debug("%s before: 0x%x\n", slot->address, -+ get_int(slot->sysfs_path, 0, "attention")); -+ val = get_value_for_ibpi(ibpi, ibpi_to_attention); -+ snprintf(buf, WRITE_BUFFER_SIZE, "%u", val); -+ snprintf(attention_path, PATH_MAX, "%s/attention", slot->sysfs_path); -+ if (buf_write(attention_path, buf) != (ssize_t) strnlen(buf, WRITE_BUFFER_SIZE)) { -+ log_error("%s write error: %d\n", slot->sysfs_path, errno); -+ return STATUS_FILE_WRITE_ERROR; -+ } -+ log_debug("%s after: 0x%x\n", slot->address, -+ get_int(slot->sysfs_path, 0, "attention")); -+ -+ return STATUS_SUCCESS; -+} -+ -+int vmdssd_write(struct block_device *device, enum ibpi_pattern ibpi) -+{ - struct pci_slot *slot; - char *short_name = strrchr(device->sysfs_path, '/'); - -@@ -145,21 +152,7 @@ int vmdssd_write(struct block_device *device, enum ibpi_pattern ibpi) - __set_errno_and_return(ENODEV); - } - -- log_debug("%s before: 0x%x\n", short_name, -- get_int(slot->sysfs_path, 0, "attention")); -- -- get_ctrl(ibpi, &val); -- snprintf(buf, WRITE_BUFFER_SIZE, "%u", val); -- snprintf(attention_path, PATH_MAX, "%s/attention", slot->sysfs_path); -- if (buf_write(attention_path, buf) != (ssize_t) strnlen(buf, WRITE_BUFFER_SIZE)) { -- log_error("%s write error: %d\n", slot->sysfs_path, errno); -- return -1; -- } -- -- log_debug("%s after: 0x%x\n", short_name, -- get_int(slot->sysfs_path, 0, "attention")); -- -- return 0; -+ return vmdssd_write_attention_buf(slot, ibpi); - } - - char *vmdssd_get_path(const char *cntrl_path) -diff --git a/src/vmdssd.h b/src/vmdssd.h -index 4c90fcb35ea2..f07d989280bc 100644 ---- a/src/vmdssd.h -+++ b/src/vmdssd.h -@@ -1,6 +1,6 @@ - /* - * Intel(R) Enclosure LED Utilities -- * Copyright (c) 2016-2019, Intel Corporation -+ * Copyright (c) 2016-2022, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, -@@ -22,9 +22,18 @@ - - #include "block.h" - #include "ibpi.h" -+#include "utils.h" -+ -+#define ATTENTION_OFF 0xF /* (1111) Attention Off, Power Off */ -+#define ATTENTION_LOCATE 0x7 /* (0111) Attention Off, Power On */ -+#define ATTENTION_REBUILD 0x5 /* (0101) Attention On, Power On */ -+#define ATTENTION_FAILURE 0xD /* (1101) Attention On, Power Off */ -+ -+extern struct ibpi_value ibpi_to_attention[]; - - int vmdssd_write(struct block_device *device, enum ibpi_pattern ibpi); - char *vmdssd_get_path(const char *cntrl_path); - struct pci_slot *vmdssd_find_pci_slot(char *device_path); -+status_t vmdssd_write_attention_buf(struct pci_slot *slot, enum ibpi_pattern ibpi); - - #endif --- -2.34.1 - diff --git a/0002-add-Dell-15G-servers.patch b/0002-add-Dell-15G-servers.patch deleted file mode 100644 index 3cf44a8..0000000 --- a/0002-add-Dell-15G-servers.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 7274b21797d1ad76a2f4ccd2e3f70279e50512b4 Mon Sep 17 00:00:00 2001 -From: prabhakar -Date: Tue, 5 Jul 2022 08:16:18 -0400 -Subject: [PATCH 2/2] add Dell 15G servers - ---- - src/dellssd.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/src/dellssd.c b/src/dellssd.c -index 5a7ac5f4a629..fce3110d62d5 100644 ---- a/src/dellssd.c -+++ b/src/dellssd.c -@@ -93,6 +93,9 @@ enum { - DELL_13G_MODULAR = 0x21, - DELL_14G_MONOLITHIC = 0x30, - DELL_14G_MODULAR = 0x31, -+ DELL_15G_MONOLITHIC = 0x40, -+ DELL_15G_MODULAR = 0x41, -+ - }; - - int get_dell_server_type() -@@ -125,6 +128,9 @@ int get_dell_server_type() - case DELL_13G_MODULAR: - case DELL_14G_MONOLITHIC: - case DELL_14G_MODULAR: -+ case DELL_15G_MONOLITHIC: -+ case DELL_15G_MODULAR: -+ - gen = rdata[10]; - return gen; - default: -@@ -166,6 +172,9 @@ static int ipmi_setled(int b, int d, int f, int state) - break; - case DELL_14G_MONOLITHIC: - case DELL_14G_MODULAR: -+ case DELL_15G_MONOLITHIC: -+ case DELL_15G_MODULAR: -+ - data[1] = DELL_OEM_STORAGE_GETDRVMAP_14G; - break; - } -@@ -206,6 +215,9 @@ static int ipmi_setled(int b, int d, int f, int state) - break; - case DELL_14G_MONOLITHIC: - case DELL_14G_MODULAR: -+ case DELL_15G_MONOLITHIC: -+ case DELL_15G_MODULAR: -+ - data[1] = DELL_OEM_STORAGE_SETDRVSTATUS_14G; - break; - } --- -2.34.1 - diff --git a/0003-ipmi-avoid-error-messages-on-non-dell-platforms-112.patch b/0003-ipmi-avoid-error-messages-on-non-dell-platforms-112.patch deleted file mode 100644 index 6150e57..0000000 --- a/0003-ipmi-avoid-error-messages-on-non-dell-platforms-112.patch +++ /dev/null @@ -1,26 +0,0 @@ -From bd78c563daa6df17ad442d10127526f5450fd06b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Kinga=20Ta=C5=84ska?= -Date: Thu, 17 Nov 2022 15:55:06 +0100 -Subject: [PATCH] ipmi: avoid error messages on non-dell platforms (#112) - -Signed-off-by: Kinga Tanska ---- - src/ipmi.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/ipmi.c b/src/ipmi.c -index 3862840..d7d9e89 100644 ---- a/src/ipmi.c -+++ b/src/ipmi.c -@@ -126,7 +126,7 @@ int ipmicmd(int sa, int lun, int netfn, int cmd, int datalen, void *data, - goto end; - } - if (rcv.msg.data[0]) -- log_info("IPMI Error: %.2x\n", rcv.msg.data[0]); -+ log_debug("IPMI Error: %.2x\n", rcv.msg.data[0]); - rc = 0; - *rlen = rcv.msg.data_len - 1; - memcpy(resp, rcv.msg.data + 1, *rlen); --- -2.39.2 - diff --git a/ledmon-0.96.tar.gz b/ledmon-0.96.tar.gz deleted file mode 100644 index 95d5de8..0000000 --- a/ledmon-0.96.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:97534302a60f03b90e69228a6a56096cf3fdfc8eb31fea52a974445268fdf5d9 -size 83222 diff --git a/ledmon-0.97.tar.gz b/ledmon-0.97.tar.gz new file mode 100644 index 0000000..c4e46a5 --- /dev/null +++ b/ledmon-0.97.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:40ee7e462b78c77468cc2ef356a06c5b6db44747d596dc11532f7b6f378d2d4b +size 99216 diff --git a/ledmon.changes b/ledmon.changes index 9efc869..8365a56 100644 --- a/ledmon.changes +++ b/ledmon.changes @@ -1,3 +1,35 @@ +------------------------------------------------------------------- +Thu May 18 03:50:57 UTC 2023 - Nicholas Yang + +- Update to version 0.97: + + Enhancements + + ledctl: add support to empty slots blinking + ledmon license change to LGPLv2 + ledctl: Add SES get/set/list slot support + Update NPEM wait command + Remove exclusionary language + ledmon: Define ONESHOT_NORMAL for VMD + + Bug fixes + + ipmi: avoid error messages on non-dell platforms + vmdssd: define normal pattern + ledctl: clear unsupported params from config + block.c: get_block_device_from_sysfs_path modification + fix ibpi_value lists getter + amd_ipmi: Allow to _enable_smbus_control + ledmon.c: allocate memory for ignore + sysfs: add only vmd devices to slots_list + Rename --controller parameter + Slots list implementations and fixes + +- Drop no longer needed patches: + * 0001-Ledctl-slots-management-94.patch + * 0002-add-Dell-15G-servers.patch + * 0003-ipmi-avoid-error-messages-on-non-dell-platforms-112.patch + ------------------------------------------------------------------- Wed Apr 26 11:27:18 UTC 2023 - Johannes Segitz diff --git a/ledmon.spec b/ledmon.spec index dfa9e01..76f9750 100644 --- a/ledmon.spec +++ b/ledmon.spec @@ -17,17 +17,14 @@ Name: ledmon -Version: 0.96 +Version: 0.97 Release: 0 Summary: Enclosure LED Utilities -License: GPL-2.0-only +License: GPL-2.0-only AND LGPL-2.1-or-later Group: Hardware/Other URL: https://github.com/intel/ledmon/ -Source0: https://github.com/intel/ledmon/archive/%{version}.tar.gz#/%{name}-%{version}.tar.gz +Source0: https://github.com/intel/ledmon/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz Patch0: harden_ledmon.service.patch -Patch1: 0001-Ledctl-slots-management-94.patch -Patch2: 0002-add-Dell-15G-servers.patch -Patch3: 0003-ipmi-avoid-error-messages-on-non-dell-platforms-112.patch BuildRequires: autoconf BuildRequires: automake BuildRequires: libsgutils-devel @@ -74,7 +71,7 @@ rm %{buildroot}%{_datarootdir}/doc/ledmon/README.md %service_del_postun %{name}.service %files -%license COPYING +%license COPYING COPYING.LIB %doc README.md %{_sbindir}/ledmon %{_sbindir}/ledctl