mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 22:40:54 -04:00
qcacld-3.0: Handle attribute OEM_DATA_RESPONSE_EXPECTED
Add support for OEM_DATA_RESPONSE_EXPECTED. Driver waits for the response from FW when this attribute is set and forward the blob of data to supplicant. Change-Id: I3e51809e4f5736b521c26e37afb02396f9c5ed23 CRs-Fixed: 2694556
This commit is contained in:
parent
7f4a948144
commit
0ec49a71f7
8 changed files with 202 additions and 106 deletions
|
|
@ -1374,6 +1374,11 @@ struct hdd_adapter {
|
|||
qdf_mutex_t sta_periodic_stats_lock;
|
||||
#endif /* WLAN_FEATURE_PERIODIC_STA_STATS */
|
||||
qdf_event_t peer_cleanup_done;
|
||||
#ifdef FEATURE_OEM_DATA
|
||||
bool oem_data_in_progress;
|
||||
void *cookie;
|
||||
bool response_expected;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define WLAN_HDD_GET_STATION_CTX_PTR(adapter) (&(adapter)->session.station)
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@
|
|||
|
||||
struct hdd_context;
|
||||
|
||||
#ifdef FEATURE_OEM_DATA
|
||||
#define WLAN_WAIT_TIME_GET_OEM_DATA 1000
|
||||
#endif
|
||||
#ifdef FEATURE_OEM_DATA_SUPPORT
|
||||
|
||||
#ifndef OEM_DATA_REQ_SIZE
|
||||
|
|
@ -284,12 +287,15 @@ extern const struct nla_policy
|
|||
/**
|
||||
* hdd_oem_event_handler_cb() - callback for oem data event
|
||||
* @oem_event_data: oem data received in the event from the FW
|
||||
* @vdev_id: vdev id
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void hdd_oem_event_handler_cb(const struct oem_data *oem_event_data);
|
||||
void hdd_oem_event_handler_cb(const struct oem_data *oem_event_data,
|
||||
uint8_t vdev_id);
|
||||
#else
|
||||
static inline void hdd_oem_event_handler_cb(void *oem_event_data)
|
||||
static inline void hdd_oem_event_handler_cb(void *oem_event_data,
|
||||
uint8_t vdev_id)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -13971,7 +13971,6 @@ int hdd_register_cb(struct hdd_context *hdd_ctx)
|
|||
hdd_sme_close_session_callback,
|
||||
hdd_common_roam_callback);
|
||||
|
||||
sme_set_oem_data_event_handler_cb(mac_handle, hdd_oem_event_handler_cb);
|
||||
sme_set_roam_scan_ch_event_cb(mac_handle, hdd_get_roam_scan_ch_cb);
|
||||
status = sme_set_monitor_mode_cb(mac_handle,
|
||||
hdd_sme_monitor_mode_callback);
|
||||
|
|
@ -14005,8 +14004,6 @@ void hdd_deregister_cb(struct hdd_context *hdd_ctx)
|
|||
|
||||
mac_handle = hdd_ctx->mac_handle;
|
||||
|
||||
sme_reset_oem_data_event_handler_cb(mac_handle);
|
||||
|
||||
sme_deregister_tx_queue_cb(mac_handle);
|
||||
|
||||
sme_reset_link_layer_stats_ind_cb(mac_handle);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@
|
|||
#include "sme_api.h"
|
||||
#include "wlan_nlink_srv.h"
|
||||
#include "wlan_hdd_oemdata.h"
|
||||
|
||||
#include "wlan_osif_request_manager.h"
|
||||
#include "wlan_hdd_main.h"
|
||||
#ifdef FEATURE_OEM_DATA_SUPPORT
|
||||
#ifdef CNSS_GENL
|
||||
#include <net/cnss_nl.h>
|
||||
|
|
@ -1124,46 +1125,100 @@ oem_data_attr_policy[QCA_WLAN_VENDOR_ATTR_OEM_DATA_PARAMS_MAX + 1] = {
|
|||
.type = NLA_BINARY,
|
||||
.len = OEM_DATA_MAX_SIZE
|
||||
},
|
||||
|
||||
[QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED] = {.type = NLA_FLAG},
|
||||
};
|
||||
|
||||
void hdd_oem_event_handler_cb(const struct oem_data *oem_event_data)
|
||||
void hdd_oem_event_handler_cb(const struct oem_data *oem_event_data,
|
||||
uint8_t vdev_id)
|
||||
{
|
||||
struct sk_buff *vendor_event;
|
||||
struct osif_request *request;
|
||||
uint32_t len;
|
||||
int ret;
|
||||
struct oem_data *oem_data;
|
||||
struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
|
||||
|
||||
struct hdd_adapter *hdd_adapter = hdd_get_adapter_by_vdev(hdd_ctx,
|
||||
vdev_id);
|
||||
hdd_enter();
|
||||
|
||||
ret = wlan_hdd_validate_context(hdd_ctx);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
len = nla_total_size(oem_event_data->data_len) + NLMSG_HDRLEN;
|
||||
vendor_event =
|
||||
cfg80211_vendor_event_alloc(
|
||||
if (hdd_validate_adapter(hdd_adapter))
|
||||
return;
|
||||
|
||||
if (!oem_event_data || !(oem_event_data->data)) {
|
||||
hdd_err("Invalid oem event data");
|
||||
return;
|
||||
}
|
||||
|
||||
if (hdd_adapter->response_expected) {
|
||||
request = osif_request_get(hdd_adapter->cookie);
|
||||
if (!request) {
|
||||
hdd_err("Invalid request");
|
||||
return;
|
||||
}
|
||||
|
||||
oem_data = osif_request_priv(request);
|
||||
oem_data->data_len = oem_event_data->data_len;
|
||||
oem_data->data = qdf_mem_malloc(oem_data->data_len);
|
||||
if (!oem_data->data) {
|
||||
hdd_err("Memory allocation failure");
|
||||
return;
|
||||
}
|
||||
qdf_mem_copy(oem_data->data, oem_event_data->data,
|
||||
oem_data->data_len);
|
||||
oem_data->vdev_id = hdd_adapter->vdev_id;
|
||||
osif_request_complete(request);
|
||||
osif_request_put(request);
|
||||
} else {
|
||||
len = nla_total_size(oem_event_data->data_len) + NLMSG_HDRLEN;
|
||||
vendor_event =
|
||||
cfg80211_vendor_event_alloc(
|
||||
hdd_ctx->wiphy, NULL, len,
|
||||
QCA_NL80211_VENDOR_SUBCMD_OEM_DATA_INDEX,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!vendor_event) {
|
||||
hdd_err("cfg80211_vendor_event_alloc failed");
|
||||
return;
|
||||
}
|
||||
if (!vendor_event) {
|
||||
hdd_err("cfg80211_vendor_event_alloc failed");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA,
|
||||
oem_event_data->data_len, oem_event_data->data);
|
||||
if (ret) {
|
||||
hdd_err("OEM event put fails status %d", ret);
|
||||
kfree_skb(vendor_event);
|
||||
return;
|
||||
ret = nla_put(vendor_event,
|
||||
QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA,
|
||||
oem_event_data->data_len, oem_event_data->data);
|
||||
if (ret) {
|
||||
hdd_err("OEM event put fails status %d", ret);
|
||||
kfree_skb(vendor_event);
|
||||
return;
|
||||
}
|
||||
cfg80211_vendor_event(vendor_event, GFP_KERNEL);
|
||||
}
|
||||
|
||||
cfg80211_vendor_event(vendor_event, GFP_KERNEL);
|
||||
|
||||
hdd_exit();
|
||||
}
|
||||
|
||||
/**
|
||||
*wlan_hdd_free_oem_data: delete data of priv data
|
||||
*@priv: osif request private data
|
||||
*
|
||||
*Return: void
|
||||
*/
|
||||
static void wlan_hdd_free_oem_data(void *priv)
|
||||
{
|
||||
struct oem_data *local_priv = priv;
|
||||
|
||||
if (!local_priv)
|
||||
return;
|
||||
|
||||
if (local_priv->data) {
|
||||
qdf_mem_free(local_priv->data);
|
||||
local_priv->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* __wlan_hdd_cfg80211_oem_data_handler() - the handler for oem data
|
||||
* @wiphy: wiphy structure pointer
|
||||
|
|
@ -1179,17 +1234,34 @@ __wlan_hdd_cfg80211_oem_data_handler(struct wiphy *wiphy,
|
|||
const void *data, int data_len)
|
||||
{
|
||||
struct net_device *dev = wdev->netdev;
|
||||
QDF_STATUS status;
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
int ret;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct oem_data oem_data = {0};
|
||||
struct oem_data *get_oem_data = NULL;
|
||||
struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
|
||||
struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
|
||||
struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OEM_DATA_PARAMS_MAX + 1];
|
||||
struct osif_request *request = NULL;
|
||||
struct oem_data *priv;
|
||||
static const struct osif_request_params params = {
|
||||
.priv_size = sizeof(*priv),
|
||||
.timeout_ms = WLAN_WAIT_TIME_GET_OEM_DATA,
|
||||
.dealloc = wlan_hdd_free_oem_data,
|
||||
};
|
||||
|
||||
ret = wlan_hdd_validate_context(hdd_ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (hdd_validate_adapter(adapter))
|
||||
return -EINVAL;
|
||||
|
||||
if (adapter->oem_data_in_progress) {
|
||||
hdd_err("oem request already in progress");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (wlan_cfg80211_nla_parse(tb,
|
||||
QCA_WLAN_VENDOR_ATTR_OEM_DATA_PARAMS_MAX,
|
||||
data, data_len, oem_data_attr_policy)) {
|
||||
|
|
@ -1203,18 +1275,87 @@ __wlan_hdd_cfg80211_oem_data_handler(struct wiphy *wiphy,
|
|||
}
|
||||
|
||||
oem_data.data_len =
|
||||
nla_len(tb[QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA]);
|
||||
nla_len(tb[QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA]);
|
||||
if (!oem_data.data_len) {
|
||||
hdd_err("oem data len is 0!");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
oem_data.vdev_id = adapter->vdev_id;
|
||||
oem_data.data = nla_data(tb[QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA]);
|
||||
|
||||
status = sme_oem_data_cmd(hdd_ctx->mac_handle, &oem_data);
|
||||
if (tb[QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED])
|
||||
adapter->response_expected = nla_get_flag(
|
||||
tb[QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED]);
|
||||
|
||||
if (adapter->response_expected) {
|
||||
int skb_len = 0;
|
||||
|
||||
adapter->oem_data_in_progress = true;
|
||||
|
||||
request = osif_request_alloc(¶ms);
|
||||
if (!request) {
|
||||
hdd_err("request allocation failure");
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
adapter->cookie = osif_request_cookie(request);
|
||||
|
||||
status = sme_oem_data_cmd(hdd_ctx->mac_handle,
|
||||
hdd_oem_event_handler_cb,
|
||||
&oem_data, adapter->vdev_id);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
hdd_err("Failure while sending command to fw");
|
||||
ret = -EAGAIN;
|
||||
goto err;
|
||||
}
|
||||
ret = osif_request_wait_for_response(request);
|
||||
if (ret) {
|
||||
hdd_err("Timedout while retrieving oem get data");
|
||||
goto err;
|
||||
}
|
||||
|
||||
get_oem_data = osif_request_priv(request);
|
||||
if (!get_oem_data || !(get_oem_data->data)) {
|
||||
hdd_err("invalid get_oem_data");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
skb_len = NLMSG_HDRLEN + NLA_HDRLEN + get_oem_data->data_len;
|
||||
|
||||
skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
|
||||
skb_len);
|
||||
if (!skb) {
|
||||
hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA,
|
||||
get_oem_data->data_len, get_oem_data->data)) {
|
||||
hdd_err("nla put failure");
|
||||
kfree_skb(skb);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
wlan_cfg80211_vendor_cmd_reply(skb);
|
||||
|
||||
} else {
|
||||
status = sme_oem_data_cmd(hdd_ctx->mac_handle,
|
||||
hdd_oem_event_handler_cb,
|
||||
&oem_data, adapter->vdev_id);
|
||||
return qdf_status_to_os_return(status);
|
||||
}
|
||||
|
||||
err:
|
||||
if (request)
|
||||
osif_request_put(request);
|
||||
adapter->oem_data_in_progress = false;
|
||||
adapter->response_expected = false;
|
||||
|
||||
return ret;
|
||||
|
||||
return qdf_status_to_os_return(status);
|
||||
}
|
||||
|
||||
int wlan_hdd_cfg80211_oem_data_handler(struct wiphy *wiphy,
|
||||
|
|
|
|||
|
|
@ -768,12 +768,18 @@ QDF_STATUS sme_neighbor_report_request(mac_handle_t mac_handle,
|
|||
/**
|
||||
* sme_oem_data_cmd() - the wrapper to send oem data cmd to wma
|
||||
* @mac_handle: Opaque handle to the global MAC context.
|
||||
* @@oem_data_event_handler_cb: callback to be registered
|
||||
* @oem_data: the pointer of oem data
|
||||
* @vdev id: vdev id to fetch adapter
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS sme_oem_data_cmd(mac_handle_t mac_handle,
|
||||
struct oem_data *oem_data);
|
||||
void (*oem_data_event_handler_cb)
|
||||
(const struct oem_data *oem_event_data,
|
||||
uint8_t vdev_id),
|
||||
struct oem_data *oem_data,
|
||||
uint8_t vdev_id);
|
||||
#endif
|
||||
|
||||
#ifdef FEATURE_OEM_DATA_SUPPORT
|
||||
|
|
@ -4069,43 +4075,6 @@ QDF_STATUS sme_get_ani_level(mac_handle_t mac_handle, uint32_t *freqs,
|
|||
void *context), void *context);
|
||||
#endif /* FEATURE_ANI_LEVEL_REQUEST */
|
||||
|
||||
#ifdef FEATURE_OEM_DATA
|
||||
/**
|
||||
* sme_set_oem_data_event_handler_cb() - Register oem data event handler
|
||||
* callback
|
||||
* @mac_handle: Opaque handle to the MAC context
|
||||
* @oem_data_event_handler_cb: callback to be registered
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS sme_set_oem_data_event_handler_cb(
|
||||
mac_handle_t mac_handle,
|
||||
void (*oem_data_event_handler_cb)
|
||||
(const struct oem_data *oem_event_data));
|
||||
|
||||
/**
|
||||
* sme_reset_oem_data_event_handler_cb() - De-register oem data event handler
|
||||
* @mac_handle: Handler return by mac_open
|
||||
*
|
||||
* This function De-registers the OEM data event handler callback to SME
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void sme_reset_oem_data_event_handler_cb(mac_handle_t mac_handle);
|
||||
#else
|
||||
static inline QDF_STATUS sme_set_oem_data_event_handler_cb(
|
||||
mac_handle_t mac_handle,
|
||||
void (*oem_data_event_handler_cb)
|
||||
(void *oem_event_data))
|
||||
{
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static inline void sme_reset_oem_data_event_handler_cb(mac_handle_t mac_handle)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* sme_get_prev_connected_bss_ies() - Get the previous connected AP IEs
|
||||
* @mac_handle: The handle returned by mac_open.
|
||||
|
|
|
|||
|
|
@ -380,7 +380,9 @@ struct sme_context {
|
|||
#endif
|
||||
#ifdef FEATURE_OEM_DATA
|
||||
void (*oem_data_event_handler_cb)
|
||||
(const struct oem_data *oem_event_data);
|
||||
(const struct oem_data *oem_event_data,
|
||||
uint8_t vdev_id);
|
||||
uint8_t oem_data_vdev_id;
|
||||
#endif
|
||||
sme_get_raom_scan_ch_callback roam_scan_ch_callback;
|
||||
void *roam_scan_ch_get_context;
|
||||
|
|
|
|||
|
|
@ -3700,10 +3700,15 @@ QDF_STATUS sme_oem_req_cmd(mac_handle_t mac_handle,
|
|||
|
||||
#ifdef FEATURE_OEM_DATA
|
||||
QDF_STATUS sme_oem_data_cmd(mac_handle_t mac_handle,
|
||||
struct oem_data *oem_data)
|
||||
void (*oem_data_event_handler_cb)
|
||||
(const struct oem_data *oem_event_data,
|
||||
uint8_t vdev_id),
|
||||
struct oem_data *oem_data,
|
||||
uint8_t vdev_id)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
void *wma_handle;
|
||||
struct mac_context *mac = MAC_CONTEXT(mac_handle);
|
||||
|
||||
SME_ENTER();
|
||||
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
|
||||
|
|
@ -3712,6 +3717,12 @@ QDF_STATUS sme_oem_data_cmd(mac_handle_t mac_handle,
|
|||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
status = sme_acquire_global_lock(&mac->sme);
|
||||
if (QDF_IS_STATUS_SUCCESS(status)) {
|
||||
mac->sme.oem_data_event_handler_cb = oem_data_event_handler_cb;
|
||||
mac->sme.oem_data_vdev_id = vdev_id;
|
||||
sme_release_global_lock(&mac->sme);
|
||||
}
|
||||
status = wma_start_oem_data_cmd(wma_handle, oem_data);
|
||||
if (!QDF_IS_STATUS_SUCCESS(status))
|
||||
sme_err("fail to call wma_start_oem_data_cmd.");
|
||||
|
|
@ -16062,42 +16073,6 @@ QDF_STATUS sme_get_ani_level(mac_handle_t mac_handle, uint32_t *freqs,
|
|||
}
|
||||
#endif /* FEATURE_ANI_LEVEL_REQUEST */
|
||||
|
||||
#ifdef FEATURE_OEM_DATA
|
||||
QDF_STATUS sme_set_oem_data_event_handler_cb(
|
||||
mac_handle_t mac_handle,
|
||||
void (*oem_data_event_handler_cb)
|
||||
(const struct oem_data *oem_event_data))
|
||||
{
|
||||
struct mac_context *mac = MAC_CONTEXT(mac_handle);
|
||||
QDF_STATUS qdf_status;
|
||||
|
||||
qdf_status = sme_acquire_global_lock(&mac->sme);
|
||||
if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
|
||||
mac->sme.oem_data_event_handler_cb = oem_data_event_handler_cb;
|
||||
sme_release_global_lock(&mac->sme);
|
||||
}
|
||||
return qdf_status;
|
||||
}
|
||||
|
||||
void sme_reset_oem_data_event_handler_cb(mac_handle_t mac_handle)
|
||||
{
|
||||
struct mac_context *pmac;
|
||||
QDF_STATUS qdf_status;
|
||||
|
||||
if (!mac_handle) {
|
||||
sme_err("mac_handle is not valid");
|
||||
return;
|
||||
}
|
||||
pmac = MAC_CONTEXT(mac_handle);
|
||||
|
||||
qdf_status = sme_acquire_global_lock(&pmac->sme);
|
||||
if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
|
||||
pmac->sme.oem_data_event_handler_cb = NULL;
|
||||
sme_release_global_lock(&pmac->sme);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
QDF_STATUS sme_get_prev_connected_bss_ies(mac_handle_t mac_handle,
|
||||
uint8_t vdev_id,
|
||||
uint8_t **ies, uint32_t *ie_len)
|
||||
|
|
|
|||
|
|
@ -4950,8 +4950,9 @@ int wma_oem_event_handler(void *wma_ctx, uint8_t *event_buff, uint32_t len)
|
|||
|
||||
oem_event_data.data_len = event->data_len;
|
||||
oem_event_data.data = param_buf->data;
|
||||
|
||||
pmac->sme.oem_data_event_handler_cb(&oem_event_data);
|
||||
pmac->sme.oem_data_event_handler_cb(&oem_event_data,
|
||||
pmac->sme.oem_data_vdev_id);
|
||||
pmac->sme.oem_data_event_handler_cb = NULL;
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue