1 /* 2 * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #ifndef __WLAN_OSIF_REQUEST_MANAGER_H__ 21 #define __WLAN_OSIF_REQUEST_MANAGER_H__ 22 23 /** 24 * DOC: WLAN OSIF REQUEST MANAGER 25 * 26 * Many operations within the wlan driver occur in an asynchronous 27 * manner. Requests are received by OSIF via one of the kernel 28 * interfaces (ioctl, nl80211, virtual file system, etc.). The 29 * requests are translated to an internal format and are then passed 30 * to lower layers, usually via SME, for processing. For requests 31 * which require a response, that response comes up from the lower 32 * layers in a separate thread of execution, ultimately resulting in a 33 * call to a callback function that was provided by OSIF as part of the 34 * initial request. So a mechanism is needed to synchronize the 35 * request and response. This framework provides that mechanism. 36 * 37 * Once the framework has been initialized, the typical sequence of 38 * events is as follows: 39 * 40 * Request Thread: 41 * 1. Create a &struct osif_request_params which describes the request. 42 * 2. Call osif_request_alloc() to allocate a &struct osif_request. 43 * 3. Call osif_request_priv() to get a pointer to the private data. 44 * 4. Place any information which must be shared with the Response 45 * Callback in the private data area. 46 * 5. Call osif_request_cookie() to get the unique cookie assigned 47 * to the request. 48 * 6. Call the underlying request handling API, passing the cookie 49 * as the callback's private context. 50 * 7. Call osif_request_wait_for_response() to wait for the response 51 * (or for the request to time out). 52 * 8. Use the return status to see if the request was successful. If 53 * it was, retrieve any response information from the private 54 * structure and prepare a response for userspace. 55 * 9. Call osif_request_put() to relinquish access to the request. 56 * 10. Return status to the caller. 57 * 58 * Response Callback: 59 * 1. Call osif_request_get() with the provided cookie to see if the 60 * request structure is still valid. If it returns %NULL then 61 * return since this means the request thread has already timed 62 * out. 63 * 2. Call osif_request_priv() to get access to the private data area. 64 * 3. Write response data into the private data area. 65 * 4. Call osif_request_complete() to indicate that the response is 66 * ready to be processed by the request thread. 67 * 5. Call osif_request_put() to relinquish the callback function's 68 * reference to the request. 69 */ 70 71 /* this is opaque to clients */ 72 struct osif_request; 73 74 /** 75 * typedef osif_request_dealloc() - Private data deallocation function 76 * @priv: pointer to request private date 77 */ 78 typedef void (*osif_request_dealloc)(void *priv); 79 80 /** 81 * struct osif_request_params - OSIF request parameters 82 * @priv_size: Size of the private data area required to pass 83 * information between the request thread and the response callback. 84 * @timeout_ms: The amount of time to wait for a response in milliseconds. 85 * @dealloc: Function to be called when the request is destroyed to 86 * deallocate any allocations made in the private area of the 87 * request struct. Can be %NULL if no private allocations are 88 * made. 89 */ 90 struct osif_request_params { 91 uint32_t priv_size; 92 uint32_t timeout_ms; 93 osif_request_dealloc dealloc; 94 }; 95 96 /** 97 * osif_request_alloc() - Allocate a request struct 98 * @params: parameter block that specifies the attributes of the 99 * request 100 * 101 * This function will attempt to allocate a &struct osif_request with 102 * the specified @params. If successful, the caller can then use 103 * request struct to make an asynchronous request. Once the request is 104 * no longer needed, the reference should be relinquished via a call 105 * to osif_request_put(). 106 * 107 * Return: A pointer to an allocated &struct osif_request (which also 108 * contains room for the private buffer) if the allocation is 109 * successful, %NULL if the allocation fails. 110 */ 111 struct osif_request *osif_request_alloc(const struct osif_request_params *params); 112 113 /** 114 * osif_request_priv() - Get pointer to request private data 115 * @request: The request struct that contains the private data 116 * 117 * This function will return a pointer to the private data area that 118 * is part of the request struct. The caller must already have a valid 119 * reference to @request from either osif_request_alloc() or 120 * osif_request_get(). 121 * 122 * Returns: pointer to the private data area. Note that this pointer 123 * will always be an offset from the input @request pointer and hence 124 * this function will never return %NULL. 125 */ 126 void *osif_request_priv(struct osif_request *request); 127 128 /** 129 * osif_request_cookie() - Get cookie of a request 130 * @request: The request struct associated with the request 131 * 132 * This function will return the unique cookie that has been assigned 133 * to the request. This cookie can subsequently be passed to 134 * osif_request_get() to retrieve the request. 135 * 136 * Note that the cookie is defined as a void pointer as it is intended 137 * to be passed as an opaque context pointer from OSIF to underlying 138 * layers when making a request, and subsequently passed back to OSIF 139 * as an opaque pointer in an asynchronous callback. 140 * 141 * Returns: The cookie assigned to the request. 142 */ 143 void *osif_request_cookie(struct osif_request *request); 144 145 /** 146 * osif_request_get() - Get a reference to a request struct 147 * @cookie: The cookie of the request struct that needs to be 148 * referenced 149 * 150 * This function will use the cookie to determine if the associated 151 * request struct is valid, and if so, will increment the reference 152 * count of the struct. This means the caller is guaranteed that the 153 * request struct is valid and the underlying private data can be 154 * dereferenced. 155 * 156 * Returns: The pointer to the request struct associated with @cookie 157 * if the request is still valid, %NULL if the underlying request 158 * struct is no longer valid. 159 */ 160 struct osif_request *osif_request_get(void *cookie); 161 162 /** 163 * osif_request_put() - Release a reference to a request struct 164 * @request: The request struct that no longer needs to be referenced 165 * 166 * This function will decrement the reference count of the struct, and 167 * will clean up the request if this is the last reference. The caller 168 * must already have a valid reference to @request, either from 169 * osif_request_alloc() or osif_request_get(). 170 * 171 * Returns: Nothing 172 */ 173 void osif_request_put(struct osif_request *request); 174 175 /** 176 * osif_request_wait_for_response() - Wait for a response 177 * @request: The request struct associated with the request 178 * 179 * This function will wait until either a response is received and 180 * communicated via osif_request_complete(), or until the request 181 * timeout period expires. 182 * 183 * Returns: 0 if a response was received, -ETIMEDOUT if the response 184 * timed out. 185 */ 186 int osif_request_wait_for_response(struct osif_request *request); 187 188 /** 189 * osif_request_complete() - Complete a request 190 * @request: The request struct associated with the request 191 * 192 * This function is used to indicate that a response has been received 193 * and that any information required by the request thread has been 194 * copied into the private data area of the request struct. This will 195 * unblock any osif_request_wait_for_response() that is pending on this 196 * @request. 197 * 198 * Returns: Nothing 199 */ 200 void osif_request_complete(struct osif_request *request); 201 202 /** 203 * osif_request_manager_init() - Initialize the OSIF Request Manager 204 * 205 * This function must be called during system initialization to 206 * initialize the OSIF Request Manager. 207 * 208 * Returns: Nothing 209 */ 210 void osif_request_manager_init(void); 211 212 /** 213 * osif_request_manager_deinit() - Deinitialize the OSIF Request Manager 214 * 215 * This function must be called during system shutdown to deinitialize 216 * the OSIF Request Manager. 217 * 218 * Returns: Nothing 219 */ 220 void osif_request_manager_deinit(void); 221 222 #endif /* __WLAN_OSIF_REQUEST_MANAGER_H__ */ 223