blob: 2f38cf0e947ac5d496a004c95c8fd6c3d55fa608 [file] [log] [blame]
/*
* Copyright (c) 2019 The Linux Foundation. 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
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <osdep.h>
#include <wmi.h>
#include <wmi_unified_priv.h>
#include <wmi_unified_interop_issues_ap_api.h>
/**
* extract_interop_issues_ap_ev_param_tlv() - extract info from event
* @wmi_handle: wmi handle
* @param evt_buf: pointer to event buffer
* @param param: Pointer to hold interop issues ap info
*
* Return: QDF_STATUS_SUCCESS for success or error code
*/
static QDF_STATUS
extract_interop_issues_ap_ev_param_tlv(wmi_unified_t wmi_handle, void *evt_buf,
struct wlan_interop_issues_ap_event *data)
{
wmi_pdev_rap_info_event_fixed_param *fixed_param;
WMI_PDEV_RAP_INFO_EVENTID_param_tlvs *param_buf =
(WMI_PDEV_RAP_INFO_EVENTID_param_tlvs *)evt_buf;
if (!param_buf) {
wmi_err_rl("Invalid param_buf");
return -EINVAL;
}
fixed_param = param_buf->fixed_param;
if (!fixed_param) {
wmi_err_rl("Invalid fixed_praram");
return -EINVAL;
}
if (fixed_param->type != WMI_ROGUE_AP_ON_STA_PS) {
wmi_err_rl("Invalid type");
return -EINVAL;
}
data->pdev_id = fixed_param->pdev_id;
WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_param->bssid, data->rap_addr.bytes);
return QDF_STATUS_SUCCESS;
}
/**
* send_set_rap_ps_cmd_tlv() - set interop issues ap mac address in fw
* @wmi_handle: wmi handle
* @rap: interop issues ap info
*
* Return: QDF_STATUS_SUCCESS for success or error code
*/
static QDF_STATUS
send_set_rap_ps_cmd_tlv(wmi_unified_t wmi_handle,
struct wlan_interop_issues_ap_info *rap)
{
wmi_pdev_set_rap_config_fixed_param *cmd;
wmi_pdev_set_rap_config_on_sta_ps_tlv_param *param;
uint8_t *buf_ptr;
wmi_buf_t buf;
uint32_t ret;
uint32_t len, count;
qdf_size_t i;
count = rap->count;
len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + sizeof(*param) * count;
buf = wmi_buf_alloc(wmi_handle, len);
if (!buf)
return QDF_STATUS_E_FAILURE;
buf_ptr = wmi_buf_data(buf);
cmd = (wmi_pdev_set_rap_config_fixed_param *)buf_ptr;
WMITLV_SET_HDR(&cmd->tlv_header,
WMITLV_TAG_STRUC_wmi_pdev_set_rap_config_fixed_param,
WMITLV_GET_STRUCT_TLVLEN
(wmi_pdev_set_rap_config_fixed_param));
cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
wmi_handle,
WMI_HOST_PDEV_ID_SOC);
cmd->type = WMI_ROGUE_AP_ON_STA_PS;
if (count)
cmd->sta_ps_detection_enabled = 1;
else
cmd->sta_ps_detection_enabled = 0;
buf_ptr += sizeof(*cmd);
WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
sizeof(wmi_pdev_set_rap_config_on_sta_ps_tlv_param) * count);
buf_ptr += WMI_TLV_HDR_SIZE;
for (i = 0; i < count; i++) {
param = (wmi_pdev_set_rap_config_on_sta_ps_tlv_param *)buf_ptr;
WMITLV_SET_HDR(&param->tlv_header,
WMITLV_TAG_STRUC_wmi_pdev_set_rap_config_on_sta_ps_tlv_param,
WMITLV_GET_STRUCT_TLVLEN
(wmi_pdev_set_rap_config_on_sta_ps_tlv_param));
WMI_CHAR_ARRAY_TO_MAC_ADDR(rap->rap_items[i].bytes,
&param->bssid);
buf_ptr += sizeof(*param);
}
ret = wmi_unified_cmd_send(wmi_handle, buf, len,
WMI_PDEV_SET_RAP_CONFIG_CMDID);
if (ret) {
wmi_buf_free(buf);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
void wmi_interop_issues_ap_attach_tlv(wmi_unified_t wmi_handle)
{
struct wmi_ops *ops = wmi_handle->ops;
ops->extract_interop_issues_ap_ev_param =
extract_interop_issues_ap_ev_param_tlv;
ops->send_set_rap_ps_cmd = send_set_rap_ps_cmd_tlv;
}