xref: /wlan-dirver/qca-wifi-host-cmn/wmi/src/wmi_unified_apf_tlv.c (revision 503663c6daafffe652fa360bde17243568cd6d2a)
1 /*
2  * Copyright (c) 2016-2019 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_apf_tlv.h"
20 #include "wmi.h"
21 
22 QDF_STATUS wmi_send_set_active_apf_mode_cmd_tlv(wmi_unified_t wmi_handle,
23 					    uint8_t vdev_id,
24 					    enum wmi_host_active_apf_mode
25 								     ucast_mode,
26 					    enum wmi_host_active_apf_mode
27 							       mcast_bcast_mode)
28 {
29 	const WMITLV_TAG_ID tag_id =
30 		WMITLV_TAG_STRUC_wmi_bpf_set_vdev_active_mode_cmd_fixed_param;
31 	const uint32_t tlv_len = WMITLV_GET_STRUCT_TLVLEN(
32 				wmi_bpf_set_vdev_active_mode_cmd_fixed_param);
33 	QDF_STATUS status;
34 	wmi_bpf_set_vdev_active_mode_cmd_fixed_param *cmd;
35 	wmi_buf_t buf;
36 
37 	WMI_LOGD("Sending WMI_BPF_SET_VDEV_ACTIVE_MODE_CMDID(%u, %d, %d)",
38 		 vdev_id, ucast_mode, mcast_bcast_mode);
39 
40 	/* allocate command buffer */
41 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
42 	if (!buf) {
43 		WMI_LOGE("%s: wmi_buf_alloc failed", __func__);
44 		return QDF_STATUS_E_NOMEM;
45 	}
46 
47 	/* set TLV header */
48 	cmd = (wmi_bpf_set_vdev_active_mode_cmd_fixed_param *)wmi_buf_data(buf);
49 	WMITLV_SET_HDR(&cmd->tlv_header, tag_id, tlv_len);
50 
51 	/* populate data */
52 	cmd->vdev_id = vdev_id;
53 	cmd->uc_mode = ucast_mode;
54 	cmd->mcbc_mode = mcast_bcast_mode;
55 
56 	/* send to FW */
57 	status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
58 				      WMI_BPF_SET_VDEV_ACTIVE_MODE_CMDID);
59 	if (QDF_IS_STATUS_ERROR(status)) {
60 		WMI_LOGE("Failed to send WMI_BPF_SET_VDEV_ACTIVE_MODE_CMDID:%d",
61 			 status);
62 		wmi_buf_free(buf);
63 		return status;
64 	}
65 
66 	return QDF_STATUS_SUCCESS;
67 }
68 
69 QDF_STATUS wmi_send_apf_enable_cmd_tlv(wmi_unified_t wmi_handle,
70 				       uint32_t vdev_id,
71 				       bool enable)
72 {
73 	wmi_bpf_set_vdev_enable_cmd_fixed_param *cmd;
74 	wmi_buf_t buf;
75 
76 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
77 	if (!buf) {
78 		WMI_LOGP("%s: wmi_buf_alloc failed", __func__);
79 		return QDF_STATUS_E_NOMEM;
80 	}
81 
82 	cmd = (wmi_bpf_set_vdev_enable_cmd_fixed_param *) wmi_buf_data(buf);
83 	WMITLV_SET_HDR(&cmd->tlv_header,
84 		WMITLV_TAG_STRUC_wmi_bpf_set_vdev_enable_cmd_fixed_param,
85 		WMITLV_GET_STRUCT_TLVLEN(
86 			wmi_bpf_set_vdev_enable_cmd_fixed_param));
87 	cmd->vdev_id = vdev_id;
88 	cmd->is_enabled = enable;
89 
90 	if (wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
91 				 WMI_BPF_SET_VDEV_ENABLE_CMDID)) {
92 		WMI_LOGE("%s: Failed to enable/disable APF interpreter",
93 			 __func__);
94 		wmi_buf_free(buf);
95 		return QDF_STATUS_E_FAILURE;
96 	}
97 
98 	return QDF_STATUS_SUCCESS;
99 }
100 
101 QDF_STATUS
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_LOGP("%s: wmi_buf_alloc failed", __func__);
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_LOGE("%s: Failed to write APF work memory", __func__);
151 		wmi_buf_free(buf);
152 		return QDF_STATUS_E_FAILURE;
153 	}
154 
155 	return QDF_STATUS_SUCCESS;
156 }
157 
158 QDF_STATUS
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_LOGP("%s: wmi_buf_alloc failed", __func__);
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_LOGE("%s: Failed to get APF work memory", __func__);
186 		wmi_buf_free(buf);
187 		return QDF_STATUS_E_FAILURE;
188 	}
189 
190 	return QDF_STATUS_SUCCESS;
191 }
192 
193 QDF_STATUS
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_LOGE("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_LOGE("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