|
@@ -0,0 +1,229 @@
|
|
|
+/*
|
|
|
+ * Copyright (c) 2017 The Linux Foundation. All rights reserved.
|
|
|
+ *
|
|
|
+ * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
|
|
|
+ *
|
|
|
+ *
|
|
|
+ * Permission to use, copy, modify, and/or distribute this software for
|
|
|
+ * any purpose with or without fee is hereby granted, provided that the
|
|
|
+ * above copyright notice and this permission notice appear in all
|
|
|
+ * copies.
|
|
|
+ *
|
|
|
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
|
|
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
|
|
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
|
|
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
|
|
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
|
|
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
|
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
+ * PERFORMANCE OF THIS SOFTWARE.
|
|
|
+ */
|
|
|
+
|
|
|
+/*
|
|
|
+ * This file was originally distributed by Qualcomm Atheros, Inc.
|
|
|
+ * under proprietary terms before Copyright ownership was assigned
|
|
|
+ * to the Linux Foundation.
|
|
|
+ */
|
|
|
+
|
|
|
+#ifndef __WLAN_HDD_REQUEST_MANAGER_H__
|
|
|
+#define __WLAN_HDD_REQUEST_MANAGER_H__
|
|
|
+
|
|
|
+/**
|
|
|
+ * DOC: WLAN HDD REQUEST MANAGER
|
|
|
+ *
|
|
|
+ * Many operations within the wlan driver occur in an asynchronous
|
|
|
+ * manner. Requests are received by HDD via one of the kernel
|
|
|
+ * interfaces (ioctl, nl80211, virtual file system, etc.). The
|
|
|
+ * requests are translated to an internal format and are then passed
|
|
|
+ * to lower layers, usually via SME, for processing. For requests
|
|
|
+ * which require a response, that response comes up from the lower
|
|
|
+ * layers in a separate thread of execution, ultimately resulting in a
|
|
|
+ * call to a callback function that was provided by HDD as part of the
|
|
|
+ * initial request. So a mechanism is needed to synchronize the
|
|
|
+ * request and response. This framework provides that mechanism.
|
|
|
+ *
|
|
|
+ * Once the framework has been initialized, the typical sequence of
|
|
|
+ * events is as follows:
|
|
|
+ *
|
|
|
+ * Request Thread:
|
|
|
+ * 1. Create a &struct hdd_request_params which describes the request.
|
|
|
+ * 2. Call hdd_request_alloc() to allocate a &struct hdd_request.
|
|
|
+ * 3. Call hdd_request_priv() to get a pointer to the private data.
|
|
|
+ * 4. Place any information which must be shared with the Response
|
|
|
+ * Callback in the private data area.
|
|
|
+ * 5. Call hdd_request_cookie() to get the unique cookie assigned
|
|
|
+ * to the request.
|
|
|
+ * 6. Call the underlying request handling API, passing the cookie
|
|
|
+ * as the callback's private context.
|
|
|
+ * 7. Call hdd_request_wait_for_response() to wait for the response
|
|
|
+ * (or for the request to time out).
|
|
|
+ * 8. Use the return status to see if the request was successful. If
|
|
|
+ * it was, retrieve any response information from the private
|
|
|
+ * structure and prepare a response for userspace.
|
|
|
+ * 9. Call hdd_request_put() to relinquish access to the request.
|
|
|
+ * 10. Return status to the caller.
|
|
|
+ *
|
|
|
+ * Response Callback:
|
|
|
+ * 1. Call hdd_request_get() with the provided cookie to see if the
|
|
|
+ * request structure is still valid. If it returns %NULL then
|
|
|
+ * return since this means the request thread has already timed
|
|
|
+ * out.
|
|
|
+ * 2. Call hdd_request_priv() to get access to the private data area.
|
|
|
+ * 3. Write response data into the private data area.
|
|
|
+ * 4. Call hdd_request_complete() to indicate that the response is
|
|
|
+ * ready to be processed by the request thread.
|
|
|
+ * 5. Call hdd_request_put() to relinquish the callback function's
|
|
|
+ * reference to the request.
|
|
|
+ */
|
|
|
+
|
|
|
+/* this is opaque to clients */
|
|
|
+struct hdd_request;
|
|
|
+
|
|
|
+/**
|
|
|
+ * typedef hdd_request_dealloc - Private data deallocation function
|
|
|
+ */
|
|
|
+typedef void (*hdd_request_dealloc)(void *priv);
|
|
|
+
|
|
|
+/**
|
|
|
+ * struct hdd_request_params - HDD request parameters
|
|
|
+ * @priv_size: Size of the private data area required to pass
|
|
|
+ * information between the request thread and the response callback.
|
|
|
+ * @timeout_ms: The amount of time to wait for a response in milliseconds.
|
|
|
+ * @dealloc: Function to be called when the request is destroyed to
|
|
|
+ * deallocate any allocations made in the private area of the
|
|
|
+ * request struct. Can be %NULL if no private allocations are
|
|
|
+ * made.
|
|
|
+ */
|
|
|
+struct hdd_request_params {
|
|
|
+ uint32_t priv_size;
|
|
|
+ uint32_t timeout_ms;
|
|
|
+ hdd_request_dealloc dealloc;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * hdd_request_alloc() - Allocate a request struct
|
|
|
+ * @params: parameter block that specifies the attributes of the
|
|
|
+ * request
|
|
|
+ *
|
|
|
+ * This function will attempt to allocate a &struct hdd_request with
|
|
|
+ * the specified @params. If successful, the caller can then use
|
|
|
+ * request struct to make an asynchronous request. Once the request is
|
|
|
+ * no longer needed, the reference should be relinquished via a call
|
|
|
+ * to hdd_request_put().
|
|
|
+ *
|
|
|
+ * Return: A pointer to an allocated &struct hdd_request (which also
|
|
|
+ * contains room for the private buffer) if the allocation is
|
|
|
+ * successful, %NULL if the allocation fails.
|
|
|
+ */
|
|
|
+struct hdd_request *hdd_request_alloc(const struct hdd_request_params *params);
|
|
|
+
|
|
|
+/**
|
|
|
+ * hdd_request_priv() - Get pointer to request private data
|
|
|
+ * @request: The request struct that contains the private data
|
|
|
+ *
|
|
|
+ * This function will return a pointer to the private data area that
|
|
|
+ * is part of the request struct. The caller must already have a valid
|
|
|
+ * reference to @request from either hdd_request_alloc() or
|
|
|
+ * hdd_request_get().
|
|
|
+ *
|
|
|
+ * Returns: pointer to the private data area. Note that this pointer
|
|
|
+ * will always be an offset from the input @request pointer and hence
|
|
|
+ * this function will never return %NULL.
|
|
|
+ */
|
|
|
+void *hdd_request_priv(struct hdd_request *request);
|
|
|
+
|
|
|
+/**
|
|
|
+ * hdd_request_cookie() - Get cookie of a request
|
|
|
+ * @request: The request struct associated with the request
|
|
|
+ *
|
|
|
+ * This function will return the unique cookie that has been assigned
|
|
|
+ * to the request. This cookie can subsequently be passed to
|
|
|
+ * hdd_request_get() to retrieve the request.
|
|
|
+ *
|
|
|
+ * Note that the cookie is defined as a void pointer as it is intended
|
|
|
+ * to be passed as an opaque context pointer from HDD to underlying
|
|
|
+ * layers when making a request, and subsequently passed back to HDD
|
|
|
+ * as an opaque pointer in an asynchronous callback.
|
|
|
+ *
|
|
|
+ * Returns: The cookie assigned to the request.
|
|
|
+ */
|
|
|
+void *hdd_request_cookie(struct hdd_request *request);
|
|
|
+
|
|
|
+/**
|
|
|
+ * hdd_request_get() - Get a reference to a request struct
|
|
|
+ * @cookie: The cookie of the request struct that needs to be
|
|
|
+ * referenced
|
|
|
+ *
|
|
|
+ * This function will use the cookie to determine if the associated
|
|
|
+ * request struct is valid, and if so, will increment the reference
|
|
|
+ * count of the struct. This means the caller is guaranteed that the
|
|
|
+ * request struct is valid and the underlying private data can be
|
|
|
+ * dereferenced.
|
|
|
+ *
|
|
|
+ * Returns: The pointer to the request struct associated with @cookie
|
|
|
+ * if the request is still valid, %NULL if the underlying request
|
|
|
+ * struct is no longer valid.
|
|
|
+ */
|
|
|
+struct hdd_request *hdd_request_get(void *cookie);
|
|
|
+
|
|
|
+/**
|
|
|
+ * hdd_request_put() - Release a reference to a request struct
|
|
|
+ * @request: The request struct that no longer needs to be referenced
|
|
|
+ *
|
|
|
+ * This function will decrement the reference count of the struct, and
|
|
|
+ * will clean up the request if this is the last reference. The caller
|
|
|
+ * must already have a valid reference to @request, either from
|
|
|
+ * hdd_request_alloc() or hdd_request_get().
|
|
|
+ *
|
|
|
+ * Returns: Nothing
|
|
|
+ */
|
|
|
+void hdd_request_put(struct hdd_request *request);
|
|
|
+
|
|
|
+/**
|
|
|
+ * hdd_request_wait_for_response() - Wait for a response
|
|
|
+ * @request: The request struct associated with the request
|
|
|
+ *
|
|
|
+ * This function will wait until either a response is received and
|
|
|
+ * communicated via hdd_request_complete(), or until the request
|
|
|
+ * timeout period expires.
|
|
|
+ *
|
|
|
+ * Returns: 0 if a response was received, -ETIMEDOUT if the response
|
|
|
+ * timed out.
|
|
|
+ */
|
|
|
+int hdd_request_wait_for_response(struct hdd_request *request);
|
|
|
+
|
|
|
+/**
|
|
|
+ * hdd_request_complete() - Complete a request
|
|
|
+ * @request: The request struct associated with the request
|
|
|
+ *
|
|
|
+ * This function is used to indicate that a response has been received
|
|
|
+ * and that any information required by the request thread has been
|
|
|
+ * copied into the private data area of the request struct. This will
|
|
|
+ * unblock any hdd_request_wait_for_response() that is pending on this
|
|
|
+ * @request.
|
|
|
+ *
|
|
|
+ * Returns: Nothing
|
|
|
+ */
|
|
|
+void hdd_request_complete(struct hdd_request *request);
|
|
|
+
|
|
|
+/**
|
|
|
+ * hdd_request_manager_init() - Initialize the HDD Request Manager
|
|
|
+ *
|
|
|
+ * This function must be called during system initialization to
|
|
|
+ * initialize the HDD Request Manager.
|
|
|
+ *
|
|
|
+ * Returns: Nothing
|
|
|
+ */
|
|
|
+void hdd_request_manager_init(void);
|
|
|
+
|
|
|
+/**
|
|
|
+ * hdd_request_manager_deinit() - Deinitialize the HDD Request Manager
|
|
|
+ *
|
|
|
+ * This function must be called during system shutdown to deinitialize
|
|
|
+ * the HDD Request Manager.
|
|
|
+ *
|
|
|
+ * Returns: Nothing
|
|
|
+ */
|
|
|
+void hdd_request_manager_deinit(void);
|
|
|
+
|
|
|
+#endif /* __WLAN_HDD_REQUEST_MANAGER_H__ */
|