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