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