Browse Source

qcacmn: Add 2x2+1x1 DBS Action type

Add new DBS Action types and handle
the Actions in policy_mgr_next_actions
API.

Change-Id: Iccc62303383c0701955446a172ed956d1aea0e0f
CRs-Fixed: 2257692
Liangwei Dong 6 years ago
parent
commit
10a38dcc42

+ 40 - 0
umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h

@@ -1730,11 +1730,51 @@ bool policy_mgr_is_current_hwmode_dbs(struct wlan_objmgr_psoc *psoc);
  * DBS and there is no need for downgrading while entering DBS.
  *    true: DBS 2x2 can always be supported
  *    false: hw_modes support DBS 1x1 as well
+ * Genoa DBS 2x2 + 1x1 will not be included.
  *
  * Return: true - DBS2x2, false - DBS1x1
  */
 bool policy_mgr_is_hw_dbs_2x2_capable(struct wlan_objmgr_psoc *psoc);
 
+/*
+ * policy_mgr_is_2x2_1x1_dbs_capable() - check 2x2+1x1 DBS supported or not
+ * @psoc: PSOC object data
+ *
+ * This routine is called to check 2x2 5G + 1x1 2G (DBS1) or
+ * 2x2 2G + 1x1 5G (DBS2) support or not.
+ * Either DBS1 or DBS2 supported
+ *
+ * Return: true/false
+ */
+bool policy_mgr_is_2x2_1x1_dbs_capable(struct wlan_objmgr_psoc *psoc);
+
+/*
+ * policy_mgr_is_2x2_5G_1x1_2G_dbs_capable() - check Genoa DBS1 enabled or not
+ * @psoc: PSOC object data
+ *
+ * This routine is called to check support DBS1 or not.
+ * Notes: DBS1: 2x2 5G + 1x1 2G.
+ * This function will call policy_mgr_get_hw_mode_idx_from_dbs_hw_list to match
+ * the HW mode from hw mode list. The parameters will also be matched to
+ * 2x2 5G +2x2 2G HW mode. But firmware will not report 2x2 5G + 2x2 2G alone
+ * with 2x2 5G + 1x1 2G at same time. So, it is safe to find DBS1 with
+ * policy_mgr_get_hw_mode_idx_from_dbs_hw_list.
+ *
+ * Return: true/false
+ */
+bool policy_mgr_is_2x2_5G_1x1_2G_dbs_capable(struct wlan_objmgr_psoc *psoc);
+
+/*
+ * policy_mgr_is_2x2_2G_1x1_5G_dbs_capable() - check Genoa DBS2 enabled or not
+ * @psoc: PSOC object data
+ *
+ * This routine is called to check support DBS2 or not.
+ * Notes: DBS2: 2x2 2G + 1x1 5G
+ *
+ * Return: true/false
+ */
+bool policy_mgr_is_2x2_2G_1x1_5G_dbs_capable(struct wlan_objmgr_psoc *psoc);
+
 /**
  * policy_mgr_init() - Policy Manager component initialization
  *                 routine

+ 17 - 2
umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h

@@ -689,6 +689,12 @@ enum policy_mgr_two_connection_mode {
  * @PM_SBS_DOWNGRADE: switch to SBS mode & downgrade to 1x1
  * @PM_DOWNGRADE: downgrade to 1x1
  * @PM_UPGRADE: upgrade to 2x2
+ * @PM_DBS1: switch to DBS 1
+ * @PM_DBS1_DOWNGRADE: downgrade 2G beaconing entity to 1x1 and switch to DBS1.
+ * @PM_DBS2: switch to DBS 2
+ * @PM_DBS2_DOWNGRADE: downgrade 5G beaconing entity to 1x1 and switch to DBS2.
+ * @PM_UPGRADE_5G: upgrade 5g beaconing entity to 2x2.
+ * @PM_UPGRADE_2G: upgrade 2g beaconing entity to 2x2.
  * @PM_MAX_CONC_PRIORITY_MODE: Max place holder
  *
  * These are generic IDs that identify the various roles
@@ -705,6 +711,12 @@ enum policy_mgr_conc_next_action {
 	PM_SBS_DOWNGRADE,
 	PM_DOWNGRADE,
 	PM_UPGRADE,
+	PM_DBS1,
+	PM_DBS1_DOWNGRADE,
+	PM_DBS2,
+	PM_DBS2_DOWNGRADE,
+	PM_UPGRADE_5G,
+	PM_UPGRADE_2G,
 
 	PM_MAX_CONC_NEXT_ACTION
 };
@@ -882,8 +894,10 @@ struct policy_mgr_conc_connection_info {
  * @mac0_bw: MAC0 bandwidth
  * @mac1_bw: MAC1 bandwidth
  * @mac0_band_cap: mac0 band (5g/2g) capability
- * @dbs_cap: DBS capability
- * @agile_dfs_cap: Agile DFS capability
+ * @dbs_cap: DBS capabality
+ * @agile_dfs_cap: Agile DFS capabality
+ * @action_type: for dbs mode, the field indicates the "Action type" to be
+ * used to switch to the mode. To help the hw mode validation.
  */
 struct policy_mgr_hw_mode_params {
 	uint8_t mac0_tx_ss;
@@ -896,6 +910,7 @@ struct policy_mgr_hw_mode_params {
 	uint8_t dbs_cap;
 	uint8_t agile_dfs_cap;
 	uint8_t sbs_cap;
+	enum policy_mgr_conc_next_action action_type;
 };
 
 /**

+ 167 - 23
umac/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c

@@ -620,19 +620,32 @@ done:
 	return status;
 }
 
-QDF_STATUS policy_mgr_next_actions(struct wlan_objmgr_psoc *psoc,
+/**
+ * policy_mgr_validate_dbs_switch() - Check DBS action valid or not
+ * @psoc: Pointer to psoc
+ * @session_id: vdev id
+ * @action: action requested
+ * @reason: reason of hw mode change
+ *
+ * This routine will check the current hw mode with requested action.
+ * If we are already in the mode, the caller will do nothing.
+ * This will be called by policy_mgr_next_actions to check the action needed
+ * or not.
+ *
+ * return : QDF_STATUS_SUCCESS, action is allowed.
+ *          QDF_STATUS_E_ALREADY, action is not needed.
+ *          QDF_STATUS_E_FAILURE, error happens.
+ *          QDF_STATUS_E_NOSUPPORT, the requested mode not supported.
+ */
+static
+QDF_STATUS policy_mgr_validate_dbs_switch(
+		struct wlan_objmgr_psoc *psoc,
 		uint32_t session_id,
 		enum policy_mgr_conc_next_action action,
 		enum policy_mgr_conn_update_reason reason)
 {
-	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	QDF_STATUS status;
 	struct policy_mgr_hw_mode_params hw_mode;
-	struct dbs_nss nss_dbs = {0};
-
-	if (policy_mgr_is_hw_dbs_capable(psoc) == false) {
-		policy_mgr_err("driver isn't dbs capable, no further action needed");
-		return QDF_STATUS_E_NOSUPPORT;
-	}
 
 	/* check for the current HW index to see if really need any action */
 	status = policy_mgr_get_current_hw_mode(psoc, &hw_mode);
@@ -640,28 +653,95 @@ QDF_STATUS policy_mgr_next_actions(struct wlan_objmgr_psoc *psoc,
 		policy_mgr_err("policy_mgr_get_current_hw_mode failed");
 		return status;
 	}
+
+	if (hw_mode.sbs_cap) {
+		if ((action == PM_SBS) || (action == PM_SBS_DOWNGRADE)) {
+			if (!policy_mgr_is_hw_sbs_capable(psoc)) {
+				/* No action */
+				policy_mgr_notice("firmware is not sbs capable");
+				return QDF_STATUS_E_NOSUPPORT;
+			}
+			/* current mode is already SBS nothing to be
+			 * done
+			 */
+			 policy_mgr_notice("current mode is already SBS");
+			return QDF_STATUS_E_ALREADY;
+		} else {
+			return QDF_STATUS_SUCCESS;
+		}
+	}
+
+	if (!hw_mode.dbs_cap) {
+		if (action == PM_SINGLE_MAC ||
+		    action == PM_SINGLE_MAC_UPGRADE) {
+			policy_mgr_notice("current mode is already single MAC");
+			return QDF_STATUS_E_ALREADY;
+		} else {
+			return QDF_STATUS_SUCCESS;
+		}
+	}
 	/**
-	 *  if already in DBS no need to request DBS. Might be needed
-	 *  to extend the logic when multiple dbs HW mode is available
+	 * If already in DBS, no need to request DBS again (HL, Napier).
+	 * For dual DBS HW, in case DBS1 -> DBS2 or DBS2 -> DBS1
+	 * switching, we need to check the current DBS mode is same as
+	 * requested or not.
 	 */
-	if ((((PM_DBS_DOWNGRADE == action) || (PM_DBS == action) ||
-		(PM_DBS_UPGRADE == action))
-		&& hw_mode.dbs_cap)) {
+	if (policy_mgr_is_2x2_5G_1x1_2G_dbs_capable(psoc) ||
+	    policy_mgr_is_2x2_2G_1x1_5G_dbs_capable(psoc)) {
+		policy_mgr_info("curr dbs action %d new action %d",
+				hw_mode.action_type, action);
+		if (hw_mode.action_type == PM_DBS1 &&
+		    ((action == PM_DBS1 ||
+		    action == PM_DBS1_DOWNGRADE))) {
+			policy_mgr_err("driver is already in DBS_5G_2x2_24G_1x1 (%d), no further action %d needed",
+				       hw_mode.action_type, action);
+			return QDF_STATUS_E_ALREADY;
+		} else if (hw_mode.action_type == PM_DBS2 &&
+			   ((action == PM_DBS2 ||
+			   action == PM_DBS2_DOWNGRADE))) {
+			policy_mgr_err("driver is already in DBS_24G_2x2_5G_1x1 (%d), no further action %d needed",
+				       hw_mode.action_type, action);
+			return QDF_STATUS_E_ALREADY;
+		}
+	} else if ((action == PM_DBS_DOWNGRADE) || (action == PM_DBS) ||
+		   (action == PM_DBS_UPGRADE)) {
 		policy_mgr_err("driver is already in %s mode, no further action needed",
-				(hw_mode.dbs_cap) ? "dbs" : "non dbs");
+			       (hw_mode.dbs_cap) ? "dbs" : "non dbs");
 		return QDF_STATUS_E_ALREADY;
 	}
+	return QDF_STATUS_SUCCESS;
+}
 
-	if ((PM_SBS == action) || (action == PM_SBS_DOWNGRADE)) {
-		if (!policy_mgr_is_hw_sbs_capable(psoc)) {
-			/* No action */
-			policy_mgr_notice("firmware is not sbs capable");
-			return QDF_STATUS_E_NOSUPPORT;
-		}
-		/* check if current mode is already SBS nothing to be
-		 * done
-		 */
+QDF_STATUS policy_mgr_next_actions(
+		struct wlan_objmgr_psoc *psoc,
+		uint32_t session_id,
+		enum policy_mgr_conc_next_action action,
+		enum policy_mgr_conn_update_reason reason)
+{
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	struct dbs_nss nss_dbs = {0};
+	struct policy_mgr_hw_mode_params hw_mode;
+	enum policy_mgr_conc_next_action next_action;
 
+	if (policy_mgr_is_hw_dbs_capable(psoc) == false) {
+		policy_mgr_err("driver isn't dbs capable, no further action needed");
+		return QDF_STATUS_E_NOSUPPORT;
+	}
+
+	/* check for the current HW index to see if really need any action */
+	status = policy_mgr_get_current_hw_mode(psoc, &hw_mode);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		policy_mgr_err("policy_mgr_get_current_hw_mode failed");
+		return status;
+	}
+
+	/* check for the current HW index to see if really need any action */
+	status = policy_mgr_validate_dbs_switch(psoc, session_id, action,
+						reason);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		policy_mgr_err(" not take action %d reason %d session %d status %d",
+			       action, reason, session_id, status);
+		return status;
 	}
 
 	switch (action) {
@@ -755,6 +835,70 @@ QDF_STATUS policy_mgr_next_actions(struct wlan_objmgr_psoc *psoc,
 		status = policy_mgr_nss_update(psoc, POLICY_MGR_RX_NSS_2,
 					PM_NOP, POLICY_MGR_ANY, reason);
 		break;
+	case PM_DBS1_DOWNGRADE:
+		status = policy_mgr_complete_action(psoc, POLICY_MGR_RX_NSS_1,
+						    PM_DBS1, reason,
+						    session_id);
+		break;
+	case PM_DBS2_DOWNGRADE:
+		status = policy_mgr_complete_action(psoc, POLICY_MGR_RX_NSS_1,
+						    PM_DBS2, reason,
+						    session_id);
+		break;
+	case PM_DBS1:
+		/*
+		 * PM_DBS1 (2x2 5G + 1x1 2G) will support 5G 2x2. If previous
+		 * mode is DBS, that should be 2x2 2G + 1x1 5G mode and
+		 * the 5G band was downgraded to 1x1. So, we need to
+		 * upgrade 5G vdevs after hw mode change.
+		 */
+		if (hw_mode.dbs_cap)
+			next_action = PM_UPGRADE_5G;
+		else
+			next_action = PM_NOP;
+		status = policy_mgr_pdev_set_hw_mode(
+					psoc, session_id,
+					HW_MODE_SS_2x2,
+					HW_MODE_80_MHZ,
+					HW_MODE_SS_1x1, HW_MODE_40_MHZ,
+					HW_MODE_MAC_BAND_5G,
+					HW_MODE_DBS,
+					HW_MODE_AGILE_DFS_NONE,
+					HW_MODE_SBS_NONE,
+					reason, next_action);
+		break;
+	case PM_DBS2:
+		/*
+		 * PM_DBS2 (2x2 2G + 1x1 5G) will support 2G 2x2. If previous
+		 * mode is DBS, that should be 2x2 5G + 1x1 2G mode and
+		 * the 2G band was downgraded to 1x1. So, we need to
+		 * upgrade 5G vdevs after hw mode change.
+		 */
+		if (hw_mode.dbs_cap)
+			next_action = PM_UPGRADE_2G;
+		else
+			next_action = PM_NOP;
+		status = policy_mgr_pdev_set_hw_mode(
+						psoc, session_id,
+						HW_MODE_SS_2x2,
+						HW_MODE_40_MHZ,
+						HW_MODE_SS_1x1, HW_MODE_40_MHZ,
+						HW_MODE_MAC_BAND_2G,
+						HW_MODE_DBS,
+						HW_MODE_AGILE_DFS_NONE,
+						HW_MODE_SBS_NONE,
+						reason, next_action);
+		break;
+	case PM_UPGRADE_5G:
+		status = policy_mgr_nss_update(
+					psoc, POLICY_MGR_RX_NSS_2,
+					PM_NOP, POLICY_MGR_BAND_5, reason);
+		break;
+	case PM_UPGRADE_2G:
+		status = policy_mgr_nss_update(
+					psoc, POLICY_MGR_RX_NSS_2,
+					PM_NOP, POLICY_MGR_BAND_24, reason);
+		break;
 	default:
 		policy_mgr_err("unexpected action value %d", action);
 		status = QDF_STATUS_E_FAILURE;

+ 25 - 2
umac/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c

@@ -480,6 +480,8 @@ QDF_STATUS policy_mgr_get_hw_mode_from_idx(
 {
 	uint32_t param;
 	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	uint8_t mac0_min_ss;
+	uint8_t mac1_min_ss;
 	uint32_t i, hw_mode_id;
 
 	pm_ctx = policy_mgr_get_context(psoc);
@@ -514,7 +516,20 @@ QDF_STATUS policy_mgr_get_hw_mode_from_idx(
 	hw_mode->dbs_cap = POLICY_MGR_HW_MODE_DBS_MODE_GET(param);
 	hw_mode->agile_dfs_cap = POLICY_MGR_HW_MODE_AGILE_DFS_GET(param);
 	hw_mode->sbs_cap = POLICY_MGR_HW_MODE_SBS_MODE_GET(param);
-
+	if (hw_mode->dbs_cap) {
+		mac0_min_ss = QDF_MIN(hw_mode->mac0_tx_ss, hw_mode->mac0_rx_ss);
+		mac1_min_ss = QDF_MIN(hw_mode->mac1_tx_ss, hw_mode->mac1_rx_ss);
+		if (hw_mode->mac0_band_cap == WLAN_5G_CAPABILITY &&
+		    mac0_min_ss && mac1_min_ss &&
+		    mac0_min_ss > mac1_min_ss)
+			hw_mode->action_type = PM_DBS1;
+		else if (hw_mode->mac0_band_cap == WLAN_2G_CAPABILITY &&
+			 mac0_min_ss && mac1_min_ss &&
+			 mac0_min_ss > mac1_min_ss)
+			hw_mode->action_type = PM_DBS2;
+		else
+			hw_mode->action_type = PM_DBS;
+	}
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -2613,6 +2628,7 @@ QDF_STATUS policy_mgr_complete_action(struct wlan_objmgr_psoc *psoc,
 				uint32_t session_id)
 {
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	enum policy_mgr_band downgrade_band;
 
 	if (policy_mgr_is_hw_dbs_capable(psoc) == false) {
 		policy_mgr_err("driver isn't dbs capable, no further action needed");
@@ -2624,8 +2640,15 @@ QDF_STATUS policy_mgr_complete_action(struct wlan_objmgr_psoc *psoc,
 	 * protection. So, not taking any lock inside
 	 * policy_mgr_complete_action() during pm_conc_connection_list access.
 	 */
+	if (next_action == PM_DBS1)
+		downgrade_band = POLICY_MGR_BAND_24;
+	else if (next_action == PM_DBS2)
+		downgrade_band = POLICY_MGR_BAND_5;
+	else
+		downgrade_band = POLICY_MGR_ANY;
+
 	status = policy_mgr_nss_update(psoc, new_nss, next_action,
-				       POLICY_MGR_ANY, reason);
+				       downgrade_band, reason);
 	if (!QDF_IS_STATUS_SUCCESS(status))
 		status = policy_mgr_next_actions(psoc, session_id,
 						next_action, reason);

+ 79 - 2
umac/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c

@@ -769,9 +769,86 @@ bool policy_mgr_is_dbs_enable(struct wlan_objmgr_psoc *psoc)
 bool policy_mgr_is_hw_dbs_2x2_capable(struct wlan_objmgr_psoc *psoc)
 {
 	struct dbs_nss nss_dbs;
+	uint32_t nss;
 
-	return ((policy_mgr_get_hw_dbs_nss(psoc, &nss_dbs)) >= HW_MODE_SS_2x2)
-		? true : false;
+	nss = policy_mgr_get_hw_dbs_nss(psoc, &nss_dbs);
+	if (nss >= HW_MODE_SS_2x2 && (nss_dbs.mac0_ss == nss_dbs.mac1_ss))
+		return true;
+	else
+		return false;
+}
+
+/*
+ * policy_mgr_is_2x2_1x1_dbs_capable() - check 2x2+1x1 DBS supported or not
+ * @psoc: PSOC object data
+ *
+ * This routine is called to check 2x2 5G + 1x1 2G (DBS1) or
+ * 2x2 2G + 1x1 5G (DBS2) support or not.
+ * Either DBS1 or DBS2 supported
+ *
+ * Return: true/false
+ */
+bool policy_mgr_is_2x2_1x1_dbs_capable(struct wlan_objmgr_psoc *psoc)
+{
+	struct dbs_nss nss_dbs;
+	uint32_t nss;
+
+	nss = policy_mgr_get_hw_dbs_nss(psoc, &nss_dbs);
+	if (nss >= HW_MODE_SS_2x2 && (nss_dbs.mac0_ss > nss_dbs.mac1_ss))
+		return true;
+	else
+		return false;
+}
+
+/*
+ * policy_mgr_is_2x2_5G_1x1_2G_dbs_capable() - check Genoa DBS1 enabled or not
+ * @psoc: PSOC object data
+ *
+ * This routine is called to check support DBS1 or not.
+ * Notes: DBS1: 2x2 5G + 1x1 2G.
+ * This function will call policy_mgr_get_hw_mode_idx_from_dbs_hw_list to match
+ * the HW mode from hw mode list. The parameters will also be matched to
+ * 2x2 5G +2x2 2G HW mode. But firmware will not report 2x2 5G + 2x2 2G alone
+ * with 2x2 5G + 1x1 2G at same time. So, it is safe to find DBS1 with
+ * policy_mgr_get_hw_mode_idx_from_dbs_hw_list.
+ *
+ * Return: true/false
+ */
+bool policy_mgr_is_2x2_5G_1x1_2G_dbs_capable(struct wlan_objmgr_psoc *psoc)
+{
+	return policy_mgr_is_2x2_1x1_dbs_capable(psoc) &&
+		(policy_mgr_get_hw_mode_idx_from_dbs_hw_list(
+					psoc,
+					HW_MODE_SS_2x2,
+					HW_MODE_80_MHZ,
+					HW_MODE_SS_1x1, HW_MODE_40_MHZ,
+					HW_MODE_MAC_BAND_5G,
+					HW_MODE_DBS,
+					HW_MODE_AGILE_DFS_NONE,
+					HW_MODE_SBS_NONE) >= 0);
+}
+
+/*
+ * policy_mgr_is_2x2_2G_1x1_5G_dbs_capable() - check Genoa DBS2 enabled or not
+ * @psoc: PSOC object data
+ *
+ * This routine is called to check support DBS2 or not.
+ * Notes: DBS2: 2x2 2G + 1x1 5G
+ *
+ * Return: true/false
+ */
+bool policy_mgr_is_2x2_2G_1x1_5G_dbs_capable(struct wlan_objmgr_psoc *psoc)
+{
+	return policy_mgr_is_2x2_1x1_dbs_capable(psoc) &&
+		(policy_mgr_get_hw_mode_idx_from_dbs_hw_list(
+					psoc,
+					HW_MODE_SS_2x2,
+					HW_MODE_40_MHZ,
+					HW_MODE_SS_1x1, HW_MODE_40_MHZ,
+					HW_MODE_MAC_BAND_2G,
+					HW_MODE_DBS,
+					HW_MODE_AGILE_DFS_NONE,
+					HW_MODE_SBS_NONE) >= 0);
 }
 
 uint32_t policy_mgr_get_connection_count(struct wlan_objmgr_psoc *psoc)