1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Set of common sysfs utilities. 4 * 5 * Copyright (C) 2018 Google, Inc. 6 */ 7 8 /* The functions described here are a set of utilities to allow each file in the 9 * Gasket driver framework to manage their own set of sysfs entries, instead of 10 * centralizing all that work in one file. 11 * 12 * The goal of these utilities is to allow for sysfs entries to be easily 13 * created without causing a proliferation of sysfs "show" functions. This 14 * requires O(N) string lookups during show function execution, but as reading 15 * sysfs entries is rarely performance-critical, this is likely acceptible. 16 */ 17 #ifndef __GASKET_SYSFS_H__ 18 #define __GASKET_SYSFS_H__ 19 20 #include "gasket_constants.h" 21 #include "gasket_core.h" 22 #include <linux/device.h> 23 #include <linux/stringify.h> 24 #include <linux/sysfs.h> 25 26 /* The maximum number of mappings/devices a driver needs to support. */ 27 #define GASKET_SYSFS_NUM_MAPPINGS (GASKET_FRAMEWORK_DESC_MAX * GASKET_DEV_MAX) 28 29 /* The maximum number of sysfs nodes in a directory. 30 */ 31 #define GASKET_SYSFS_MAX_NODES 196 32 33 /* 34 * Terminator struct for a gasket_sysfs_attr array. Must be at the end of 35 * all gasket_sysfs_attribute arrays. 36 */ 37 #define GASKET_END_OF_ATTR_ARRAY \ 38 { \ 39 .attr = __ATTR_NULL, \ 40 .data.attr_type = 0, \ 41 } 42 43 /* 44 * Pairing of sysfs attribute and user data. 45 * Used in lookups in sysfs "show" functions to return attribute metadata. 46 */ 47 struct gasket_sysfs_attribute { 48 /* The underlying sysfs device attribute associated with this data. */ 49 struct device_attribute attr; 50 51 /* User-specified data to associate with the attribute. */ 52 union { 53 struct bar_address_ { 54 ulong bar; 55 ulong offset; 56 } bar_address; 57 uint attr_type; 58 } data; 59 60 /* 61 * Function pointer to a callback to be invoked when this attribute is 62 * written (if so configured). The arguments are to the Gasket device 63 * pointer, the enclosing gasket_attr structure, and the value written. 64 * The callback should perform any logging necessary, as errors cannot 65 * be returned from the callback. 66 */ 67 void (*write_callback)(struct gasket_dev *dev, 68 struct gasket_sysfs_attribute *attr, 69 ulong value); 70 }; 71 72 #define GASKET_SYSFS_RO(_name, _show_function, _attr_type) \ 73 { \ 74 .attr = __ATTR(_name, 0444, _show_function, NULL), \ 75 .data.attr_type = _attr_type \ 76 } 77 78 /* Initializes the Gasket sysfs subsystem. 79 * 80 * Description: Performs one-time initialization. Must be called before usage 81 * at [Gasket] module load time. 82 */ 83 void gasket_sysfs_init(void); 84 85 /* 86 * Create an entry in mapping_data between a device and a Gasket device. 87 * @device: Device struct to map to. 88 * @gasket_dev: The dev struct associated with the driver controlling @device. 89 * 90 * Description: This function maps a gasket_dev* to a device*. This mapping can 91 * be used in sysfs_show functions to get a handle to the gasket_dev struct 92 * controlling the device node. 93 * 94 * If this function is not called before gasket_sysfs_create_entries, a warning 95 * will be logged. 96 */ 97 int gasket_sysfs_create_mapping(struct device *device, 98 struct gasket_dev *gasket_dev); 99 100 /* 101 * Creates bulk entries in sysfs. 102 * @device: Kernel device structure. 103 * @attrs: List of attributes/sysfs entries to create. 104 * 105 * Description: Creates each sysfs entry described in "attrs". Can be called 106 * multiple times for a given @device. If the gasket_dev specified in 107 * gasket_sysfs_create_mapping had a legacy device, the entries will be created 108 * for it, as well. 109 */ 110 int gasket_sysfs_create_entries(struct device *device, 111 const struct gasket_sysfs_attribute *attrs); 112 113 /* 114 * Removes a device mapping from the global table. 115 * @device: Device to unmap. 116 * 117 * Description: Removes the device->Gasket device mapping from the internal 118 * table. 119 */ 120 void gasket_sysfs_remove_mapping(struct device *device); 121 122 /* 123 * User data lookup based on kernel device structure. 124 * @device: Kernel device structure. 125 * 126 * Description: Returns the user data associated with "device" in a prior call 127 * to gasket_sysfs_create_entries. Returns NULL if no mapping can be found. 128 * Upon success, this call take a reference to internal sysfs data that must be 129 * released with gasket_sysfs_put_device_data. While this reference is held, the 130 * underlying device sysfs information/structure will remain valid/will not be 131 * deleted. 132 */ 133 struct gasket_dev *gasket_sysfs_get_device_data(struct device *device); 134 135 /* 136 * Releases a references to internal data. 137 * @device: Kernel device structure. 138 * @dev: Gasket device descriptor (returned by gasket_sysfs_get_device_data). 139 */ 140 void gasket_sysfs_put_device_data(struct device *device, 141 struct gasket_dev *gasket_dev); 142 143 /* 144 * Gasket-specific attribute lookup. 145 * @device: Kernel device structure. 146 * @attr: Device attribute to look up. 147 * 148 * Returns the Gasket sysfs attribute associated with the kernel device 149 * attribute and device structure itself. Upon success, this call will take a 150 * reference to internal sysfs data that must be released with a call to 151 * gasket_sysfs_put_attr. While this reference is held, the underlying device 152 * sysfs information/structure will remain valid/will not be deleted. 153 */ 154 struct gasket_sysfs_attribute * 155 gasket_sysfs_get_attr(struct device *device, struct device_attribute *attr); 156 157 /* 158 * Releases a references to internal data. 159 * @device: Kernel device structure. 160 * @attr: Gasket sysfs attribute descriptor (returned by 161 * gasket_sysfs_get_attr). 162 */ 163 void gasket_sysfs_put_attr(struct device *device, 164 struct gasket_sysfs_attribute *attr); 165 166 /* 167 * Write to a register sysfs node. 168 * @buf: NULL-terminated data being written. 169 * @count: number of bytes in the "buf" argument. 170 */ 171 ssize_t gasket_sysfs_register_store(struct device *device, 172 struct device_attribute *attr, 173 const char *buf, size_t count); 174 175 #endif /* __GASKET_SYSFS_H__ */ 176