Browse Source

qcacld-3.0: Add wow user pattern support in PMO

Add wow user pattern support in PMO.

Change-Id: I186e650e3a165ea0aeaada4bba880005c5be8b5f
CRs-Fixed: 2135644
Mukul Sharma 7 years ago
parent
commit
4a46599568

+ 79 - 5
pmo/core/inc/wlan_pmo_wow.h

@@ -175,6 +175,54 @@ static inline void pmo_decrement_wow_default_ptrn(
 	}
 }
 
+/**
+ * pmo_get_wow_default_ptrn() -Get wow default ptrn
+ * @vdev_ctx: pmo vdev priv ctx
+ *
+ * API to get wow default ptrn
+ *
+ * Return: current wow default ptrn count
+ */
+static inline uint8_t pmo_get_wow_default_ptrn(
+		struct pmo_vdev_priv_obj *vdev_ctx)
+{
+	uint8_t count;
+
+	if (vdev_ctx->pmo_psoc_ctx->psoc_cfg.ptrn_id_per_vdev) {
+		qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
+		count = vdev_ctx->num_wow_default_patterns;
+		qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
+	} else {
+		qdf_spin_lock_bh(&vdev_ctx->pmo_psoc_ctx->lock);
+		count = vdev_ctx->pmo_psoc_ctx->wow.ptrn_id_def;
+		qdf_spin_unlock_bh(&vdev_ctx->pmo_psoc_ctx->lock);
+	}
+
+	return count;
+}
+
+/**
+ * pmo_get_wow_default_ptrn() -Set wow default ptrn
+ * @vdev_ctx: pmo vdev priv ctx
+ *
+ * API to set wow default ptrn
+ *
+ * Return: Set wow default ptrn count
+ */
+static inline void pmo_set_wow_default_ptrn(
+		struct pmo_vdev_priv_obj *vdev_ctx, uint8_t value)
+{
+	if (vdev_ctx->pmo_psoc_ctx->psoc_cfg.ptrn_id_per_vdev) {
+		qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
+		vdev_ctx->num_wow_default_patterns = value;
+		qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
+	} else {
+		qdf_spin_lock_bh(&vdev_ctx->pmo_psoc_ctx->lock);
+		vdev_ctx->pmo_psoc_ctx->wow.ptrn_id_def = value;
+		qdf_spin_unlock_bh(&vdev_ctx->pmo_psoc_ctx->lock);
+	}
+}
+
 /**
  * pmo_increment_wow_user_ptrn() -increment wow user ptrn
  * @vdev_ctx: pmo vdev priv ctx
@@ -219,6 +267,32 @@ static inline void pmo_decrement_wow_user_ptrn(
 	}
 }
 
+/**
+ * pmo_get_wow_user_ptrn() -Get wow user ptrn
+ * @vdev_ctx: pmo vdev priv ctx
+ *
+ * API to Get wow user ptrn
+ *
+ * Return: None
+ */
+static inline uint8_t pmo_get_wow_user_ptrn(
+		struct pmo_vdev_priv_obj *vdev_ctx)
+{
+	uint8_t count;
+
+	if (vdev_ctx->pmo_psoc_ctx->psoc_cfg.ptrn_id_per_vdev) {
+		qdf_spin_lock_bh(&vdev_ctx->pmo_vdev_lock);
+		count = vdev_ctx->num_wow_user_patterns;
+		qdf_spin_unlock_bh(&vdev_ctx->pmo_vdev_lock);
+	} else {
+		qdf_spin_lock_bh(&vdev_ctx->pmo_psoc_ctx->lock);
+		count = vdev_ctx->pmo_psoc_ctx->wow.ptrn_id_usr;
+		qdf_spin_unlock_bh(&vdev_ctx->pmo_psoc_ctx->lock);
+	}
+
+	return count;
+}
+
 void pmo_dump_wow_ptrn(struct pmo_wow_add_pattern *ptrn);
 
 /**
@@ -229,18 +303,18 @@ void pmo_dump_wow_ptrn(struct pmo_wow_add_pattern *ptrn);
  *
  * Return: false if any errors encountered, QDF_STATUS_SUCCESS otherwise
  */
-QDF_STATUS pmo_core_add_wow_pattern(struct wlan_objmgr_vdev *vdev,
-		const char *ptrn);
+QDF_STATUS pmo_core_add_wow_user_pattern(struct wlan_objmgr_vdev *vdev,
+			struct pmo_wow_add_pattern *ptrn);
 
 /**
  * pmo_core_del_wow_pattern() - Function which will delete the WoWL pattern
  * @vdev: pointer to the vdev
- * @ptrn: pointer to the pattern string to be added
+ * @ptrn: pointer to the pattern string to be delete
  *
  * Return: error if any errors encountered, QDF_STATUS_SUCCESS otherwise
  */
