Browse Source

qcacld-3.0: Add support for OEM async event from FW

Add handle for OEM data async event from FW sends to userspace

Change-Id: I8104dde974f3b4b4eb9a409235b3b0da4cc97857
CRs-Fixed: 3216034
Vinod Kumar Myadam 2 years ago
parent
commit
b4520fdd7d

+ 13 - 1
core/hdd/inc/wlan_hdd_oemdata.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -284,6 +285,14 @@ extern const struct nla_policy
 #endif
 
 #ifdef FEATURE_OEM_DATA
+/**
+ * hdd_oem_event_async_cb() - callback for oem data async event
+ * @oem_event_data: oem data received in the event from the FW
+ *
+ * Return: None
+ */
+void hdd_oem_event_async_cb(const struct oem_data *oem_event_data);
+
 /**
  * hdd_oem_event_handler_cb() - callback for oem data event
  * @oem_event_data: oem data received in the event from the FW
@@ -298,6 +307,9 @@ static inline void hdd_oem_event_handler_cb(void *oem_event_data,
 					    uint8_t vdev_id)
 {
 }
-#endif
 
+static inline void hdd_oem_event_async_cb(void *oem_event_data)
+{
+}
+#endif
 #endif /* __WLAN_HDD_OEM_DATA_H__ */

+ 5 - 0
core/hdd/src/wlan_hdd_main.c

@@ -166,6 +166,8 @@
 #include "pld_common.h"
 #include "wlan_hdd_pre_cac.h"
 
+#include "sme_api.h"
+
 #ifdef CNSS_GENL
 #ifdef CONFIG_CNSS_OUT_OF_TREE
 #include "cnss_nl.h"
@@ -15226,6 +15228,8 @@ static int hdd_features_init(struct hdd_context *hdd_ctx)
 	hdd_thermal_stats_cmd_init(hdd_ctx);
 	sme_set_cal_failure_event_cb(hdd_ctx->mac_handle,
 				     hdd_cal_fail_send_event);
+	sme_async_oem_event_init(hdd_ctx->mac_handle,
+				 hdd_oem_event_async_cb);
 
 	hdd_exit();
 	return 0;
@@ -15241,6 +15245,7 @@ static int hdd_features_init(struct hdd_context *hdd_ctx)
  */
 static void hdd_features_deinit(struct hdd_context *hdd_ctx)
 {
+	sme_async_oem_event_deinit(hdd_ctx->mac_handle);
 	wlan_hdd_gpio_wakeup_deinit(hdd_ctx);
 	wlan_hdd_twt_deinit(hdd_ctx);
 	wlan_hdd_deinit_chan_info(hdd_ctx);

+ 36 - 0
core/hdd/src/wlan_hdd_oemdata.c

@@ -1133,6 +1133,41 @@ oem_data_attr_policy[QCA_WLAN_VENDOR_ATTR_OEM_DATA_PARAMS_MAX + 1] = {
 	[QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED] = {.type = NLA_FLAG},
 };
 
+void hdd_oem_event_async_cb(const struct oem_data *oem_event_data)
+{
+	struct sk_buff *vendor_event;
+	uint32_t len;
+	int ret;
+	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+
+	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(
+				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;
+	}
+
+	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);
+	hdd_exit();
+}
+
 void hdd_oem_event_handler_cb(const struct oem_data *oem_event_data,
 			      uint8_t vdev_id)
 {
@@ -1199,6 +1234,7 @@ void hdd_oem_event_handler_cb(const struct oem_data *oem_event_data,
 		}
 		cfg80211_vendor_event(vendor_event, GFP_KERNEL);
 	}
+	sme_oem_event_deinit(hdd_ctx->mac_handle);
 
 	hdd_exit();
 }

+ 38 - 0
core/sme/inc/sme_api.h

@@ -800,6 +800,43 @@ QDF_STATUS sme_oem_data_cmd(mac_handle_t mac_handle,
 			     uint8_t vdev_id),
 			     struct oem_data *oem_data,
 			     uint8_t vdev_id);
