blob: cb2d425b71c1def9f0bbb28a2c9e05600125b7e3 [file] [log] [blame]
Jeff Johnson3a3bc292017-01-20 07:23:10 -08001/*
2 * Copyright (c) 2017 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_HDD_REQUEST_MANAGER_H__
29#define __WLAN_HDD_REQUEST_MANAGER_H__
30
31/**
32 * DOC: WLAN HDD REQUEST MANAGER
33 *
34 * Many operations within the wlan driver occur in an asynchronous
35 * manner. Requests are received by HDD 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 HDD 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 hdd_request_params which describes the request.
50 * 2. Call hdd_request_alloc() to allocate a &struct hdd_request.
51 * 3. Call hdd_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 hdd_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 hdd_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 hdd_request_put() to relinquish access to the request.
64 * 10. Return status to the caller.
65 *
66 * Response Callback:
67 * 1. Call hdd_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 hdd_request_priv() to get access to the private data area.
72 * 3. Write response data into the private data area.
73 * 4. Call hdd_request_complete() to indicate that the response is
74 * ready to be processed by the request thread.
75 * 5. Call hdd_request_put() to relinquish the callback function's
76 * reference to the request.
77 */
78
79/* this is opaque to clients */
80struct hdd_request;
81
82/**
83 * typedef hdd_request_dealloc - Private data deallocation function
84 */
85typedef void (*hdd_request_dealloc)(void *priv);
86
87/**
88 * struct hdd_request_params - HDD 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 */
97struct hdd_request_params {
98 uint32_t priv_size;
99 uint32_t timeout_ms;
100 hdd_request_dealloc dealloc;
101};
102
103/**
104 * hdd_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 hdd_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 hdd_request_put().
113 *
114 * Return: A pointer to an allocated &struct hdd_request (which also
115 * contains room for the private buffer) if the allocation is
116 * successful, %NULL if the allocation fails.
117 */
118struct hdd_request *hdd_request_alloc(const struct hdd_request_params *params);
119
120/**
121 * hdd_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 hdd_request_alloc() or
127 * hdd_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 */
133void *hdd_request_priv(struct hdd_request *request);
134
135/**
136 * hdd_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 * hdd_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 HDD to underlying
145 * layers when making a request, and subsequently passed back to HDD
146 * as an opaque pointer in an asynchronous callback.
147 *
148 * Returns: The cookie assigned to the request.
149 */
150void *hdd_request_cookie(struct hdd_request *request);
151
152/**
153 * hdd_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 */
167struct hdd_request *hdd_request_get(void *cookie);
168
169/**
170 * hdd_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 * hdd_request_alloc() or hdd_request_get().
177 *
178 * Returns: Nothing
179 */
180void hdd_request_put(struct hdd_request *request);
181
182/**
183 * hdd_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 hdd_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 */
193int hdd_request_wait_for_response(struct hdd_request *request);
194
195/**
196 * hdd_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 hdd_request_wait_for_response() that is pending on this
203 * @request.
204 *
205 * Returns: Nothing
206 */
207void hdd_request_complete(struct hdd_request *request);
208
209/**
210 * hdd_request_manager_init() - Initialize the HDD Request Manager
211 *
212 * This function must be called during system initialization to
213 * initialize the HDD Request Manager.
214 *
215 * Returns: Nothing
216 */
217void hdd_request_manager_init(void);
218
219/**
220 * hdd_request_manager_deinit() - Deinitialize the HDD Request Manager
221 *
222 * This function must be called during system shutdown to deinitialize
223 * the HDD Request Manager.
224 *
225 * Returns: Nothing
226 */
227void hdd_request_manager_deinit(void);
228
229#endif /* __WLAN_HDD_REQUEST_MANAGER_H__ */