-QDF_STATUS pmo_core_del_wow_pattern(struct wlan_objmgr_vdev *vdev,
-		const char *ptrn);
+QDF_STATUS pmo_core_del_wow_user_pattern(struct wlan_objmgr_vdev *vdev,
+			uint8_t pattern_id);
 
 /**
  * pmo_core_wow_enter() - store enable/disable status for pattern

+ 89 - 14
pmo/core/src/wlan_pmo_wow.c

@@ -27,30 +27,105 @@
 #include "wlan_pmo_static_config.h"
 #include "wlan_reg_services_api.h"
 
-static inline int pmo_find_wow_ptrn_len(const char *ptrn)
+QDF_STATUS pmo_core_add_wow_user_pattern(struct wlan_objmgr_vdev *vdev,
+		struct pmo_wow_add_pattern *ptrn)
 {
-	int len = 0;
+	QDF_STATUS status;
+	uint8_t id;
+	uint8_t bit_to_check, pos;
+	uint8_t new_mask[PMO_WOWL_BCAST_PATTERN_MAX_SIZE];
+	struct pmo_vdev_priv_obj *vdev_ctx;
+
+	status = pmo_vdev_get_ref(vdev);
+	if (QDF_IS_STATUS_ERROR(status))
+		goto out;
 
-	while (*ptrn != '\0' && *ptrn != PMO_WOW_INTER_PTRN_TOKENIZER) {
-		len++;
-		ptrn++;
+	vdev_ctx = pmo_vdev_get_priv(vdev);
+
+	/* clear all default patterns cofigured by pmo */
+	for (id = 0; id < pmo_get_wow_default_ptrn(vdev_ctx); id++)
+		pmo_tgt_del_wow_pattern(vdev, id, false);
+
+	pmo_set_wow_default_ptrn(vdev_ctx, 0);
+
+	pmo_debug("Add user passed wow pattern id %d vdev id %d",
+		ptrn->pattern_id, ptrn->session_id);
+	/*
+	 * Convert received pattern mask value from bit representation
+	 * to byte representation.
+	 *
+	 * For example, received value from umac,
+	 *
+	 *      Mask value    : A1 (equivalent binary is "1010 0001")
+	 *      Pattern value : 12:00:13:00:00:00:00:44
+	 *
+	 * The value which goes to FW after the conversion from this
+	 * function (1 in mask value will become FF and 0 will
+	 * become 00),
+	 *
+	 *      Mask value    : FF:00:FF:00:0:00:00:FF
+	 *      Pattern value : 12:00:13:00:00:00:00:44
+	 */
+	qdf_mem_zero(new_mask, sizeof(new_mask));
+	for (pos = 0; pos < ptrn->pattern_size; pos++) {
+		bit_to_check = (PMO_NUM_BITS_IN_BYTE - 1) -
+			       (pos % PMO_NUM_BITS_IN_BYTE);
+		bit_to_check = 0x1 << bit_to_check;
+		if (ptrn->pattern_mask[pos / PMO_NUM_BITS_IN_BYTE] &
+							bit_to_check)
+			new_mask[pos] = PMO_WOW_PTRN_MASK_VALID;
 	}
 
-	return len;
-}
+	status = pmo_tgt_send_wow_patterns_to_fw(vdev,
+			ptrn->pattern_id,
+			ptrn->pattern, ptrn->pattern_size,
+			ptrn->pattern_byte_offset, new_mask,
+			ptrn->pattern_size, true);
+	if (status != QDF_STATUS_SUCCESS)
+		pmo_err("Failed to add wow pattern %d", ptrn->pattern_id);
 
-QDF_STATUS pmo_core_add_wow_pattern(struct wlan_objmgr_vdev *vdev,
-		const char *ptrn)
-{
-	return QDF_STATUS_SUCCESS;
+	pmo_vdev_put_ref(vdev);
+out:
+	PMO_EXIT();
+
+	return status;
 }
 
-QDF_STATUS pmo_core_del_wow_pattern(struct wlan_objmgr_vdev *vdev,
-		const char *ptrn)
+QDF_STATUS pmo_core_del_wow_user_pattern(struct wlan_objmgr_vdev *vdev,
+		uint8_t pattern_id)
 {
-	return QDF_STATUS_SUCCESS;
+	QDF_STATUS status;
+	struct pmo_vdev_priv_obj *vdev_ctx;
+
+	status = pmo_vdev_get_ref(vdev);
+	if (QDF_IS_STATUS_ERROR(status))
+		goto out;
+
+	vdev_ctx = pmo_vdev_get_priv(vdev);
+	if (pmo_get_wow_user_ptrn(vdev_ctx) <= 0) {
+		pmo_err("No valid user pattern. Num user pattern %u",
+			pmo_get_wow_user_ptrn(vdev_ctx));
+		status = QDF_STATUS_E_INVAL;
+		goto rel_ref;
+	}
+
+	pmo_debug("Delete user passed wow pattern id %d total user pattern %d",
+		pattern_id, pmo_get_wow_user_ptrn(vdev_ctx));
+
+	pmo_tgt_del_wow_pattern(vdev, pattern_id, true);
+
+	/* configure default patterns once all user patterns are deleted */
+	if (!pmo_get_wow_user_ptrn(vdev_ctx))
+		pmo_register_wow_default_patterns(vdev);
+rel_ref:
+	pmo_vdev_put_ref(vdev);
+out:
+	PMO_EXIT();
+
+	return status;
 }
 
