at v6.17 4.4 kB view raw
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