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