Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
C
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136/* SPDX-License-Identifier: GPL-2.0-only *//* * Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES */#ifndef __LINUX_FWCTL_H#define __LINUX_FWCTL_H#include <linux/device.h>#include <linux/cdev.h>#include <linux/cleanup.h>#include <uapi/fwctl/fwctl.h>
struct fwctl_device;struct fwctl_uctx;
/** * struct fwctl_ops - Driver provided operations * * fwctl_unregister() will wait until all excuting ops are completed before it * returns. Drivers should be mindful to not let their ops run for too long as * it will block device hot unplug and module unloading. */struct fwctl_ops { /** * @device_type: The drivers assigned device_type number. This is uABI. */ enum fwctl_device_type device_type; /** * @uctx_size: The size of the fwctl_uctx struct to allocate. The first * bytes of this memory will be a fwctl_uctx. The driver can use the * remaining bytes as its private memory. */ size_t uctx_size; /** * @open_uctx: Called when a file descriptor is opened before the uctx * is ever used. */ int (*open_uctx)(struct fwctl_uctx *uctx); /** * @close_uctx: Called when the uctx is destroyed, usually when the FD * is closed. */ void (*close_uctx)(struct fwctl_uctx *uctx); /** * @info: Implement FWCTL_INFO. Return a kmalloc() memory that is copied * to out_device_data. On input length indicates the size of the user * buffer on output it indicates the size of the memory. The driver can * ignore length on input, the core code will handle everything. */ void *(*info)(struct fwctl_uctx *uctx, size_t *length); /** * @fw_rpc: Implement FWCTL_RPC. Deliver rpc_in/in_len to the FW and * return the response and set out_len. rpc_in can be returned as the * response pointer. Otherwise the returned pointer is freed with * kvfree(). */ void *(*fw_rpc)(struct fwctl_uctx *uctx, enum fwctl_rpc_scope scope, void *rpc_in, size_t in_len, size_t *out_len);};
/** * struct fwctl_device - Per-driver registration struct * @dev: The sysfs (class/fwctl/fwctlXX) device * * Each driver instance will have one of these structs with the driver private * data following immediately after. This struct is refcounted, it is freed by * calling fwctl_put(). */struct fwctl_device { struct device dev; /* private: */ struct cdev cdev;
/* Protect uctx_list */ struct mutex uctx_list_lock; struct list_head uctx_list; /* * Protect ops, held for write when ops becomes NULL during unregister, * held for read whenever ops is loaded or an ops function is running. */ struct rw_semaphore registration_lock; const struct fwctl_ops *ops;};
struct fwctl_device *_fwctl_alloc_device(struct device *parent, const struct fwctl_ops *ops, size_t size);/** * fwctl_alloc_device - Allocate a fwctl * @parent: Physical device that provides the FW interface * @ops: Driver ops to register * @drv_struct: 'struct driver_fwctl' that holds the struct fwctl_device * @member: Name of the struct fwctl_device in @drv_struct * * This allocates and initializes the fwctl_device embedded in the drv_struct. * Upon success the pointer must be freed via fwctl_put(). Returns a 'drv_struct * \*' on success, NULL on error. */#define fwctl_alloc_device(parent, ops, drv_struct, member) \ ({ \ static_assert(__same_type(struct fwctl_device, \ ((drv_struct *)NULL)->member)); \ static_assert(offsetof(drv_struct, member) == 0); \ (drv_struct *)_fwctl_alloc_device(parent, ops, \ sizeof(drv_struct)); \ })
static inline struct fwctl_device *fwctl_get(struct fwctl_device *fwctl){ get_device(&fwctl->dev); return fwctl;}static inline void fwctl_put(struct fwctl_device *fwctl){ put_device(&fwctl->dev);}DEFINE_FREE(fwctl, struct fwctl_device *, if (_T) fwctl_put(_T));
int fwctl_register(struct fwctl_device *fwctl);void fwctl_unregister(struct fwctl_device *fwctl);
/** * struct fwctl_uctx - Per user FD context * @fwctl: fwctl instance that owns the context * * Every FD opened by userspace will get a unique context allocation. Any driver * private data will follow immediately after. */struct fwctl_uctx { struct fwctl_device *fwctl; /* private: */ /* Head at fwctl_device::uctx_list */ struct list_head uctx_list_entry;};
#endif