diff options
Diffstat (limited to 'drivers/staging/gasket/gasket_sysfs.h')
-rw-r--r-- | drivers/staging/gasket/gasket_sysfs.h | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/drivers/staging/gasket/gasket_sysfs.h b/drivers/staging/gasket/gasket_sysfs.h new file mode 100644 index 000000000000..f32eaf89e056 --- /dev/null +++ b/drivers/staging/gasket/gasket_sysfs.h @@ -0,0 +1,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(GASKET_ARRAY_END_TOKEN, S_IRUGO, NULL, 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_get_device_data. 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__ */ |