xref: /wlan-dirver/qca-wifi-host-cmn/wmi/src/wmi_unified_apf_tlv.c (revision dd4dc88b837a295134aa9869114a2efee0f4894b)
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 
21 QDF_STATUS wmi_send_set_active_apf_mode_cmd_tlv(wmi_unified_t wmi_handle,
22 					    uint8_t vdev_id,
23 					    enum wmi_host_active_apf_mode
24 								     ucast_mode,
25 					    enum wmi_host_active_apf_mode
26 							       mcast_bcast_mode)
27 {
28 	const WMITLV_TAG_ID tag_id =
29 		WMITLV_TAG_STRUC_wmi_bpf_set_vdev_active_mode_cmd_fixed_param;
30 	const uint32_t tlv_len = WMITLV_GET_STRUCT_TLVLEN(
31 				wmi_bpf_set_vdev_active_mode_cmd_fixed_param);
32 	QDF_STATUS status;
33 	wmi_bpf_set_vdev_active_mode_cmd_fixed_param *cmd;
34 	wmi_buf_t buf;
35 
36 	WMI_LOGD("Sending WMI_BPF_SET_VDEV_ACTIVE_MODE_CMDID(%u, %d, %d)",
37 		 vdev_id, ucast_mode, mcast_bcast_mode);
38 
39 	/* allocate command buffer */
40 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
41 	if (!buf) {
42 		WMI_LOGE("%s: wmi_buf_alloc failed", __func__);
43 		return QDF_STATUS_E_NOMEM;
44 	}
45 
46 	/* set TLV header */
47 	cmd = (wmi_bpf_set_vdev_active_mode_cmd_fixed_param *)wmi_buf_data(buf);
48 	WMITLV_SET_HDR(&cmd->tlv_header, tag_id, tlv_len);
49 
50 	/* populate data */
51 	cmd->vdev_id = vdev_id;
52 	cmd->uc_mode = ucast_mode;
53 	cmd->mcbc_mode = mcast_bcast_mode;
54 
55 	/* send to FW */
56 	status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
57 				      WMI_BPF_SET_VDEV_ACTIVE_MODE_CMDID);
58 	if (QDF_IS_STATUS_ERROR(status)) {
59 		WMI_LOGE("Failed to send WMI_BPF_SET_VDEV_ACTIVE_MODE_CMDID:%d",
60 			 status);
61 		wmi_buf_free(buf);
62 		return status;
63 	}
64 
65 	return QDF_STATUS_SUCCESS;
66 }
67 
68 QDF_STATUS wmi_send_apf_enable_cmd_tlv(wmi_unified_t wmi_handle,
69 				       uint32_t vdev_id,
70 				       bool enable)
71 {
72 	wmi_bpf_set_vdev_enable_cmd_fixed_param *cmd;
73 	wmi_buf_t buf;
74 
75 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
76 	if (!buf) {
77 		WMI_LOGP("%s: wmi_buf_alloc failed", __func__);
78 		return QDF_STATUS_E_NOMEM;
79 	}
80 
81 	cmd = (wmi_bpf_set_vdev_enable_cmd_fixed_param *) wmi_buf_data(buf);
82 	WMITLV_SET_HDR(&cmd->tlv_header,
83 		WMITLV_TAG_STRUC_wmi_bpf_set_vdev_enable_cmd_fixed_param,
84 		WMITLV_GET_STRUCT_TLVLEN(
85 			wmi_bpf_set_vdev_enable_cmd_fixed_param));
86 	cmd->vdev_id = vdev_id;
87 	cmd->is_enabled = enable;
88 
89 	if (wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
90 				 WMI_BPF_SET_VDEV_ENABLE_CMDID)) {
91 		WMI_LOGE("%s: Failed to enable/disable APF interpreter",
92 			 __func__);
93 		wmi_buf_free(buf);
94 		return QDF_STATUS_E_FAILURE;
95 	}
96 
97 	return QDF_STATUS_SUCCESS;
98 }
99 
100 QDF_STATUS
101 wmi_send_apf_write_work_memory_cmd_tlv(wmi_unified_t wmi_handle,
102 				       struct wmi_apf_write_memory_params
103 							      *apf_write_params)
104 {
105 	wmi_bpf_set_vdev_work_memory_cmd_fixed_param *cmd;
106 	uint32_t wmi_buf_len;
107 	wmi_buf_t buf;
108 	uint8_t *buf_ptr;
109 	uint32_t aligned_len = 0;
110 
111 	wmi_buf_len = sizeof(*cmd);
112 	if (apf_write_params->length) {
113 		aligned_len = roundup(apf_write_params->length,
114 				      sizeof(A_UINT32));
115 
116 		wmi_buf_len += WMI_TLV_HDR_SIZE + aligned_len;
117 
118 	}
119 
120 	buf = wmi_buf_alloc(wmi_handle, wmi_buf_len);
121 	if (!buf) {
122 		WMI_LOGP("%s: wmi_buf_alloc failed", __func__);
123 		return QDF_STATUS_E_NOMEM;
124 	}
125 
126 	buf_ptr = wmi_buf_data(buf);
127 	cmd = (wmi_bpf_set_vdev_work_memory_cmd_fixed_param *)buf_ptr;
128 	WMITLV_SET_HDR(&cmd->tlv_header,
129 		WMITLV_TAG_STRUC_wmi_bpf_set_vdev_work_memory_cmd_fixed_param,
130 		WMITLV_GET_STRUCT_TLVLEN(
131 			wmi_bpf_set_vdev_work_memory_cmd_fixed_param));
132 	cmd->vdev_id = apf_write_params->vdev_id;
133 	cmd->bpf_version = apf_write_params->apf_version;
134 	cmd->program_len = apf_write_params->program_len;
135 	cmd->addr_offset = apf_write_params->addr_offset;
136 	cmd->length = apf_write_params->length;
137 
138 	if (apf_write_params->length) {
139 		buf_ptr += sizeof(*cmd);
140 		WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
141 			       aligned_len);
142 		buf_ptr += WMI_TLV_HDR_SIZE;
143 		qdf_mem_copy(buf_ptr, apf_write_params->buf,
144 			     apf_write_params->length);
145 	}
146 
147 	if (wmi_unified_cmd_send(wmi_handle, buf, wmi_buf_len,
148 				 WMI_BPF_SET_VDEV_WORK_MEMORY_CMDID)) {
149 		WMI_LOGE("%s: Failed to write APF work memory", __func__);
150 		wmi_buf_free(buf);
151 		return QDF_STATUS_E_FAILURE;
152 	}
153 
154 	return QDF_STATUS_SUCCESS;
155 }
156 
157 QDF_STATUS
158 wmi_send_apf_read_work_memory_cmd_tlv(wmi_unified_t wmi_handle,
159 				      struct wmi_apf_read_memory_params
160 							       *apf_read_params)
161 {
162 	wmi_bpf_get_vdev_work_memory_cmd_fixed_param *cmd;
163 	wmi_buf_t buf;
164 
165 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
166 	if (!buf) {
167 		WMI_LOGP("%s: wmi_buf_alloc failed", __func__);
168 		return QDF_STATUS_E_NOMEM;
169 	}
170 
171 	cmd = (wmi_bpf_get_vdev_work_memory_cmd_fixed_param *)
172 							wmi_buf_data(buf);
173 
174 	WMITLV_SET_HDR(&cmd->tlv_header,
175 		WMITLV_TAG_STRUC_wmi_bpf_get_vdev_work_memory_cmd_fixed_param,
176 		WMITLV_GET_STRUCT_TLVLEN(
177 			wmi_bpf_get_vdev_work_memory_cmd_fixed_param));
178 	cmd->vdev_id = apf_read_params->vdev_id;
179 	cmd->addr_offset = apf_read_params->addr_offset;
180 	cmd->length = apf_read_params->length;
181 
182 	if (wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
183 				 WMI_BPF_GET_VDEV_WORK_MEMORY_CMDID)) {
184 		WMI_LOGE("%s: Failed to get APF work memory", __func__);
185 		wmi_buf_free(buf);
186 		return QDF_STATUS_E_FAILURE;
187 	}
188 
189 	return QDF_STATUS_SUCCESS;
190 }
191 
192 QDF_STATUS
193 wmi_extract_apf_read_memory_resp_event_tlv(wmi_unified_t wmi_handle,
194 				void *evt_buf,
195 				struct wmi_apf_read_memory_resp_event_params
196 									  *resp)
197 {
198 	WMI_BPF_GET_VDEV_WORK_MEMORY_RESP_EVENTID_param_tlvs *param_buf;
199 	wmi_bpf_get_vdev_work_memory_resp_evt_fixed_param *data_event;
200 
201 	param_buf = evt_buf;
202 	if (!param_buf) {
203 		WMI_LOGE("encrypt decrypt resp evt_buf is NULL");
204 		return QDF_STATUS_E_INVAL;
205 	}
206 
207 	data_event = param_buf->fixed_param;
208 
209 	resp->vdev_id = data_event->vdev_id;
210 	resp->offset = data_event->offset;
211 	resp->more_data = data_event->fragment;
212 
213 	if (data_event->length > param_buf->num_data) {
214 		WMI_LOGE("FW msg data_len %d more than TLV hdr %d",
215 			 data_event->length,
216 			 param_buf->num_data);
217 		return QDF_STATUS_E_INVAL;
218 	}
219 
220 	if (data_event->length && param_buf->data) {
221 		resp->length = data_event->length;
222 		resp->data = (uint8_t *)param_buf->data;
223 	}
224 
225 	return QDF_STATUS_SUCCESS;
226 }
227