/* 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
|
|
/*
|
* 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, 0444, _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__ */
|