+
+/**
+ * sme_oem_event_deinit() - function to deregister cb for oem event
+ * @mac_handle: Opaque handle to the global MAC context
+ *
+ * Return: None
+ */
+void sme_oem_event_deinit(mac_handle_t mac_handle);
+
+/**
+ * sme_async_oem_event_init() - function to register cb for async oem event
+ * @mac_handle: Opaque handle to the global MAC context
+ * @@oem_data_async_event_handler_cb: callback to be registered
+ *
+ * Return: None
+ */
+void sme_async_oem_event_init(mac_handle_t mac_handle,
+			      void (*oem_data_async_event_handler_cb)
+			      (const struct oem_data *oem_event_data));
+/**
+ * sme_async_oem_event_deinit() - function to deregister cb for async oem event
+ * @mac_handle: Opaque handle to the global MAC context
+ *
+ * Return: None
+ */
+void sme_async_oem_event_deinit(mac_handle_t mac_handle);
+#else
+static inline void sme_async_oem_event_init(
+				mac_handle_t mac_handle,
+				void (*oem_data_async_event_handler_cb)
+				(void *oem_event_data))
+{
+}
+
+static inline void sme_async_oem_event_deinit(mac_handle_t mac_handle)
+{
+}
 #endif
 
 #ifdef FEATURE_OEM_DATA_SUPPORT
@@ -4572,4 +4609,5 @@ QDF_STATUS sme_send_channel_change_req(mac_handle_t mac_handle,
 QDF_STATUS sme_update_beacon_country_ie(mac_handle_t mac_handle,
 					uint8_t vdev_id,
 					bool country_ie_for_all_band);
+
 #endif /* #if !defined( __SME_API_H ) */

+ 3 - 0
core/sme/inc/sme_internal.h

@@ -502,6 +502,9 @@ struct sme_context {
 			(const struct oem_data *oem_event_data,
 			 uint8_t vdev_id);
 	uint8_t oem_data_vdev_id;
+	/* async oem event callback */
+	void (*oem_data_async_event_handler_cb)
+			(const struct oem_data *oem_event_data);
 #endif
 
 #ifdef MULTI_CLIENT_LL_SUPPORT

+ 52 - 0
core/sme/src/common/sme_api.c

@@ -3965,6 +3965,58 @@ QDF_STATUS sme_oem_data_cmd(mac_handle_t mac_handle,
 	SME_EXIT();
 	return status;
 }
+
+void sme_oem_event_deinit(mac_handle_t mac_handle)
+{
+	QDF_STATUS status;
+	struct mac_context *mac = MAC_CONTEXT(mac_handle);
+
+	SME_ENTER();
+
+	status = sme_acquire_global_lock(&mac->sme);
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		mac->sme.oem_data_event_handler_cb = NULL;
+		mac->sme.oem_data_vdev_id = WMA_INVALID_VDEV_ID;
+		sme_release_global_lock(&mac->sme);
+	}
+
+	SME_EXIT();
+}
+
+void sme_async_oem_event_init(mac_handle_t mac_handle,
+			      void (*oem_data_async_event_handler_cb)
+			      (const struct oem_data *oem_event_data))
+{
+	QDF_STATUS status;
+	struct mac_context *mac = MAC_CONTEXT(mac_handle);
+
+	SME_ENTER();
+
+	status = sme_acquire_global_lock(&mac->sme);
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		mac->sme.oem_data_async_event_handler_cb =
+		oem_data_async_event_handler_cb;
+		sme_release_global_lock(&mac->sme);
+	}
+
+	SME_EXIT();
+}
+
+void sme_async_oem_event_deinit(mac_handle_t mac_handle)
+{
+	QDF_STATUS status;
+	struct mac_context *mac = MAC_CONTEXT(mac_handle);
+
+	SME_ENTER();
+
+	status = sme_acquire_global_lock(&mac->sme);
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		mac->sme.oem_data_async_event_handler_cb = NULL;
+		sme_release_global_lock(&mac->sme);
+	}
+
+	SME_EXIT();
+}
 #endif
 
 #define STA_NSS_CHAINS_SHIFT               0

+ 6 - 7
core/wma/src/wma_utils.c

@@ -5014,11 +5014,6 @@ int wma_oem_event_handler(void *wma_ctx, uint8_t *event_buff, uint32_t len)
 		return -EINVAL;
 	}
 
-	if (!pmac->sme.oem_data_event_handler_cb) {
-		wma_err("oem data handler cb is not registered");
-		return -EINVAL;
-	}
-
 	param_buf =
 		   (WMI_OEM_DATA_EVENTID_param_tlvs *)event_buff;
 	if (!param_buf) {
@@ -5040,8 +5035,12 @@ 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_vdev_id);
+
+	if (pmac->sme.oem_data_event_handler_cb)
+		pmac->sme.oem_data_event_handler_cb(&oem_event_data,
+						    pmac->sme.oem_data_vdev_id);
+	else if (pmac->sme.oem_data_async_event_handler_cb)
+		pmac->sme.oem_data_async_event_handler_cb(&oem_event_data);
 
 	return QDF_STATUS_SUCCESS;
 }