qcacld-3.0: set the limit off-channel command parameters
Set the limit off-channel command parameters and conc_system_pref
according to active tos indication from application.
CRs-Fixed: 2066088
Change-Id: I896999adb59aa468daf33364c708d95ef3062018
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index 5368f07..45bed11 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -1543,6 +1543,36 @@
struct completion response_event;
};
+/**
+ * tos - Type of service requested by the application
+ * TOS_BK: Back ground traffic
+ * TOS_BE: Best effort traffic
+ * TOS_VI: Video traffic
+ * TOS_VO: Voice traffic
+ */
+enum tos {
+ TOS_BK = 0,
+ TOS_BE = 1,
+ TOS_VI = 2,
+ TOS_VO = 3,
+};
+
+#define HDD_AC_BK_BIT 1
+#define HDD_AC_BE_BIT 2
+#define HDD_AC_VI_BIT 4
+#define HDD_AC_VO_BIT 8
+
+#define HDD_MAX_OFF_CHAN_TIME_FOR_VO 20
+#define HDD_MAX_OFF_CHAN_TIME_FOR_VI 20
+#define HDD_MAX_OFF_CHAN_TIME_FOR_BE 40
+#define HDD_MAX_OFF_CHAN_TIME_FOR_BK 40
+
+#define HDD_MAX_AC 4
+#define HDD_MAX_OFF_CHAN_ENTRIES 2
+
+#define HDD_AC_BIT_INDX 0
+#define HDD_DWELL_TIME_INDX 1
+
/** Adapter structure definition */
struct hdd_context {
/** Global CDS context */
@@ -1844,6 +1874,7 @@
uint8_t bt_vo_active:1;
struct hdd_nud_stats_context nud_stats_context;
eCsrBand curr_band;
+ uint8_t active_ac;
};
/**
@@ -2827,4 +2858,17 @@
*/
void hdd_dp_trace_init(struct hdd_config *config);
+/**
+ * hdd_set_limit_off_chan_for_tos() - set limit off-chan command parameters
+ * @adapter: pointer adapter context
+ * @tos: type of service
+ * @status: status of the traffic (active/inactive)
+ *
+ * This function updates the limit off-channel command parameters to WMA
+ *
+ * Return: 0 on success or non zero value on failure
+ */
+int hdd_set_limit_off_chan_for_tos(struct hdd_adapter *adapter, enum tos tos,
+ bool is_tos_active);
+
#endif /* end #if !defined(WLAN_HDD_MAIN_H) */
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index 6b776f9..c174b2d 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -255,6 +255,13 @@
[QDF_MODULE_ID_DFS] = {QDF_TRACE_LEVEL_ALL},
};
+int limit_off_chan_tbl[HDD_MAX_AC][HDD_MAX_OFF_CHAN_ENTRIES] = {
+ { HDD_AC_BK_BIT, HDD_MAX_OFF_CHAN_TIME_FOR_BK },
+ { HDD_AC_BE_BIT, HDD_MAX_OFF_CHAN_TIME_FOR_BE },
+ { HDD_AC_VI_BIT, HDD_MAX_OFF_CHAN_TIME_FOR_VI },
+ { HDD_AC_VO_BIT, HDD_MAX_OFF_CHAN_TIME_FOR_VO },
+};
+
/* internal function declaration */
struct notifier_block hdd_netdev_notifier;
@@ -12537,6 +12544,103 @@
return 0;
}
+/**
+ * hdd_send_limit_off_chan_cmd() - send limit off-channel command parameters
+ * @param - pointer to sir_limit_off_chan
+ *
+ * Return: 0 on success and non zero value on failure
+ */
+static int hdd_send_limit_off_chan_cmd(struct sir_limit_off_chan *param)
+{
+ struct scheduler_msg msg = {0};
+
+ msg.type = WMA_SET_LIMIT_OFF_CHAN;
+ msg.reserved = 0;
+ msg.bodyptr = param;
+
+ if (!QDF_IS_STATUS_SUCCESS(scheduler_post_msg(QDF_MODULE_ID_WMA,
+ &msg))) {
+ QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+ FL("Not able to post WMA_SET_LIMIT_OFF_CHAN to WMA"));
+ return QDF_STATUS_E_FAILURE;
+ }
+
+ return 0;
+}
+
+/**
+ * hdd_set_limit_off_chan_for_tos() - set limit off-channel command parameters
+ * @adapter - HDD adapter
+ * @tos - type of service
+ * @status - status of the traffic
+ *
+ * Return: 0 on success and non zero value on failure
+ */
+
+int hdd_set_limit_off_chan_for_tos(struct hdd_adapter *adapter, enum tos tos,
+ bool is_tos_active)
+{
+ int ac_bit;
+ struct sir_limit_off_chan *cmd;
+ struct hdd_context *hdd_ctx;
+ int ret;
+
+ hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ ret = wlan_hdd_validate_context(hdd_ctx);
+
+ if (ret < 0) {
+ hdd_err("failed to set limit off chan params");
+ return ret;
+ }
+
+ cmd = qdf_mem_malloc(sizeof(struct sir_limit_off_chan));
+ if (!cmd) {
+ hdd_err("qdf_mem_malloc failed for limit off channel");
+ return -ENOMEM;
+ }
+
+ ac_bit = limit_off_chan_tbl[tos][HDD_AC_BIT_INDX];
+
+ if (is_tos_active)
+ hdd_ctx->active_ac |= ac_bit;
+ else
+ hdd_ctx->active_ac &= ~ac_bit;
+
+ if (hdd_ctx->active_ac) {
+ if (hdd_ctx->active_ac & HDD_AC_VO_BIT) {
+ cmd->max_off_chan_time =
+ limit_off_chan_tbl[TOS_VO][HDD_DWELL_TIME_INDX];
+ policy_mgr_set_cur_conc_system_pref(hdd_ctx->hdd_psoc,
+ PM_LATENCY);
+ } else if (hdd_ctx->active_ac & HDD_AC_VI_BIT) {
+ cmd->max_off_chan_time =
+ limit_off_chan_tbl[TOS_VI][HDD_DWELL_TIME_INDX];
+ policy_mgr_set_cur_conc_system_pref(hdd_ctx->hdd_psoc,
+ PM_LATENCY);
+ } else {
+ /*ignore this command if only BE/BK is active */
+ is_tos_active = false;
+ policy_mgr_set_cur_conc_system_pref(hdd_ctx->hdd_psoc,
+ hdd_ctx->config->conc_system_pref);
+ }
+ } else {
+ /* No active tos */
+ policy_mgr_set_cur_conc_system_pref(hdd_ctx->hdd_psoc,
+ hdd_ctx->config->conc_system_pref);
+ }
+
+ cmd->vdev_id = adapter->sessionId;
+ cmd->is_tos_active = is_tos_active;
+ cmd->rest_time = hdd_ctx->config->nRestTimeConc;
+ cmd->skip_dfs_chans = true;
+
+ ret = hdd_send_limit_off_chan_cmd(cmd);
+ if (ret)
+ qdf_mem_free(cmd);
+
+ return ret;
+}
+
/* Register the module init/exit functions */
module_init(hdd_module_init);
module_exit(hdd_module_exit);
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index 411f7e5..6f564a6 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -7664,4 +7664,19 @@
uint8_t session_id;
};
+/*
+ * struct sir_limit_off_chan - limit off-channel command parameters
+ * @vdev_id: vdev id
+ * @is_tos_active: status of the traffic (active/inactive)
+ * @max_off_chan_time: max allowed off channel time
+ * @rest_time: home channel time
+ * @skip_dfs_chans: skip dfs channels during scan
+ */
+struct sir_limit_off_chan {
+ uint8_t vdev_id;
+ bool is_tos_active;
+ uint32_t max_off_chan_time;
+ uint32_t rest_time;
+ bool skip_dfs_chans;
+};
#endif /* __SIR_API_H */
diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h
index 26da90c..d988434 100644
--- a/core/mac/src/include/sir_params.h
+++ b/core/mac/src/include/sir_params.h
@@ -654,6 +654,8 @@
#define SIR_HAL_SET_ARP_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 388)
#define SIR_HAL_GET_ARP_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 389)
+#define SIR_HAL_SET_LIMIT_OFF_CHAN (SIR_HAL_ITC_MSG_TYPES_BEGIN + 390)
+
#define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
/* CFG message types */
diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h
index 773b9fc..a216cad 100644
--- a/core/wma/inc/wma_types.h
+++ b/core/wma/inc/wma_types.h
@@ -481,6 +481,7 @@
#define WMA_SET_ARP_STATS_REQ SIR_HAL_SET_ARP_STATS_REQ
#define WMA_GET_ARP_STATS_REQ SIR_HAL_GET_ARP_STATS_REQ
+#define WMA_SET_LIMIT_OFF_CHAN SIR_HAL_SET_LIMIT_OFF_CHAN
/* Bit 6 will be used to control BD rate for Management frames */
#define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40
diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c
index c39cd81..a837c47 100644
--- a/core/wma/src/wma_main.c
+++ b/core/wma/src/wma_main.c
@@ -6782,6 +6782,35 @@
}
/**
+ * wma_process_set_limit_off_chan() - set limit off chanel parameters
+ * @wma_handle: pointer to wma handle
+ * @param: pointer to sir_limit_off_chan
+ *
+ * Return: QDF_STATUS_SUCCESS for success or error code.
+ */
+static QDF_STATUS wma_process_limit_off_chan(tp_wma_handle wma_handle,
+ struct sir_limit_off_chan *param)
+{
+ int32_t err;
+ struct wmi_limit_off_chan_param limit_off_chan_param;
+
+ limit_off_chan_param.vdev_id = param->vdev_id;
+ limit_off_chan_param.status = param->is_tos_active;
+ limit_off_chan_param.max_offchan_time = param->max_off_chan_time;
+ limit_off_chan_param.rest_time = param->rest_time;
+ limit_off_chan_param.skip_dfs_chans = param->skip_dfs_chans;
+
+ err = wmi_unified_send_limit_off_chan_cmd(wma_handle->wmi_handle,
+ &limit_off_chan_param);
+ if (err) {
+ WMA_LOGE("\n failed to set limit off chan cmd");
+ return QDF_STATUS_E_FAILURE;
+ }
+
+ return QDF_STATUS_SUCCESS;
+}
+
+/**
* wma_mc_process_msg() - process wma messages and call appropriate function.
* @msg: message
*
@@ -7579,6 +7608,10 @@
(struct get_arp_stats_params *)msg->bodyptr);
qdf_mem_free(msg->bodyptr);
break;
+ case WMA_SET_LIMIT_OFF_CHAN:
+ wma_process_limit_off_chan(wma_handle, msg->bodyptr);
+ qdf_mem_free(msg->bodyptr);
+ break;
default:
WMA_LOGE("Unhandled WMA message of type %d", msg->type);
if (msg->bodyptr)