1 /*
2 * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #include <osdep.h>
21 #include <wmi.h>
22 #include <wmi_unified_priv.h>
23 #include <wmi_unified_interop_issues_ap_api.h>
24
25 /**
26 * extract_interop_issues_ap_ev_param_tlv() - extract info from event
27 * @wmi_handle: wmi handle
28 * @evt_buf: pointer to event buffer
29 * @data: Pointer to hold interop issues ap info
30 *
31 * Return: QDF_STATUS_SUCCESS for success or error code
32 */
33 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)34 extract_interop_issues_ap_ev_param_tlv(wmi_unified_t wmi_handle, void *evt_buf,
35 struct wlan_interop_issues_ap_event *data)
36 {
37 wmi_pdev_rap_info_event_fixed_param *fixed_param;
38 WMI_PDEV_RAP_INFO_EVENTID_param_tlvs *param_buf =
39 (WMI_PDEV_RAP_INFO_EVENTID_param_tlvs *)evt_buf;
40
41 if (!param_buf) {
42 wmi_err_rl("Invalid param_buf");
43 return -EINVAL;
44 }
45
46 fixed_param = param_buf->fixed_param;
47 if (!fixed_param) {
48 wmi_err_rl("Invalid fixed_praram");
49 return -EINVAL;
50 }
51
52 if (fixed_param->type != WMI_ROGUE_AP_ON_STA_PS) {
53 wmi_err_rl("Invalid type");
54 return -EINVAL;
55 }
56
57 data->pdev_id = fixed_param->pdev_id;
58 WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_param->bssid, data->rap_addr.bytes);
59
60 return QDF_STATUS_SUCCESS;
61 }
62
63 /**
64 * send_set_rap_ps_cmd_tlv() - set interop issues ap mac address in fw
65 * @wmi_handle: wmi handle
66 * @rap: interop issues ap info
67 *
68 * Return: QDF_STATUS_SUCCESS for success or error code
69 */
70 static QDF_STATUS
send_set_rap_ps_cmd_tlv(wmi_unified_t wmi_handle,struct wlan_interop_issues_ap_info * rap)71 send_set_rap_ps_cmd_tlv(wmi_unified_t wmi_handle,
72 struct wlan_interop_issues_ap_info *rap)
73 {
74 wmi_pdev_set_rap_config_fixed_param *cmd;
75 wmi_pdev_set_rap_config_on_sta_ps_tlv_param *param;
76 uint8_t *buf_ptr;
77 wmi_buf_t buf;
78 uint32_t ret;
79 uint32_t len, count;
80 qdf_size_t i;
81
82 count = rap->count;
83 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + sizeof(*param) * count;
84 buf = wmi_buf_alloc(wmi_handle, len);
85 if (!buf)
86 return QDF_STATUS_E_FAILURE;
87
88 buf_ptr = wmi_buf_data(buf);
89 cmd = (wmi_pdev_set_rap_config_fixed_param *)buf_ptr;
90
91 WMITLV_SET_HDR(&cmd->tlv_header,
92 WMITLV_TAG_STRUC_wmi_pdev_set_rap_config_fixed_param,
93 WMITLV_GET_STRUCT_TLVLEN
94 (wmi_pdev_set_rap_config_fixed_param));
95 cmd->pdev_id = wmi_handle->ops->convert_pdev_id_host_to_target(
96 wmi_handle,
97 WMI_HOST_PDEV_ID_SOC);
98
99 cmd->type = WMI_ROGUE_AP_ON_STA_PS;
100 if (rap->detect_enable)
101 cmd->sta_ps_detection_enabled = 1;
102 else
103 cmd->sta_ps_detection_enabled = 0;
104
105 buf_ptr += sizeof(*cmd);
106
107 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
108 sizeof(wmi_pdev_set_rap_config_on_sta_ps_tlv_param) * count);
109 buf_ptr += WMI_TLV_HDR_SIZE;
110
111 for (i = 0; i < count; i++) {
112 param = (wmi_pdev_set_rap_config_on_sta_ps_tlv_param *)buf_ptr;
113 WMITLV_SET_HDR(¶m->tlv_header,
114 WMITLV_TAG_STRUC_wmi_pdev_set_rap_config_on_sta_ps_tlv_param,
115 WMITLV_GET_STRUCT_TLVLEN
116 (wmi_pdev_set_rap_config_on_sta_ps_tlv_param));
117 WMI_CHAR_ARRAY_TO_MAC_ADDR(rap->rap_items[i].bytes,
118 ¶m->bssid);
119 buf_ptr += sizeof(*param);
120 }
121
122 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
123 WMI_PDEV_SET_RAP_CONFIG_CMDID);
124 if (ret) {
125 wmi_buf_free(buf);
126 return QDF_STATUS_E_FAILURE;
127 }
128
129 return QDF_STATUS_SUCCESS;
130 }
131
wmi_interop_issues_ap_attach_tlv(wmi_unified_t wmi_handle)132 void wmi_interop_issues_ap_attach_tlv(wmi_unified_t wmi_handle)
133 {
134 struct wmi_ops *ops = wmi_handle->ops;
135
136 ops->extract_interop_issues_ap_ev_param =
137 extract_interop_issues_ap_ev_param_tlv;
138 ops->send_set_rap_ps_cmd = send_set_rap_ps_cmd_tlv;
139 }
140