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