1 /* 2 * Copyright (c) 2016-2018 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 resp->length = data_event->length; 220 221 if (resp->length) 222 resp->data = (uint8_t *)param_buf->data; 223 224 return QDF_STATUS_SUCCESS; 225 } 226