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