File Index
Files and directories
Sign in
FILE

fwctl.h

File preview with syntax highlighting.

linux-6.19.14/include/linux/fwctl.h C
  1/* SPDX-License-Identifier: GPL-2.0-only */
  2/*
  3 * Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES
  4 */
  5#ifndef __LINUX_FWCTL_H
  6#define __LINUX_FWCTL_H
  7#include <linux/device.h>
  8#include <linux/cdev.h>
  9#include <linux/cleanup.h>
 10#include <uapi/fwctl/fwctl.h>
 11
 12struct fwctl_device;
 13struct fwctl_uctx;
 14
 15/**
 16 * struct fwctl_ops - Driver provided operations
 17 *
 18 * fwctl_unregister() will wait until all excuting ops are completed before it
 19 * returns. Drivers should be mindful to not let their ops run for too long as
 20 * it will block device hot unplug and module unloading.
 21 */
 22struct fwctl_ops {
 23	/**
 24	 * @device_type: The drivers assigned device_type number. This is uABI.
 25	 */
 26	enum fwctl_device_type device_type;
 27	/**
 28	 * @uctx_size: The size of the fwctl_uctx struct to allocate. The first
 29	 * bytes of this memory will be a fwctl_uctx. The driver can use the
 30	 * remaining bytes as its private memory.
 31	 */
 32	size_t uctx_size;
 33	/**
 34	 * @open_uctx: Called when a file descriptor is opened before the uctx
 35	 * is ever used.
 36	 */
 37	int (*open_uctx)(struct fwctl_uctx *uctx);
 38	/**
 39	 * @close_uctx: Called when the uctx is destroyed, usually when the FD
 40	 * is closed.
 41	 */
 42	void (*close_uctx)(struct fwctl_uctx *uctx);
 43	/**
 44	 * @info: Implement FWCTL_INFO. Return a kmalloc() memory that is copied
 45	 * to out_device_data. On input length indicates the size of the user
 46	 * buffer on output it indicates the size of the memory. The driver can
 47	 * ignore length on input, the core code will handle everything.
 48	 */
 49	void *(*info)(struct fwctl_uctx *uctx, size_t *length);
 50	/**
 51	 * @fw_rpc: Implement FWCTL_RPC. Deliver rpc_in/in_len to the FW and
 52	 * return the response and set out_len. rpc_in can be returned as the
 53	 * response pointer. Otherwise the returned pointer is freed with
 54	 * kvfree().
 55	 */
 56	void *(*fw_rpc)(struct fwctl_uctx *uctx, enum fwctl_rpc_scope scope,
 57			void *rpc_in, size_t in_len, size_t *out_len);
 58};
 59
 60/**
 61 * struct fwctl_device - Per-driver registration struct
 62 * @dev: The sysfs (class/fwctl/fwctlXX) device
 63 *
 64 * Each driver instance will have one of these structs with the driver private
 65 * data following immediately after. This struct is refcounted, it is freed by
 66 * calling fwctl_put().
 67 */
 68struct fwctl_device {
 69	struct device dev;
 70	/* private: */
 71	struct cdev cdev;
 72
 73	/* Protect uctx_list */
 74	struct mutex uctx_list_lock;
 75	struct list_head uctx_list;
 76	/*
 77	 * Protect ops, held for write when ops becomes NULL during unregister,
 78	 * held for read whenever ops is loaded or an ops function is running.
 79	 */
 80	struct rw_semaphore registration_lock;
 81	const struct fwctl_ops *ops;
 82};
 83
 84struct fwctl_device *_fwctl_alloc_device(struct device *parent,
 85					 const struct fwctl_ops *ops,
 86					 size_t size);
 87/**
 88 * fwctl_alloc_device - Allocate a fwctl
 89 * @parent: Physical device that provides the FW interface
 90 * @ops: Driver ops to register
 91 * @drv_struct: 'struct driver_fwctl' that holds the struct fwctl_device
 92 * @member: Name of the struct fwctl_device in @drv_struct
 93 *
 94 * This allocates and initializes the fwctl_device embedded in the drv_struct.
 95 * Upon success the pointer must be freed via fwctl_put(). Returns a 'drv_struct
 96 * \*' on success, NULL on error.
 97 */
 98#define fwctl_alloc_device(parent, ops, drv_struct, member)               \
 99	({                                                                \
100		static_assert(__same_type(struct fwctl_device,            \
101					  ((drv_struct *)NULL)->member)); \
102		static_assert(offsetof(drv_struct, member) == 0);         \
103		(drv_struct *)_fwctl_alloc_device(parent, ops,            \
104						  sizeof(drv_struct));    \
105	})
106
107static inline struct fwctl_device *fwctl_get(struct fwctl_device *fwctl)
108{
109	get_device(&fwctl->dev);
110	return fwctl;
111}
112static inline void fwctl_put(struct fwctl_device *fwctl)
113{
114	put_device(&fwctl->dev);
115}
116DEFINE_FREE(fwctl, struct fwctl_device *, if (_T) fwctl_put(_T));
117
118int fwctl_register(struct fwctl_device *fwctl);
119void fwctl_unregister(struct fwctl_device *fwctl);
120
121/**
122 * struct fwctl_uctx - Per user FD context
123 * @fwctl: fwctl instance that owns the context
124 *
125 * Every FD opened by userspace will get a unique context allocation. Any driver
126 * private data will follow immediately after.
127 */
128struct fwctl_uctx {
129	struct fwctl_device *fwctl;
130	/* private: */
131	/* Head at fwctl_device::uctx_list */
132	struct list_head uctx_list_entry;
133};
134
135#endif
~/ Read-only file preview.