+
 QDF_STATUS pmo_core_wow_enter(struct wlan_objmgr_vdev *vdev,
 		struct pmo_wow_enter_params *wow_enter_param)
 {

+ 3 - 0
pmo/dispatcher/inc/wlan_pmo_obj_mgmt_public_struct.h

@@ -74,6 +74,7 @@ int (*pmo_pld_auto_resume_cb)(void);
  * @send_enable_wakeup_event_req: fp to send enable wow wakeup events req
  * @send_disable_wakeup_event_req: fp to send disable wow wakeup events req
  * @send_add_wow_pattern: fp to send wow pattern request
+ * @del_wow_pattern: fp to delete wow pattern from firmware
  * @send_enhance_mc_offload_req: fp to send enhanced multicast offload request
  * @send_set_mc_filter_req: fp to send set mc filter request
  * @send_clear_mc_filter_req: fp to send clear mc filter request
@@ -128,6 +129,8 @@ struct wlan_pmo_tx_ops {
 			uint8_t ptrn_id, const uint8_t *ptrn, uint8_t ptrn_len,
 			uint8_t ptrn_offset, const uint8_t *mask,
 			uint8_t mask_len, bool user);
+	QDF_STATUS (*del_wow_pattern)(
+			struct wlan_objmgr_vdev *vdev, uint8_t ptrn_id);
 	QDF_STATUS (*send_enhance_mc_offload_req)(
 			struct wlan_objmgr_vdev *vdev, bool enable);
 	QDF_STATUS (*send_set_mc_filter_req)(

+ 4 - 0
pmo/dispatcher/inc/wlan_pmo_tgt_api.h

@@ -150,6 +150,10 @@ QDF_STATUS pmo_tgt_send_wow_patterns_to_fw(struct wlan_objmgr_vdev *vdev,
 		uint8_t ptrn_offset, const uint8_t *mask,
 		uint8_t mask_len, bool user);
 
+QDF_STATUS pmo_tgt_del_wow_pattern(
+		struct wlan_objmgr_vdev *vdev, uint8_t ptrn_id,
+		bool user);
+
 /**
  * pmo_tgt_set_mc_filter_req() - Set mcast filter command to fw
  * @vdev: objmgr vdev

+ 6 - 0
pmo/dispatcher/inc/wlan_pmo_ucfg_api.h

@@ -529,6 +529,12 @@ QDF_STATUS pmo_ucfg_psoc_bus_runtime_resume(struct wlan_objmgr_psoc *psoc,
 QDF_STATUS pmo_ucfg_psoc_suspend_target(struct wlan_objmgr_psoc *psoc,
 		int disable_target_intr);
 
+QDF_STATUS pmo_ucfg_add_wow_user_pattern(struct wlan_objmgr_vdev *vdev,
+		struct pmo_wow_add_pattern *ptrn);
+
+QDF_STATUS pmo_ucfg_del_wow_user_pattern(struct wlan_objmgr_vdev *vdev,
+		uint8_t pattern_id);
+
 /**
  * pmo_ucfg_psoc_bus_resume() -handle bus resume request for psoc
  * @psoc: objmgr psoc handle

+ 3 - 0
pmo/dispatcher/inc/wlan_pmo_wow_public_struct.h

@@ -36,6 +36,9 @@
 #define PMO_WOW_INTER_PTRN_TOKENIZER   ';'
 #define PMO_WOW_INTRA_PTRN_TOKENIZER   ':'
 
+#define PMO_WOW_PTRN_MASK_VALID     0xFF
+#define PMO_NUM_BITS_IN_BYTE           8
+
 
 /* Action frame categories */
 

+ 34 - 1
pmo/dispatcher/src/wlan_pmo_tgt_wow.c

@@ -107,7 +107,7 @@ QDF_STATUS pmo_tgt_send_wow_patterns_to_fw(
 	if (status != QDF_STATUS_SUCCESS) {
 		if (!user)
 			pmo_decrement_wow_default_ptrn(vdev_ctx);
-		pmo_err("Failed to sen wow pattern event");
+		pmo_err("Failed to send wow pattern event");
 		goto out;
 	}
 
@@ -119,3 +119,36 @@ out:
 	return status;
 }
 
+QDF_STATUS pmo_tgt_del_wow_pattern(
+		struct wlan_objmgr_vdev *vdev, uint8_t ptrn_id,
+		bool user)
+{
+	QDF_STATUS status;
+	struct pmo_vdev_priv_obj *vdev_ctx;
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_pmo_tx_ops pmo_tx_ops;
+
+	PMO_ENTER();
+	psoc = pmo_vdev_get_psoc(vdev);
+	vdev_ctx = pmo_vdev_get_priv(vdev);
+
+	pmo_tx_ops = GET_PMO_TX_OPS_FROM_PSOC(psoc);
+	if (!pmo_tx_ops.del_wow_pattern) {
+		pmo_err("del_wow_pattern is null");
+		status = QDF_STATUS_E_NULL_VALUE;
+		goto out;
+	}
+	status = pmo_tx_ops.del_wow_pattern(vdev, ptrn_id);
+	if (status) {
+		status = QDF_STATUS_E_FAILURE;
+		goto out;
+	}
+
+	if (user)
+		pmo_decrement_wow_user_ptrn(vdev_ctx);
+out:
+	PMO_EXIT();
+
+	return status;
+}
+

+ 12 - 0
pmo/dispatcher/src/wlan_pmo_ucfg_api.c

@@ -298,6 +298,18 @@ QDF_STATUS pmo_ucfg_psoc_suspend_target(struct wlan_objmgr_psoc *psoc,
 	return pmo_core_psoc_suspend_target(psoc, disable_target_intr);
 }
 
+QDF_STATUS pmo_ucfg_add_wow_user_pattern(struct wlan_objmgr_vdev *vdev,
+		struct pmo_wow_add_pattern *ptrn)
+{
+	return pmo_core_add_wow_user_pattern(vdev, ptrn);
+}
+
+QDF_STATUS pmo_ucfg_del_wow_user_pattern(struct wlan_objmgr_vdev *vdev,
+		uint8_t pattern_id)
+{
+	return pmo_core_del_wow_user_pattern(vdev, pattern_id);
+}
+
 QDF_STATUS pmo_ucfg_psoc_bus_resume_req(struct wlan_objmgr_psoc *psoc,
 		enum qdf_suspend_type type)
 {

+ 3 - 0
target_if/pmo/inc/target_if_pmo.h

@@ -69,6 +69,9 @@ QDF_STATUS target_if_pmo_send_wow_patterns_to_fw(struct wlan_objmgr_vdev *vdev,
 		uint8_t ptrn_offset, const uint8_t *mask,
 		uint8_t mask_len, bool user);
 
+QDF_STATUS target_if_pmo_del_wow_patterns_to_fw(struct wlan_objmgr_vdev *vdev,
+		uint8_t ptrn_id);
+
 /**
  * target_if_pmo_send_enhance_mc_offload_req() - send enhance mc offload req
  * @vdev: objmgr vdev

+ 2 - 0
target_if/pmo/src/target_if_pmo_main.c

@@ -43,6 +43,8 @@ void target_if_pmo_register_tx_ops(struct wlan_pmo_tx_ops *pmo_tx_ops)
 		target_if_pmo_disable_wow_wakeup_event;
 	pmo_tx_ops->send_add_wow_pattern =
 		target_if_pmo_send_wow_patterns_to_fw;
+	pmo_tx_ops->del_wow_pattern =
+		target_if_pmo_del_wow_patterns_to_fw;
 	pmo_tx_ops->send_enhance_mc_offload_req =
 		target_if_pmo_send_enhance_mc_offload_req;
 	pmo_tx_ops->send_set_mc_filter_req =

+ 26 - 0
target_if/pmo/src/target_if_pmo_wow.c

@@ -112,3 +112,29 @@ QDF_STATUS target_if_pmo_send_wow_patterns_to_fw(struct wlan_objmgr_vdev *vdev,
 	return status;
 }
 
+QDF_STATUS target_if_pmo_del_wow_patterns_to_fw(struct wlan_objmgr_vdev *vdev,
+		uint8_t ptrn_id)
+{
+	uint8_t vdev_id;
+	struct wlan_objmgr_psoc *psoc;
+	QDF_STATUS status;
+
+	if (!vdev) {
+		target_if_err("vdev ptr passed is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	vdev_id = wlan_vdev_get_id(vdev);
+	if (!psoc) {
+		target_if_err("psoc handle is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	status = wmi_unified_wow_delete_pattern_cmd(
+				GET_WMI_HDL_FROM_PSOC(psoc), ptrn_id,
+				vdev_id);
+
+	return status;
+}
+