xref: /wlan-dirver/qca-wifi-host-cmn/os_if/linux/wlan_osif_request_manager.h (revision 4865edfd190c086bbe2c69aae12a8226f877b91e)
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