Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

peci: Add sysfs interface for PECI bus

PECI devices may not be discoverable at the time when PECI controller is
being added (e.g. BMC can boot up when the Host system is still in S5).
Since we currently don't have the capabilities to figure out the Host
system state inside the PECI subsystem itself, we have to rely on
userspace to do it for us.

In the future, PECI subsystem may be expanded with mechanisms that allow
us to avoid depending on userspace interaction (e.g. CPU presence could
be detected using GPIO, and the information on whether it's discoverable
could be obtained over IPMI).
Unfortunately, those methods may ultimately not be available (support
will vary from platform to platform), which means that we still need
platform independent method triggered by userspace.

Acked-by: Joel Stanley <joel@jms.id.au>
Signed-off-by: Iwona Winiarska <iwona.winiarska@intel.com>
Link: https://lore.kernel.org/r/20220208153639.255278-8-iwona.winiarska@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Iwona Winiarska and committed by
Greg Kroah-Hartman
42bed52b 52857e68

+107 -2
+16
Documentation/ABI/testing/sysfs-bus-peci
··· 1 + What: /sys/bus/peci/rescan 2 + Date: July 2021 3 + KernelVersion: 5.18 4 + Contact: Iwona Winiarska <iwona.winiarska@intel.com> 5 + Description: 6 + Writing a non-zero value to this attribute will 7 + initiate scan for PECI devices on all PECI controllers 8 + in the system. 9 + 10 + What: /sys/bus/peci/devices/<controller_id>-<device_addr>/remove 11 + Date: July 2021 12 + KernelVersion: 5.18 13 + Contact: Iwona Winiarska <iwona.winiarska@intel.com> 14 + Description: 15 + Writing a non-zero value to this attribute will 16 + remove the PECI device and any of its children.
+1 -1
drivers/peci/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 3 3 # Core functionality 4 - peci-y := core.o request.o device.o 4 + peci-y := core.o request.o device.o sysfs.o 5 5 obj-$(CONFIG_PECI) += peci.o 6 6 7 7 # Hardware specific bus drivers
+2 -1
drivers/peci/core.c
··· 29 29 .release = peci_controller_dev_release, 30 30 }; 31 31 32 - static int peci_controller_scan_devices(struct peci_controller *controller) 32 + int peci_controller_scan_devices(struct peci_controller *controller) 33 33 { 34 34 int ret; 35 35 u8 addr; ··· 162 162 163 163 struct bus_type peci_bus_type = { 164 164 .name = "peci", 165 + .bus_groups = peci_bus_groups, 165 166 }; 166 167 167 168 static int __init peci_init(void)
+1
drivers/peci/device.c
··· 116 116 } 117 117 118 118 struct device_type peci_device_type = { 119 + .groups = peci_device_groups, 119 120 .release = peci_device_release, 120 121 };
+5
drivers/peci/internal.h
··· 8 8 #include <linux/types.h> 9 9 10 10 struct peci_controller; 11 + struct attribute_group; 11 12 struct peci_device; 12 13 struct peci_request; 13 14 ··· 20 19 void peci_request_free(struct peci_request *req); 21 20 22 21 extern struct device_type peci_device_type; 22 + extern const struct attribute_group *peci_device_groups[]; 23 23 24 24 int peci_device_create(struct peci_controller *controller, u8 addr); 25 25 void peci_device_destroy(struct peci_device *device); 26 26 27 27 extern struct bus_type peci_bus_type; 28 + extern const struct attribute_group *peci_bus_groups[]; 28 29 29 30 extern struct device_type peci_controller_type; 31 + 32 + int peci_controller_scan_devices(struct peci_controller *controller); 30 33 31 34 #endif /* __PECI_INTERNAL_H */
+82
drivers/peci/sysfs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // Copyright (c) 2021 Intel Corporation 3 + 4 + #include <linux/device.h> 5 + #include <linux/kernel.h> 6 + #include <linux/peci.h> 7 + 8 + #include "internal.h" 9 + 10 + static int rescan_controller(struct device *dev, void *data) 11 + { 12 + if (dev->type != &peci_controller_type) 13 + return 0; 14 + 15 + return peci_controller_scan_devices(to_peci_controller(dev)); 16 + } 17 + 18 + static ssize_t rescan_store(struct bus_type *bus, const char *buf, size_t count) 19 + { 20 + bool res; 21 + int ret; 22 + 23 + ret = kstrtobool(buf, &res); 24 + if (ret) 25 + return ret; 26 + 27 + if (!res) 28 + return count; 29 + 30 + ret = bus_for_each_dev(&peci_bus_type, NULL, NULL, rescan_controller); 31 + if (ret) 32 + return ret; 33 + 34 + return count; 35 + } 36 + static BUS_ATTR_WO(rescan); 37 + 38 + static struct attribute *peci_bus_attrs[] = { 39 + &bus_attr_rescan.attr, 40 + NULL 41 + }; 42 + 43 + static const struct attribute_group peci_bus_group = { 44 + .attrs = peci_bus_attrs, 45 + }; 46 + 47 + const struct attribute_group *peci_bus_groups[] = { 48 + &peci_bus_group, 49 + NULL 50 + }; 51 + 52 + static ssize_t remove_store(struct device *dev, struct device_attribute *attr, 53 + const char *buf, size_t count) 54 + { 55 + struct peci_device *device = to_peci_device(dev); 56 + bool res; 57 + int ret; 58 + 59 + ret = kstrtobool(buf, &res); 60 + if (ret) 61 + return ret; 62 + 63 + if (res && device_remove_file_self(dev, attr)) 64 + peci_device_destroy(device); 65 + 66 + return count; 67 + } 68 + static DEVICE_ATTR_IGNORE_LOCKDEP(remove, 0200, NULL, remove_store); 69 + 70 + static struct attribute *peci_device_attrs[] = { 71 + &dev_attr_remove.attr, 72 + NULL 73 + }; 74 + 75 + static const struct attribute_group peci_device_group = { 76 + .attrs = peci_device_attrs, 77 + }; 78 + 79 + const struct attribute_group *peci_device_groups[] = { 80 + &peci_device_group, 81 + NULL 82 + };