1 /* 2 * Copyright (c) 2019-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 "osdep.h" 20 #include "wmi.h" 21 #include "wmi_unified_priv.h" 22 #include "wlan_fwol_public_structs.h" 23 #include "wmi_unified_fwol_api.h" 24 25 #ifdef WLAN_FEATURE_ELNA 26 /** 27 * send_set_elna_bypass_cmd_tlv() - send set elna bypass cmd to fw 28 * @wmi_handle: wmi handle 29 * @req: set eLNA bypass request 30 * 31 * Send WMI_SET_ELNA_BYPASS_CMDID to fw. 32 * 33 * Return: QDF_STATUS 34 */ 35 static QDF_STATUS 36 send_set_elna_bypass_cmd_tlv(wmi_unified_t wmi_handle, 37 struct set_elna_bypass_request *req) 38 { 39 wmi_buf_t buf; 40 wmi_set_elna_bypass_cmd_fixed_param *cmd; 41 uint16_t len = sizeof(*cmd); 42 QDF_STATUS ret; 43 44 buf = wmi_buf_alloc(wmi_handle, len); 45 if (!buf) { 46 WMI_LOGE("%s: Failed to allocate wmi buffer", __func__); 47 return QDF_STATUS_E_NOMEM; 48 } 49 50 cmd = (wmi_set_elna_bypass_cmd_fixed_param *)wmi_buf_data(buf); 51 WMITLV_SET_HDR(&cmd->tlv_header, 52 WMITLV_TAG_STRUC_wmi_set_elna_bypass_cmd_fixed_param, 53 WMITLV_GET_STRUCT_TLVLEN 54 (wmi_set_elna_bypass_cmd_fixed_param)); 55 cmd->vdev_id = req->vdev_id; 56 cmd->en_dis = req->en_dis; 57 wmi_mtrace(WMI_SET_ELNA_BYPASS_CMDID, req->vdev_id, req->en_dis); 58 ret = wmi_unified_cmd_send(wmi_handle, buf, len, 59 WMI_SET_ELNA_BYPASS_CMDID); 60 if (QDF_IS_STATUS_ERROR(ret)) { 61 WMI_LOGE("Failed to send set param command ret = %d", ret); 62 wmi_buf_free(buf); 63 } 64 65 return ret; 66 } 67 68 /** 69 * send_get_elna_bypass_cmd_tlv() - send get elna bypass cmd to fw 70 * @wmi_handle: wmi handle 71 * @req: get eLNA bypass request 72 * 73 * Send WMI_GET_ELNA_BYPASS_CMDID to fw. 74 * 75 * Return: QDF_STATUS 76 */ 77 static QDF_STATUS 78 send_get_elna_bypass_cmd_tlv(wmi_unified_t wmi_handle, 79 struct get_elna_bypass_request *req) 80 { 81 wmi_buf_t buf; 82 wmi_get_elna_bypass_cmd_fixed_param *cmd; 83 uint16_t len = sizeof(*cmd); 84 QDF_STATUS ret; 85 86 buf = wmi_buf_alloc(wmi_handle, len); 87 if (!buf) { 88 WMI_LOGE("%s: Failed to allocate wmi buffer", __func__); 89 return QDF_STATUS_E_NOMEM; 90 } 91 92 cmd = (wmi_get_elna_bypass_cmd_fixed_param *)wmi_buf_data(buf); 93 WMITLV_SET_HDR(&cmd->tlv_header, 94 WMITLV_TAG_STRUC_wmi_get_elna_bypass_cmd_fixed_param, 95 WMITLV_GET_STRUCT_TLVLEN 96 (wmi_get_elna_bypass_cmd_fixed_param)); 97 cmd->vdev_id = req->vdev_id; 98 wmi_mtrace(WMI_GET_ELNA_BYPASS_CMDID, req->vdev_id, 0); 99 ret = wmi_unified_cmd_send(wmi_handle, buf, len, 100 WMI_GET_ELNA_BYPASS_CMDID); 101 if (QDF_IS_STATUS_ERROR(ret)) { 102 WMI_LOGE("Failed to send set param command ret = %d", ret); 103 wmi_buf_free(buf); 104 } 105 106 return ret; 107 } 108 109 /** 110 * extract_get_elna_bypass_resp_tlv() - Extract WMI get eLNA bypass response 111 * @wmi_handle: wmi handle 112 * @resp_buf: response buffer 113 * @resp: get eLNA bypass response 114 * 115 * Extract WMI get eLNA bypass response from firmware. 116 * 117 * Return: QDF_STATUS 118 */ 119 static QDF_STATUS 120 extract_get_elna_bypass_resp_tlv(struct wmi_unified *wmi_handle, void *resp_buf, 121 struct get_elna_bypass_response *resp) 122 { 123 WMI_GET_ELNA_BYPASS_EVENTID_param_tlvs *param_buf; 124 wmi_get_elna_bypass_event_fixed_param *evt; 125 126 param_buf = resp_buf; 127 evt = param_buf->fixed_param; 128 if (!evt) { 129 WMI_LOGE("Invalid get elna bypass event"); 130 return QDF_STATUS_E_INVAL; 131 } 132 133 WMI_LOGD("Get elna bypass %d from vdev %d", evt->en_dis, evt->vdev_id); 134 135 resp->vdev_id = evt->vdev_id; 136 resp->en_dis = evt->en_dis; 137 138 return QDF_STATUS_SUCCESS; 139 } 140 #endif /* WLAN_FEATURE_ELNA */ 141 142 #ifdef WLAN_FEATURE_ELNA 143 static void wmi_fwol_attach_elna_tlv(struct wmi_ops *ops) 144 { 145 ops->send_set_elna_bypass_cmd = send_set_elna_bypass_cmd_tlv; 146 ops->send_get_elna_bypass_cmd = send_get_elna_bypass_cmd_tlv; 147 ops->extract_get_elna_bypass_resp = extract_get_elna_bypass_resp_tlv; 148 } 149 #else 150 static void wmi_fwol_attach_elna_tlv(struct wmi_ops *ops) 151 { 152 } 153 #endif /* WLAN_FEATURE_ELNA */ 154 155 #ifdef WLAN_SEND_DSCP_UP_MAP_TO_FW 156 /** 157 * send_dscp_tid_map_cmd_tlv() - send dscp to tid map cmd to fw 158 * @wmi_handle: wmi handle 159 * @dscp_to_tid_map: array of dscp to tid map values 160 * 161 * Send WMI_PDEV_SET_DSCP_TID_MAP_CMDID to fw. 162 * 163 * Return: QDF_STATUS 164 */ 165 static QDF_STATUS 166 send_dscp_tid_map_cmd_tlv(wmi_unified_t wmi_handle, 167 uint32_t *dscp_to_tid_map) 168 { 169 QDF_STATUS status; 170 wmi_pdev_set_dscp_tid_map_cmd_fixed_param *cmd; 171 wmi_buf_t buf; 172 uint16_t len = sizeof(*cmd); 173 174 buf = wmi_buf_alloc(wmi_handle, len); 175 if (!buf) { 176 WMI_LOGE("%s: Failed to allocate wmi buffer", __func__); 177 return QDF_STATUS_E_NOMEM; 178 } 179 180 cmd = (wmi_pdev_set_dscp_tid_map_cmd_fixed_param *)wmi_buf_data(buf); 181 WMITLV_SET_HDR( 182 &cmd->tlv_header, 183 WMITLV_TAG_STRUC_wmi_pdev_set_dscp_tid_map_cmd_fixed_param, 184 WMITLV_GET_STRUCT_TLVLEN 185 (wmi_pdev_set_dscp_tid_map_cmd_fixed_param)); 186 cmd->reserved0 = WMI_PDEV_ID_SOC; 187 qdf_mem_copy(&cmd->dscp_to_tid_map, dscp_to_tid_map, 188 sizeof(uint32_t) * WMI_DSCP_MAP_MAX); 189 190 status = wmi_unified_cmd_send(wmi_handle, buf, len, 191 WMI_PDEV_SET_DSCP_TID_MAP_CMDID); 192 if (status) { 193 WMI_LOGE("Failed to send dscp_up_map_to_fw %d", status); 194 wmi_buf_free(buf); 195 } 196 197 return status; 198 } 199 200 static void wmi_fwol_attach_dscp_tid_tlv(struct wmi_ops *ops) 201 { 202 ops->send_dscp_tid_map_cmd = send_dscp_tid_map_cmd_tlv; 203 } 204 #else 205 static void wmi_fwol_attach_dscp_tid_tlv(struct wmi_ops *ops) 206 { 207 } 208 #endif /* WLAN_SEND_DSCP_UP_MAP_TO_FW */ 209 210 void wmi_fwol_attach_tlv(wmi_unified_t wmi_handle) 211 { 212 struct wmi_ops *ops = wmi_handle->ops; 213 214 wmi_fwol_attach_elna_tlv(ops); 215 wmi_fwol_attach_dscp_tid_tlv(ops); 216 217 } 218