1 /*
2 * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <wmi_unified_priv.h>
20 #include "wmi_unified_apf_tlv.h"
21 #include "wmi.h"
22
wmi_send_set_active_apf_mode_cmd_tlv(wmi_unified_t wmi_handle,uint8_t vdev_id,enum wmi_host_active_apf_mode ucast_mode,enum wmi_host_active_apf_mode mcast_bcast_mode)23 QDF_STATUS wmi_send_set_active_apf_mode_cmd_tlv(wmi_unified_t wmi_handle,
24 uint8_t vdev_id,
25 enum wmi_host_active_apf_mode
26 ucast_mode,
27 enum wmi_host_active_apf_mode
28 mcast_bcast_mode)
29 {
30 const WMITLV_TAG_ID tag_id =
31 WMITLV_TAG_STRUC_wmi_bpf_set_vdev_active_mode_cmd_fixed_param;
32 const uint32_t tlv_len = WMITLV_GET_STRUCT_TLVLEN(
33 wmi_bpf_set_vdev_active_mode_cmd_fixed_param);
34 QDF_STATUS status;
35 wmi_bpf_set_vdev_active_mode_cmd_fixed_param *cmd;
36 wmi_buf_t buf;
37
38 wmi_debug("Sending WMI_BPF_SET_VDEV_ACTIVE_MODE_CMDID(%u, %d, %d)",
39 vdev_id, ucast_mode, mcast_bcast_mode);
40
41 /* allocate command buffer */
42 buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
43 if (!buf) {
44 wmi_err("wmi_buf_alloc failed");
45 return QDF_STATUS_E_NOMEM;
46 }
47
48 /* set TLV header */
49 cmd = (wmi_bpf_set_vdev_active_mode_cmd_fixed_param *)wmi_buf_data(buf);
50 WMITLV_SET_HDR(&cmd->tlv_header, tag_id, tlv_len);
51
52 /* populate data */
53 cmd->vdev_id = vdev_id;
54 cmd->uc_mode = ucast_mode;
55 cmd->mcbc_mode = mcast_bcast_mode;
56
57 /* send to FW */
58 status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
59 WMI_BPF_SET_VDEV_ACTIVE_MODE_CMDID);
60 if (QDF_IS_STATUS_ERROR(status)) {
61 wmi_err("Failed to send WMI_BPF_SET_VDEV_ACTIVE_MODE_CMDID:%d",
62 status);
63 wmi_buf_free(buf);
64 return status;
65 }
66
67 return QDF_STATUS_SUCCESS;
68 }
69
wmi_send_apf_enable_cmd_tlv(wmi_unified_t wmi_handle,uint32_t vdev_id,bool enable)70 QDF_STATUS wmi_send_apf_enable_cmd_tlv(wmi_unified_t wmi_handle,
71 uint32_t vdev_id,
72 bool enable)
73 {
74 wmi_bpf_set_vdev_enable_cmd_fixed_param *cmd;
75 wmi_buf_t buf;
76
77 buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
78 if (!buf) {
79 wmi_err("wmi_buf_alloc failed");
80 return QDF_STATUS_E_NOMEM;
81 }
82
83 cmd = (wmi_bpf_set_vdev_enable_cmd_fixed_param *) wmi_buf_data(buf);
84 WMITLV_SET_HDR(&cmd->tlv_header,
85 WMITLV_TAG_STRUC_wmi_bpf_set_vdev_enable_cmd_fixed_param,
86 WMITLV_GET_STRUCT_TLVLEN(
87 wmi_bpf_set_vdev_enable_cmd_fixed_param));
88 cmd->vdev_id = vdev_id;
89 cmd->is_enabled = enable;
90
91 if (wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
92 WMI_BPF_SET_VDEV_ENABLE_CMDID)) {
93 wmi_err("Failed to enable/disable APF interpreter");
94 wmi_buf_free(buf);
95 return QDF_STATUS_E_FAILURE;
96 }
97
98 return QDF_STATUS_SUCCESS;
99 }
100
101 QDF_STATUS
wmi_send_apf_write_work_memory_cmd_tlv(wmi_unified_t wmi_handle,struct wmi_apf_write_memory_params * apf_write_params)102 wmi_send_apf_write_work_memory_cmd_tlv(wmi_unified_t wmi_handle,
103 struct wmi_apf_write_memory_params
104 *apf_write_params)
105 {
106 wmi_bpf_set_vdev_work_memory_cmd_fixed_param *cmd;
107 uint32_t wmi_buf_len;
108 wmi_buf_t buf;
109 uint8_t *buf_ptr;
110 uint32_t aligned_len = 0;
111
112 wmi_buf_len = sizeof(*cmd);
113 if (apf_write_params->length) {
114 aligned_len = roundup(apf_write_params->length,
115 sizeof(A_UINT32));
116
117 wmi_buf_len += WMI_TLV_HDR_SIZE + aligned_len;
118
119 }
120
121 buf = wmi_buf_alloc(wmi_handle, wmi_buf_len);
122 if (!buf) {
123 wmi_err("wmi_buf_alloc failed");
124 return QDF_STATUS_E_NOMEM;
125 }
126
127 buf_ptr = wmi_buf_data(buf);
128 cmd = (wmi_bpf_set_vdev_work_memory_cmd_fixed_param *)buf_ptr;
129 WMITLV_SET_HDR(&cmd->tlv_header,
130 WMITLV_TAG_STRUC_wmi_bpf_set_vdev_work_memory_cmd_fixed_param,
131 WMITLV_GET_STRUCT_TLVLEN(
132 wmi_bpf_set_vdev_work_memory_cmd_fixed_param));
133 cmd->vdev_id = apf_write_params->vdev_id;
134 cmd->bpf_version = apf_write_params->apf_version;
135 cmd->program_len = apf_write_params->program_len;
136 cmd->addr_offset = apf_write_params->addr_offset;
137 cmd->length = apf_write_params->length;
138
139 if (apf_write_params->length) {
140 buf_ptr += sizeof(*cmd);
141 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
142 aligned_len);
143 buf_ptr += WMI_TLV_HDR_SIZE;
144 qdf_mem_copy(buf_ptr, apf_write_params->buf,
145 apf_write_params->length);
146 }
147
148 if (wmi_unified_cmd_send(wmi_handle, buf, wmi_buf_len,
149 WMI_BPF_SET_VDEV_WORK_MEMORY_CMDID)) {
150 wmi_err("Failed to write APF work memory");
151 wmi_buf_free(buf);
152 return QDF_STATUS_E_FAILURE;
153 }
154
155 return QDF_STATUS_SUCCESS;
156 }
157
158 QDF_STATUS
wmi_send_apf_read_work_memory_cmd_tlv(wmi_unified_t wmi_handle,struct wmi_apf_read_memory_params * apf_read_params)159 wmi_send_apf_read_work_memory_cmd_tlv(wmi_unified_t wmi_handle,
160 struct wmi_apf_read_memory_params
161 *apf_read_params)
162 {
163 wmi_bpf_get_vdev_work_memory_cmd_fixed_param *cmd;
164 wmi_buf_t buf;
165
166 buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
167 if (!buf) {
168 wmi_err("wmi_buf_alloc failed");
169 return QDF_STATUS_E_NOMEM;
170 }
171
172 cmd = (wmi_bpf_get_vdev_work_memory_cmd_fixed_param *)
173 wmi_buf_data(buf);
174
175 WMITLV_SET_HDR(&cmd->tlv_header,
176 WMITLV_TAG_STRUC_wmi_bpf_get_vdev_work_memory_cmd_fixed_param,
177 WMITLV_GET_STRUCT_TLVLEN(
178 wmi_bpf_get_vdev_work_memory_cmd_fixed_param));
179 cmd->vdev_id = apf_read_params->vdev_id;
180 cmd->addr_offset = apf_read_params->addr_offset;
181 cmd->length = apf_read_params->length;
182
183 if (wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
184 WMI_BPF_GET_VDEV_WORK_MEMORY_CMDID)) {
185 wmi_err("Failed to get APF work memory");
186 wmi_buf_free(buf);
187 return QDF_STATUS_E_FAILURE;
188 }
189
190 return QDF_STATUS_SUCCESS;
191 }
192
193 QDF_STATUS
wmi_extract_apf_read_memory_resp_event_tlv(wmi_unified_t wmi_handle,void * evt_buf,struct wmi_apf_read_memory_resp_event_params * resp)194 wmi_extract_apf_read_memory_resp_event_tlv(wmi_unified_t wmi_handle,
195 void *evt_buf,
196 struct wmi_apf_read_memory_resp_event_params
197 *resp)
198 {
199 WMI_BPF_GET_VDEV_WORK_MEMORY_RESP_EVENTID_param_tlvs *param_buf;
200 wmi_bpf_get_vdev_work_memory_resp_evt_fixed_param *data_event;
201
202 param_buf = evt_buf;
203 if (!param_buf) {
204 wmi_err("encrypt decrypt resp evt_buf is NULL");
205 return QDF_STATUS_E_INVAL;
206 }
207
208 data_event = param_buf->fixed_param;
209
210 resp->vdev_id = data_event->vdev_id;
211 resp->offset = data_event->offset;
212 resp->more_data = data_event->fragment;
213
214 if (data_event->length > param_buf->num_data) {
215 wmi_err("FW msg data_len %d more than TLV hdr %d",
216 data_event->length,
217 param_buf->num_data);
218 return QDF_STATUS_E_INVAL;
219 }
220
221 if (data_event->length && param_buf->data) {
222 resp->length = data_event->length;
223 resp->data = (uint8_t *)param_buf->data;
224 }
225
226 return QDF_STATUS_SUCCESS;
227 }
228