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