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 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 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 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 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 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