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