qcacmn: Add tlv formation of ocb commands in common wmi layer
Move tlv formation of wmi ocb/dsrc commands from umac to
common wmi layer.
Change-Id: I2735b40b97b8ff120e37e343fc6f3681cd0d73f9
CRs-Fixed:983606
diff --git a/wmi_unified_tlv.c b/wmi_unified_tlv.c
index d9f2381..589b12c 100644
--- a/wmi_unified_tlv.c
+++ b/wmi_unified_tlv.c
@@ -261,7 +261,7 @@
/**
* send_peer_param_cmd_tlv() - set peer parameter in fw
- * @wma_ctx: wmi handle
+ * @wmi: wmi handle
* @peer_addr: peer mac address
* @param : pointer to hold peer set parameter
*
@@ -682,7 +682,7 @@
/**
* send_set_ap_ps_param_cmd_tlv() - set ap powersave parameters
- * @wma_ctx: wma context
+ * @wmi_handle: wmi handle
* @peer_addr: peer mac address
* @param: pointer to ap_ps parameter structure
*
@@ -723,7 +723,7 @@
/**
* send_set_sta_ps_param_cmd_tlv() - set sta powersave parameters
- * @wma_ctx: wma context
+ * @wmi_handle: wmi handle
* @peer_addr: peer mac address
* @param: pointer to sta_ps parameter structure
*
@@ -764,7 +764,7 @@
/**
* send_crash_inject_cmd_tlv() - inject fw crash
- * @wma_handle: wma handle
+ * @wmi_handle: wmi handle
* @param: ponirt to crash inject paramter structure
*
* Return: 0 for success or return error
@@ -1632,7 +1632,7 @@
* @wmi_handle: wmi handle
* @noa: p2p power save parameters
*
- * Return: none
+ * Return: CDF status
*/
int32_t send_set_p2pgo_noa_req_cmd_tlv(wmi_unified_t wmi_handle,
struct p2p_ps_params *noa)
@@ -1700,7 +1700,7 @@
* @wmi_handle: wmi handle
* @noa: p2p opp power save parameters
*
- * Return: none
+ * Return: CDF status
*/
int32_t send_set_p2pgo_oppps_req_cmd_tlv(wmi_unified_t wmi_handle,
struct p2p_ps_params *oppps)
@@ -1779,6 +1779,7 @@
wmi_buf_free(wmi_buf);
return CDF_STATUS_E_FAILURE;
}
+
return CDF_STATUS_SUCCESS;
}
@@ -1853,6 +1854,645 @@
return ret;
}
+/**
+ * send_ocb_set_utc_time_cmd() - send the UTC time to the firmware
+ * @wmi_handle: pointer to the wmi handle
+ * @utc: pointer to the UTC time struct
+ *
+ * Return: 0 on succes
+ */
+int send_ocb_set_utc_time_cmd_tlv(wmi_unified_t wmi_handle,
+ struct ocb_utc_param *utc)
+{
+ int32_t ret;
+ wmi_ocb_set_utc_time_cmd_fixed_param *cmd;
+ uint8_t *buf_ptr;
+ uint32_t len, i;
+ wmi_buf_t buf;
+
+ len = sizeof(*cmd);
+ buf = wmi_buf_alloc(wmi_handle, len);
+ if (!buf) {
+ WMA_LOGE(FL("wmi_buf_alloc failed"));
+ return -ENOMEM;
+ }
+
+ buf_ptr = (uint8_t *)wmi_buf_data(buf);
+ cmd = (wmi_ocb_set_utc_time_cmd_fixed_param *)buf_ptr;
+ WMITLV_SET_HDR(&cmd->tlv_header,
+ WMITLV_TAG_STRUC_wmi_ocb_set_utc_time_cmd_fixed_param,
+ WMITLV_GET_STRUCT_TLVLEN(wmi_ocb_set_utc_time_cmd_fixed_param));
+ cmd->vdev_id = utc->vdev_id;
+
+ for (i = 0; i < SIZE_UTC_TIME; i++)
+ WMI_UTC_TIME_SET(cmd, i, utc->utc_time[i]);
+
+ for (i = 0; i < SIZE_UTC_TIME_ERROR; i++)
+ WMI_TIME_ERROR_SET(cmd, i, utc->time_error[i]);
+
+ ret = wmi_unified_cmd_send(wmi_handle, buf, len,
+ WMI_OCB_SET_UTC_TIME_CMDID);
+ if (ret != EOK) {
+ WMA_LOGE(FL("Failed to set OCB UTC time"));
+ wmi_buf_free(buf);
+ return -EIO;
+ }
+
+ return CDF_STATUS_SUCCESS;
+}
+
+/**
+ * send_ocb_start_timing_advert_cmd_tlv() - start sending the timing advertisement
+ * frames on a channel
+ * @wmi_handle: pointer to the wmi handle
+ * @timing_advert: pointer to the timing advertisement struct
+ *
+ * Return: 0 on succes
+ */
+int send_ocb_start_timing_advert_cmd_tlv(wmi_unified_t wmi_handle,
+ struct ocb_timing_advert_param *timing_advert)
+{
+ int32_t ret;
+ wmi_ocb_start_timing_advert_cmd_fixed_param *cmd;
+ uint8_t *buf_ptr;
+ uint32_t len, len_template;
+ wmi_buf_t buf;
+
+ len = sizeof(*cmd) +
+ WMI_TLV_HDR_SIZE;
+
+ len_template = timing_advert->template_length;
+ /* Add padding to the template if needed */
+ if (len_template % 4 != 0)
+ len_template += 4 - (len_template % 4);
+ len += len_template;
+
+ buf = wmi_buf_alloc(wmi_handle, len);
+ if (!buf) {
+ WMA_LOGE(FL("wmi_buf_alloc failed"));
+ return -ENOMEM;
+ }
+
+ buf_ptr = (uint8_t *)wmi_buf_data(buf);
+ cmd = (wmi_ocb_start_timing_advert_cmd_fixed_param *)buf_ptr;
+ WMITLV_SET_HDR(&cmd->tlv_header,
+ WMITLV_TAG_STRUC_wmi_ocb_start_timing_advert_cmd_fixed_param,
+ WMITLV_GET_STRUCT_TLVLEN(
+ wmi_ocb_start_timing_advert_cmd_fixed_param));
+ cmd->vdev_id = timing_advert->vdev_id;
+ cmd->repeat_rate = timing_advert->repeat_rate;
+ cmd->channel_freq = timing_advert->chan_freq;
+ cmd->timestamp_offset = timing_advert->timestamp_offset;
+ cmd->time_value_offset = timing_advert->time_value_offset;
+ cmd->timing_advert_template_length = timing_advert->template_length;
+ buf_ptr += sizeof(*cmd);
+
+ /* Add the timing advert template */
+ WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
+ len_template);
+ cdf_mem_copy(buf_ptr + WMI_TLV_HDR_SIZE,
+ (uint8_t *)timing_advert->template_value,
+ timing_advert->template_length);
+
+ ret = wmi_unified_cmd_send(wmi_handle, buf, len,
+ WMI_OCB_START_TIMING_ADVERT_CMDID);
+ if (ret != EOK) {
+ WMA_LOGE(FL("Failed to start OCB timing advert"));
+ wmi_buf_free(buf);
+ return -EIO;
+ }
+
+ return CDF_STATUS_SUCCESS;
+}
+
+/**
+ * send_ocb_stop_timing_advert_cmd_tlv() - stop sending the timing advertisement frames
+ * on a channel
+ * @wmi_handle: pointer to the wmi handle
+ * @timing_advert: pointer to the timing advertisement struct
+ *
+ * Return: 0 on succes
+ */
+int send_ocb_stop_timing_advert_cmd_tlv(wmi_unified_t wmi_handle,
+ struct ocb_timing_advert_param *timing_advert)
+{
+ int32_t ret;
+ wmi_ocb_stop_timing_advert_cmd_fixed_param *cmd;
+ uint8_t *buf_ptr;
+ uint32_t len;
+ wmi_buf_t buf;
+
+ len = sizeof(*cmd);
+ buf = wmi_buf_alloc(wmi_handle, len);
+ if (!buf) {
+ WMA_LOGE(FL("wmi_buf_alloc failed"));
+ return -ENOMEM;
+ }
+
+ buf_ptr = (uint8_t *)wmi_buf_data(buf);
+ cmd = (wmi_ocb_stop_timing_advert_cmd_fixed_param *)buf_ptr;
+ WMITLV_SET_HDR(&cmd->tlv_header,
+ WMITLV_TAG_STRUC_wmi_ocb_stop_timing_advert_cmd_fixed_param,
+ WMITLV_GET_STRUCT_TLVLEN(
+ wmi_ocb_stop_timing_advert_cmd_fixed_param));
+ cmd->vdev_id = timing_advert->vdev_id;
+ cmd->channel_freq = timing_advert->chan_freq;
+
+ ret = wmi_unified_cmd_send(wmi_handle, buf, len,
+ WMI_OCB_STOP_TIMING_ADVERT_CMDID);
+ if (ret != EOK) {
+ WMA_LOGE(FL("Failed to stop OCB timing advert"));
+ wmi_buf_free(buf);
+ return -EIO;
+ }
+
+ return CDF_STATUS_SUCCESS;
+}
+
+/**
+ * send_ocb_get_tsf_timer_cmd_tlv() - get ocb tsf timer val
+ * @wmi_handle: pointer to the wmi handle
+ * @request: pointer to the request
+ *
+ * Return: 0 on succes
+ */
+int send_ocb_get_tsf_timer_cmd_tlv(wmi_unified_t wmi_handle,
+ uint8_t vdev_id)
+{
+ CDF_STATUS ret;
+ wmi_ocb_get_tsf_timer_cmd_fixed_param *cmd;
+ uint8_t *buf_ptr;
+ wmi_buf_t buf;
+ int32_t len;
+
+ len = sizeof(*cmd);
+ buf = wmi_buf_alloc(wmi_handle, len);
+ if (!buf) {
+ WMA_LOGE(FL("wmi_buf_alloc failed"));
+ return -ENOMEM;
+ }
+ buf_ptr = (uint8_t *)wmi_buf_data(buf);
+
+ cmd = (wmi_ocb_get_tsf_timer_cmd_fixed_param *)buf_ptr;
+ cdf_mem_zero(cmd, len);
+ WMITLV_SET_HDR(&cmd->tlv_header,
+ WMITLV_TAG_STRUC_wmi_ocb_get_tsf_timer_cmd_fixed_param,
+ WMITLV_GET_STRUCT_TLVLEN(
+ wmi_ocb_get_tsf_timer_cmd_fixed_param));
+ cmd->vdev_id = vdev_id;
+
+ /* Send the WMI command */
+ ret = wmi_unified_cmd_send(wmi_handle, buf, len,
+ WMI_OCB_GET_TSF_TIMER_CMDID);
+ /* If there is an error, set the completion event */
+ if (ret != EOK) {
+ WMA_LOGE(FL("Failed to send WMI message: %d"), ret);
+ wmi_buf_free(buf);
+ return -EIO;
+ }
+
+ return CDF_STATUS_SUCCESS;
+}
+
+/**
+ * send_dcc_get_stats_cmd_tlv() - get the DCC channel stats
+ * @wmi_handle: pointer to the wmi handle
+ * @get_stats_param: pointer to the dcc stats
+ *
+ * Return: 0 on succes
+ */
+int send_dcc_get_stats_cmd_tlv(wmi_unified_t wmi_handle,
+ struct dcc_get_stats_param *get_stats_param)
+{
+ int32_t ret;
+ wmi_dcc_get_stats_cmd_fixed_param *cmd;
+ wmi_dcc_channel_stats_request *channel_stats_array;
+ wmi_buf_t buf;
+ uint8_t *buf_ptr;
+ uint32_t len;
+ uint32_t i;
+
+ /* Validate the input */
+ if (get_stats_param->request_array_len !=
+ get_stats_param->channel_count * sizeof(*channel_stats_array)) {
+ WMA_LOGE(FL("Invalid parameter"));
+ return -EINVAL;
+ }
+
+ /* Allocate memory for the WMI command */
+ len = sizeof(*cmd) + WMI_TLV_HDR_SIZE +
+ get_stats_param->request_array_len;
+
+ buf = wmi_buf_alloc(wmi_handle, len);
+ if (!buf) {
+ WMA_LOGE(FL("wmi_buf_alloc failed"));
+ return CDF_STATUS_E_NOMEM;
+ }
+
+ buf_ptr = wmi_buf_data(buf);
+ cdf_mem_zero(buf_ptr, len);
+
+ /* Populate the WMI command */
+ cmd = (wmi_dcc_get_stats_cmd_fixed_param *)buf_ptr;
+ buf_ptr += sizeof(*cmd);
+
+ WMITLV_SET_HDR(&cmd->tlv_header,
+ WMITLV_TAG_STRUC_wmi_dcc_get_stats_cmd_fixed_param,
+ WMITLV_GET_STRUCT_TLVLEN(
+ wmi_dcc_get_stats_cmd_fixed_param));
+ cmd->vdev_id = get_stats_param->vdev_id;
+ cmd->num_channels = get_stats_param->channel_count;
+
+ WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
+ get_stats_param->request_array_len);
+ buf_ptr += WMI_TLV_HDR_SIZE;
+
+ channel_stats_array = (wmi_dcc_channel_stats_request *)buf_ptr;
+ cdf_mem_copy(channel_stats_array, get_stats_param->request_array,
+ get_stats_param->request_array_len);
+ for (i = 0; i < cmd->num_channels; i++)
+ WMITLV_SET_HDR(&channel_stats_array[i].tlv_header,
+ WMITLV_TAG_STRUC_wmi_dcc_channel_stats_request,
+ WMITLV_GET_STRUCT_TLVLEN(
+ wmi_dcc_channel_stats_request));
+
+ /* Send the WMI command */
+ ret = wmi_unified_cmd_send(wmi_handle, buf, len,
+ WMI_DCC_GET_STATS_CMDID);
+
+ if (ret != EOK) {
+ WMA_LOGE(FL("Failed to send WMI message: %d"), ret);
+ wmi_buf_free(buf);
+ return -EIO;
+ }
+
+ return CDF_STATUS_SUCCESS;
+}
+
+/**
+ * send_dcc_clear_stats_cmd_tlv() - command to clear the DCC stats
+ * @wmi_handle: pointer to the wmi handle
+ * @vdev_id: vdev id
+ * @dcc_stats_bitmap: dcc status bitmap
+ *
+ * Return: 0 on succes
+ */
+int send_dcc_clear_stats_cmd_tlv(wmi_unified_t wmi_handle,
+ uint32_t vdev_id, uint32_t dcc_stats_bitmap)
+{
+ int32_t ret;
+ wmi_dcc_clear_stats_cmd_fixed_param *cmd;
+ wmi_buf_t buf;
+ uint8_t *buf_ptr;
+ uint32_t len;
+
+ /* Allocate memory for the WMI command */
+ len = sizeof(*cmd);
+
+ buf = wmi_buf_alloc(wmi_handle, len);
+ if (!buf) {
+ WMA_LOGE(FL("wmi_buf_alloc failed"));
+ return -ENOMEM;
+ }
+
+ buf_ptr = wmi_buf_data(buf);
+ cdf_mem_zero(buf_ptr, len);
+
+ /* Populate the WMI command */
+ cmd = (wmi_dcc_clear_stats_cmd_fixed_param *)buf_ptr;
+
+ WMITLV_SET_HDR(&cmd->tlv_header,
+ WMITLV_TAG_STRUC_wmi_dcc_clear_stats_cmd_fixed_param,
+ WMITLV_GET_STRUCT_TLVLEN(
+ wmi_dcc_clear_stats_cmd_fixed_param));
+ cmd->vdev_id = vdev_id;
+ cmd->dcc_stats_bitmap = dcc_stats_bitmap;
+
+ /* Send the WMI command */
+ ret = wmi_unified_cmd_send(wmi_handle, buf, len,
+ WMI_DCC_CLEAR_STATS_CMDID);
+ if (ret != EOK) {
+ WMA_LOGE(FL("Failed to send the WMI command"));
+ wmi_buf_free(buf);
+ return -EIO;
+ }
+
+ return CDF_STATUS_SUCCESS;
+}
+
+/**
+ * send_dcc_update_ndl_cmd_tlv() - command to update the NDL data
+ * @wmi_handle: pointer to the wmi handle
+ * @update_ndl_param: pointer to the request parameters
+ *
+ * Return: 0 on success
+ */
+int send_dcc_update_ndl_cmd_tlv(wmi_unified_t wmi_handle,
+ struct dcc_update_ndl_param *update_ndl_param)
+{
+ CDF_STATUS cdf_status;
+ wmi_dcc_update_ndl_cmd_fixed_param *cmd;
+ wmi_dcc_ndl_chan *ndl_chan_array;
+ wmi_dcc_ndl_active_state_config *ndl_active_state_array;
+ uint32_t active_state_count;
+ wmi_buf_t buf;
+ uint8_t *buf_ptr;
+ uint32_t len;
+ uint32_t i;
+
+ /* validate the input */
+ if (update_ndl_param->dcc_ndl_chan_list_len !=
+ update_ndl_param->channel_count * sizeof(*ndl_chan_array)) {
+ WMA_LOGE(FL("Invalid parameter"));
+ return CDF_STATUS_E_INVAL;
+ }
+ active_state_count = 0;
+ ndl_chan_array = update_ndl_param->dcc_ndl_chan_list;
+ for (i = 0; i < update_ndl_param->channel_count; i++)
+ active_state_count +=
+ WMI_NDL_NUM_ACTIVE_STATE_GET(&ndl_chan_array[i]);
+ if (update_ndl_param->dcc_ndl_active_state_list_len !=
+ active_state_count * sizeof(*ndl_active_state_array)) {
+ WMA_LOGE(FL("Invalid parameter"));
+ return CDF_STATUS_E_INVAL;
+ }
+
+ /* Allocate memory for the WMI command */
+ len = sizeof(*cmd) +
+ WMI_TLV_HDR_SIZE + update_ndl_param->dcc_ndl_chan_list_len +
+ WMI_TLV_HDR_SIZE +
+ update_ndl_param->dcc_ndl_active_state_list_len;
+
+ buf = wmi_buf_alloc(wmi_handle, len);
+ if (!buf) {
+ WMA_LOGE(FL("wmi_buf_alloc failed"));
+ return -ENOMEM;
+ }
+
+ buf_ptr = wmi_buf_data(buf);
+ cdf_mem_zero(buf_ptr, len);
+
+ /* Populate the WMI command */
+ cmd = (wmi_dcc_update_ndl_cmd_fixed_param *)buf_ptr;
+ buf_ptr += sizeof(*cmd);
+
+ WMITLV_SET_HDR(&cmd->tlv_header,
+ WMITLV_TAG_STRUC_wmi_dcc_update_ndl_cmd_fixed_param,
+ WMITLV_GET_STRUCT_TLVLEN(
+ wmi_dcc_update_ndl_cmd_fixed_param));
+ cmd->vdev_id = update_ndl_param->vdev_id;
+ cmd->num_channel = update_ndl_param->channel_count;
+
+ WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
+ update_ndl_param->dcc_ndl_chan_list_len);
+ buf_ptr += WMI_TLV_HDR_SIZE;
+
+ ndl_chan_array = (wmi_dcc_ndl_chan *)buf_ptr;
+ cdf_mem_copy(ndl_chan_array, update_ndl_param->dcc_ndl_chan_list,
+ update_ndl_param->dcc_ndl_chan_list_len);
+ for (i = 0; i < cmd->num_channel; i++)
+ WMITLV_SET_HDR(&ndl_chan_array[i].tlv_header,
+ WMITLV_TAG_STRUC_wmi_dcc_ndl_chan,
+ WMITLV_GET_STRUCT_TLVLEN(
+ wmi_dcc_ndl_chan));
+ buf_ptr += update_ndl_param->dcc_ndl_chan_list_len;
+
+ WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
+ update_ndl_param->dcc_ndl_active_state_list_len);
+ buf_ptr += WMI_TLV_HDR_SIZE;
+
+ ndl_active_state_array = (wmi_dcc_ndl_active_state_config *) buf_ptr;
+ cdf_mem_copy(ndl_active_state_array,
+ update_ndl_param->dcc_ndl_active_state_list,
+ update_ndl_param->dcc_ndl_active_state_list_len);
+ for (i = 0; i < active_state_count; i++) {
+ WMITLV_SET_HDR(&ndl_active_state_array[i].tlv_header,
+ WMITLV_TAG_STRUC_wmi_dcc_ndl_active_state_config,
+ WMITLV_GET_STRUCT_TLVLEN(
+ wmi_dcc_ndl_active_state_config));
+ }
+ buf_ptr += update_ndl_param->dcc_ndl_active_state_list_len;
+
+ /* Send the WMI command */
+ cdf_status = wmi_unified_cmd_send(wmi_handle, buf, len,
+ WMI_DCC_UPDATE_NDL_CMDID);
+ /* If there is an error, set the completion event */
+ if (cdf_status) {
+ WMA_LOGE(FL("Failed to send WMI message: %d"), cdf_status);
+ wmi_buf_free(buf);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * send_ocb_set_config_cmd_tlv() - send the OCB config to the FW
+ * @wmi_handle: pointer to the wmi handle
+ * @config: the OCB configuration
+ *
+ * Return: 0 on success
+ */
+int send_ocb_set_config_cmd_tlv(wmi_unified_t wmi_handle,
+ struct ocb_config_param *config, uint32_t *ch_mhz)
+{
+ int32_t ret;
+ wmi_ocb_set_config_cmd_fixed_param *cmd;
+ wmi_channel *chan;
+ wmi_ocb_channel *ocb_chan;
+ wmi_qos_parameter *qos_param;
+ wmi_dcc_ndl_chan *ndl_chan;
+ wmi_dcc_ndl_active_state_config *ndl_active_config;
+ wmi_ocb_schedule_element *sched_elem;
+ uint8_t *buf_ptr;
+ wmi_buf_t buf;
+ int32_t len;
+ int32_t i, j, active_state_count;
+
+ /*
+ * Validate the dcc_ndl_chan_list_len and count the number of active
+ * states. Validate dcc_ndl_active_state_list_len.
+ */
+ active_state_count = 0;
+ if (config->dcc_ndl_chan_list_len) {
+ if (!config->dcc_ndl_chan_list ||
+ config->dcc_ndl_chan_list_len !=
+ config->channel_count * sizeof(wmi_dcc_ndl_chan)) {
+ WMA_LOGE(FL("NDL channel is invalid. List len: %d"),
+ config->dcc_ndl_chan_list_len);
+ return -EINVAL;
+ }
+
+ for (i = 0, ndl_chan = config->dcc_ndl_chan_list;
+ i < config->channel_count; ++i, ++ndl_chan)
+ active_state_count +=
+ WMI_NDL_NUM_ACTIVE_STATE_GET(ndl_chan);
+
+ if (active_state_count) {
+ if (!config->dcc_ndl_active_state_list ||
+ config->dcc_ndl_active_state_list_len !=
+ active_state_count *
+ sizeof(wmi_dcc_ndl_active_state_config)) {
+ WMA_LOGE(FL("NDL active state is invalid."));
+ return -EINVAL;
+ }
+ }
+ }
+
+ len = sizeof(*cmd) +
+ WMI_TLV_HDR_SIZE + config->channel_count *
+ sizeof(wmi_channel) +
+ WMI_TLV_HDR_SIZE + config->channel_count *
+ sizeof(wmi_ocb_channel) +
+ WMI_TLV_HDR_SIZE + config->channel_count *
+ sizeof(wmi_qos_parameter) * WMI_MAX_NUM_AC +
+ WMI_TLV_HDR_SIZE + config->dcc_ndl_chan_list_len +
+ WMI_TLV_HDR_SIZE + active_state_count *
+ sizeof(wmi_dcc_ndl_active_state_config) +
+ WMI_TLV_HDR_SIZE + config->schedule_size *
+ sizeof(wmi_ocb_schedule_element);
+ buf = wmi_buf_alloc(wmi_handle, len);
+ if (!buf) {
+ WMA_LOGE(FL("wmi_buf_alloc failed"));
+ return -ENOMEM;
+ }
+
+ buf_ptr = (uint8_t *)wmi_buf_data(buf);
+ cmd = (wmi_ocb_set_config_cmd_fixed_param *)buf_ptr;
+ WMITLV_SET_HDR(&cmd->tlv_header,
+ WMITLV_TAG_STRUC_wmi_ocb_set_config_cmd_fixed_param,
+ WMITLV_GET_STRUCT_TLVLEN(wmi_ocb_set_config_cmd_fixed_param));
+ cmd->vdev_id = config->session_id;
+ cmd->channel_count = config->channel_count;
+ cmd->schedule_size = config->schedule_size;
+ cmd->flags = config->flags;
+ buf_ptr += sizeof(*cmd);
+
+ /* Add the wmi_channel info */
+ WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
+ config->channel_count*sizeof(wmi_channel));
+ buf_ptr += WMI_TLV_HDR_SIZE;
+ for (i = 0; i < config->channel_count; i++) {
+ chan = (wmi_channel *)buf_ptr;
+ WMITLV_SET_HDR(&chan->tlv_header,
+ WMITLV_TAG_STRUC_wmi_channel,
+ WMITLV_GET_STRUCT_TLVLEN(wmi_channel));
+ chan->mhz = config->channels[i].chan_freq;
+ chan->band_center_freq1 = config->channels[i].chan_freq;
+ chan->band_center_freq2 = 0;
+ chan->info = 0;
+
+ WMI_SET_CHANNEL_MODE(chan, ch_mhz[i]);
+ WMI_SET_CHANNEL_MAX_POWER(chan, config->channels[i].max_pwr);
+ WMI_SET_CHANNEL_MIN_POWER(chan, config->channels[i].min_pwr);
+ WMI_SET_CHANNEL_MAX_TX_POWER(chan, config->channels[i].max_pwr);
+ WMI_SET_CHANNEL_REG_POWER(chan, config->channels[i].reg_pwr);
+ WMI_SET_CHANNEL_ANTENNA_MAX(chan,
+ config->channels[i].antenna_max);
+
+ if (config->channels[i].bandwidth < 10)
+ WMI_SET_CHANNEL_FLAG(chan, WMI_CHAN_FLAG_QUARTER_RATE);
+ else if (config->channels[i].bandwidth < 20)
+ WMI_SET_CHANNEL_FLAG(chan, WMI_CHAN_FLAG_HALF_RATE);
+ buf_ptr += sizeof(*chan);
+ }
+
+ /* Add the wmi_ocb_channel info */
+ WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
+ config->channel_count*sizeof(wmi_ocb_channel));
+ buf_ptr += WMI_TLV_HDR_SIZE;
+ for (i = 0; i < config->channel_count; i++) {
+ ocb_chan = (wmi_ocb_channel *)buf_ptr;
+ WMITLV_SET_HDR(&ocb_chan->tlv_header,
+ WMITLV_TAG_STRUC_wmi_ocb_channel,
+ WMITLV_GET_STRUCT_TLVLEN(wmi_ocb_channel));
+ ocb_chan->bandwidth = config->channels[i].bandwidth;
+ WMI_CHAR_ARRAY_TO_MAC_ADDR(
+ config->channels[i].mac_address.bytes,
+ &ocb_chan->mac_address);
+ buf_ptr += sizeof(*ocb_chan);
+ }
+
+ /* Add the wmi_qos_parameter info */
+ WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
+ config->channel_count * sizeof(wmi_qos_parameter)*WMI_MAX_NUM_AC);
+ buf_ptr += WMI_TLV_HDR_SIZE;
+ /* WMI_MAX_NUM_AC parameters for each channel */
+ for (i = 0; i < config->channel_count; i++) {
+ for (j = 0; j < WMI_MAX_NUM_AC; j++) {
+ qos_param = (wmi_qos_parameter *)buf_ptr;
+ WMITLV_SET_HDR(&qos_param->tlv_header,
+ WMITLV_TAG_STRUC_wmi_qos_parameter,
+ WMITLV_GET_STRUCT_TLVLEN(wmi_qos_parameter));
+ qos_param->aifsn =
+ config->channels[i].qos_params[j].aifsn;
+ qos_param->cwmin =
+ config->channels[i].qos_params[j].cwmin;
+ qos_param->cwmax =
+ config->channels[i].qos_params[j].cwmax;
+ buf_ptr += sizeof(*qos_param);
+ }
+ }
+
+ /* Add the wmi_dcc_ndl_chan (per channel) */
+ WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
+ config->dcc_ndl_chan_list_len);
+ buf_ptr += WMI_TLV_HDR_SIZE;
+ if (config->dcc_ndl_chan_list_len) {
+ ndl_chan = (wmi_dcc_ndl_chan *)buf_ptr;
+ cdf_mem_copy(ndl_chan, config->dcc_ndl_chan_list,
+ config->dcc_ndl_chan_list_len);
+ for (i = 0; i < config->channel_count; i++)
+ WMITLV_SET_HDR(&(ndl_chan[i].tlv_header),
+ WMITLV_TAG_STRUC_wmi_dcc_ndl_chan,
+ WMITLV_GET_STRUCT_TLVLEN(wmi_dcc_ndl_chan));
+ buf_ptr += config->dcc_ndl_chan_list_len;
+ }
+
+ /* Add the wmi_dcc_ndl_active_state_config */
+ WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, active_state_count *
+ sizeof(wmi_dcc_ndl_active_state_config));
+ buf_ptr += WMI_TLV_HDR_SIZE;
+ if (active_state_count) {
+ ndl_active_config = (wmi_dcc_ndl_active_state_config *)buf_ptr;
+ cdf_mem_copy(ndl_active_config,
+ config->dcc_ndl_active_state_list,
+ active_state_count * sizeof(*ndl_active_config));
+ for (i = 0; i < active_state_count; ++i)
+ WMITLV_SET_HDR(&(ndl_active_config[i].tlv_header),
+ WMITLV_TAG_STRUC_wmi_dcc_ndl_active_state_config,
+ WMITLV_GET_STRUCT_TLVLEN(
+ wmi_dcc_ndl_active_state_config));
+ buf_ptr += active_state_count *
+ sizeof(*ndl_active_config);
+ }
+
+ /* Add the wmi_ocb_schedule_element info */
+ WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
+ config->schedule_size * sizeof(wmi_ocb_schedule_element));
+ buf_ptr += WMI_TLV_HDR_SIZE;
+ for (i = 0; i < config->schedule_size; i++) {
+ sched_elem = (wmi_ocb_schedule_element *)buf_ptr;
+ WMITLV_SET_HDR(&sched_elem->tlv_header,
+ WMITLV_TAG_STRUC_wmi_ocb_schedule_element,
+ WMITLV_GET_STRUCT_TLVLEN(wmi_ocb_schedule_element));
+ sched_elem->channel_freq = config->schedule[i].chan_freq;
+ sched_elem->total_duration = config->schedule[i].total_duration;
+ sched_elem->guard_interval = config->schedule[i].guard_interval;
+ buf_ptr += sizeof(*sched_elem);
+ }
+
+
+ ret = wmi_unified_cmd_send(wmi_handle, buf, len,
+ WMI_OCB_SET_CONFIG_CMDID);
+ if (ret != EOK) {
+ WMA_LOGE("Failed to set OCB config");
+ wmi_buf_free(buf);
+ return -EIO;
+ }
+
+ return 0;
+}
struct wmi_ops tlv_ops = {
.send_vdev_create_cmd = send_vdev_create_cmd_tlv,
.send_vdev_delete_cmd = send_vdev_delete_cmd_tlv,
@@ -1890,6 +2530,14 @@
.send_set_p2pgo_noa_req_cmd = send_set_p2pgo_noa_req_cmd_tlv,
.send_set_smps_params_cmd = send_set_smps_params_cmd_tlv,
.send_set_mimops_cmd = send_set_mimops_cmd_tlv,
+ .send_ocb_set_utc_time_cmd = send_ocb_set_utc_time_cmd_tlv,
+ .send_ocb_get_tsf_timer_cmd = send_ocb_get_tsf_timer_cmd_tlv,
+ .send_dcc_clear_stats_cmd = send_dcc_clear_stats_cmd_tlv,
+ .send_dcc_get_stats_cmd = send_dcc_get_stats_cmd_tlv,
+ .send_dcc_update_ndl_cmd = send_dcc_update_ndl_cmd_tlv,
+ .send_ocb_set_config_cmd = send_ocb_set_config_cmd_tlv,
+ .send_ocb_stop_timing_advert_cmd = send_ocb_stop_timing_advert_cmd_tlv,
+ .send_ocb_start_timing_advert_cmd = send_ocb_start_timing_advert_cmd_tlv,
/* TODO - Add other tlv apis here */
};