diff --git a/wmi/inc/wmi_unified_fwol_api.h b/wmi/inc/wmi_unified_fwol_api.h index 478246ca3e..d88264cec6 100644 --- a/wmi/inc/wmi_unified_fwol_api.h +++ b/wmi/inc/wmi_unified_fwol_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -87,4 +87,19 @@ wmi_unified_send_dscp_tip_map_cmd(struct wmi_unified *wmi_handle, } #endif /* WLAN_SEND_DSCP_UP_MAP_TO_FW */ +#ifdef WLAN_FEATURE_MDNS_OFFLOAD +/** + * wmi_unified_send_set_mdns_config_cmd() - Send WMI set mDNS config cmd + * @wmi_handle: wmi handle + * @mdns_info: mdns config info + * + * Send WMI set mDNS config command to firmware. + * + * Return: QDF_STATUS + */ +QDF_STATUS +wmi_unified_send_set_mdns_config_cmd(struct wmi_unified *wmi_handle, + struct mdns_config_info *mdns_info); +#endif /* WLAN_FEATURE_MDNS_OFFLOAD */ + #endif /* _WMI_UNIFIED_FWOL_API_H_ */ diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index 72ada5d406..1e0012f1c6 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -2488,6 +2488,11 @@ QDF_STATUS (*send_dscp_tid_map_cmd)(wmi_unified_t wmi_handle, uint32_t *dscp_to_tid_map); #endif +#ifdef WLAN_FEATURE_MDNS_OFFLOAD +QDF_STATUS (*send_set_mdns_config_cmd)(wmi_unified_t wmi_handle, + struct mdns_config_info *mdns_info); +#endif /* WLAN_FEATURE_MDNS_OFFLOAD */ + QDF_STATUS (*send_pdev_get_pn_cmd)(wmi_unified_t wmi_handle, struct peer_request_pn_param *pn_params); QDF_STATUS (*extract_get_pn_data)(wmi_unified_t wmi_handle, diff --git a/wmi/src/wmi_unified_fwol_api.c b/wmi/src/wmi_unified_fwol_api.c index 7bca133af9..e50941d38c 100644 --- a/wmi/src/wmi_unified_fwol_api.c +++ b/wmi/src/wmi_unified_fwol_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -71,3 +71,16 @@ wmi_unified_send_dscp_tip_map_cmd(struct wmi_unified *wmi_handle, return QDF_STATUS_E_FAILURE; } #endif /* WLAN_SEND_DSCP_UP_MAP_TO_FW */ + +#ifdef WLAN_FEATURE_MDNS_OFFLOAD +QDF_STATUS +wmi_unified_send_set_mdns_config_cmd(struct wmi_unified *wmi_handle, + struct mdns_config_info *mdns_info) +{ + if (wmi_handle->ops->send_set_mdns_config_cmd) + return wmi_handle->ops->send_set_mdns_config_cmd(wmi_handle, + mdns_info); + + return QDF_STATUS_E_FAILURE; +} +#endif /* WLAN_FEATURE_MDNS_OFFLOAD */ diff --git a/wmi/src/wmi_unified_fwol_tlv.c b/wmi/src/wmi_unified_fwol_tlv.c index 39751fd83d..08735f97df 100644 --- a/wmi/src/wmi_unified_fwol_tlv.c +++ b/wmi/src/wmi_unified_fwol_tlv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -207,11 +207,232 @@ static void wmi_fwol_attach_dscp_tid_tlv(struct wmi_ops *ops) } #endif /* WLAN_SEND_DSCP_UP_MAP_TO_FW */ +#ifdef WLAN_FEATURE_MDNS_OFFLOAD +/** + * send_set_mdns_fqdn_cmd_tlv() - send set mDNS FQDN cmd to fw + * @wmi_handle: wmi handle + * @mdns_info: mDNS config info + * + * Send WMI_MDNS_SET_FQDN_CMDID to fw. + * + * Return: QDF_STATUS + */ +static QDF_STATUS +send_set_mdns_fqdn_cmd_tlv(wmi_unified_t wmi_handle, + struct mdns_config_info *mdns_info) +{ + wmi_buf_t buf; + uint8_t *buf_ptr; + wmi_mdns_set_fqdn_cmd_fixed_param *cmd; + uint16_t len = sizeof(*cmd); + uint16_t fqdn_len_aligned; + QDF_STATUS ret; + + fqdn_len_aligned = roundup(mdns_info->fqdn_len, sizeof(uint32_t)); + if (fqdn_len_aligned < mdns_info->fqdn_len) { + wmi_err_rl("integer overflow while rounding up data_len"); + return QDF_STATUS_E_FAILURE; + } + + if (fqdn_len_aligned > WMI_SVC_MSG_MAX_SIZE - WMI_TLV_HDR_SIZE) { + wmi_err_rl("wmi_max_msg_size overflow for given data_len"); + return QDF_STATUS_E_FAILURE; + } + + len += WMI_TLV_HDR_SIZE + fqdn_len_aligned; + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + wmi_err_rl("Failed to allocate wmi buffer"); + return QDF_STATUS_E_NOMEM; + } + + buf_ptr = wmi_buf_data(buf); + cmd = (wmi_mdns_set_fqdn_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_mdns_set_fqdn_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_mdns_set_fqdn_cmd_fixed_param)); + cmd->vdev_id = mdns_info->vdev_id; + cmd->type = mdns_info->fqdn_type; + cmd->fqdn_len = mdns_info->fqdn_len; + buf_ptr += sizeof(*cmd); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, fqdn_len_aligned); + buf_ptr += WMI_TLV_HDR_SIZE; + qdf_mem_copy(buf_ptr, mdns_info->fqdn_data, cmd->fqdn_len); + + wmi_mtrace(WMI_MDNS_SET_FQDN_CMDID, mdns_info->vdev_id, + mdns_info->fqdn_type); + + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_MDNS_SET_FQDN_CMDID); + if (QDF_IS_STATUS_ERROR(ret)) + wmi_buf_free(buf); + + return ret; +} + +/** + * send_set_mdns_response_cmd_tlv() - send set mDNS response cmd to fw + * @wmi_handle: wmi handle + * @mdns_info: mDNS config info + * + * Send WMI_MDNS_SET_RESPONSE_CMDID to fw. + * + * Return: QDF_STATUS + */ +static QDF_STATUS +send_set_mdns_response_cmd_tlv(wmi_unified_t wmi_handle, + struct mdns_config_info *mdns_info) +{ + wmi_buf_t buf; + uint8_t *buf_ptr; + wmi_mdns_set_resp_cmd_fixed_param *cmd; + uint16_t len = sizeof(*cmd); + uint16_t resp_len_aligned; + QDF_STATUS ret; + + resp_len_aligned = roundup(mdns_info->answer_payload_len, sizeof(uint32_t)); + if (resp_len_aligned < mdns_info->answer_payload_len) { + wmi_err_rl("integer overflow while rounding up data_len"); + return QDF_STATUS_E_FAILURE; + } + + if (resp_len_aligned > WMI_SVC_MSG_MAX_SIZE - WMI_TLV_HDR_SIZE) { + wmi_err_rl("wmi_max_msg_size overflow for given data_len"); + return QDF_STATUS_E_FAILURE; + } + + len += WMI_TLV_HDR_SIZE + resp_len_aligned; + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + wmi_err_rl("Failed to allocate wmi buffer"); + return QDF_STATUS_E_NOMEM; + } + + buf_ptr = wmi_buf_data(buf); + cmd = (wmi_mdns_set_resp_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_mdns_set_resp_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_mdns_set_resp_cmd_fixed_param)); + cmd->vdev_id = mdns_info->vdev_id; + cmd->AR_count = mdns_info->resource_record_count; + cmd->resp_len = mdns_info->answer_payload_len; + buf_ptr += sizeof(*cmd); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, resp_len_aligned); + buf_ptr += WMI_TLV_HDR_SIZE; + qdf_mem_copy(buf_ptr, mdns_info->answer_payload_data, cmd->resp_len); + + wmi_mtrace(WMI_MDNS_SET_RESPONSE_CMDID, mdns_info->vdev_id, 0); + + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_MDNS_SET_RESPONSE_CMDID); + if (QDF_IS_STATUS_ERROR(ret)) + wmi_buf_free(buf); + + return ret; +} + +/** + * send_set_mdns_offload_cmd_tlv() - send set mDNS offload cmd to fw + * @wmi_handle: wmi handle + * @mdns_info: mDNS config info + * + * Send WMI_MDNS_OFFLOAD_ENABLE_CMDID to fw. + * + * Return: QDF_STATUS + */ +static QDF_STATUS +send_set_mdns_offload_cmd_tlv(wmi_unified_t wmi_handle, + struct mdns_config_info *mdns_info) +{ + wmi_buf_t buf; + wmi_mdns_offload_cmd_fixed_param *cmd; + uint16_t len = sizeof(*cmd); + QDF_STATUS ret; + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + wmi_err_rl("Failed to allocate wmi buffer"); + return QDF_STATUS_E_NOMEM; + } + + cmd = (wmi_mdns_offload_cmd_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_mdns_offload_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_mdns_offload_cmd_fixed_param)); + cmd->vdev_id = mdns_info->vdev_id; + cmd->enable = mdns_info->enable; + + wmi_mtrace(WMI_MDNS_OFFLOAD_ENABLE_CMDID, mdns_info->vdev_id, 0); + + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_MDNS_OFFLOAD_ENABLE_CMDID); + if (QDF_IS_STATUS_ERROR(ret)) + wmi_buf_free(buf); + + return ret; +} + +/** + * send_set_mdns_config_cmd_tlv() - send set mDNS config cmd to fw + * @wmi_handle: wmi handle + * @mdns_info: mdns config info + * + * Return: QDF_STATUS + */ +static QDF_STATUS +send_set_mdns_config_cmd_tlv(wmi_unified_t wmi_handle, + struct mdns_config_info *mdns_info) +{ + QDF_STATUS ret; + + if (!mdns_info->enable) { + ret = send_set_mdns_offload_cmd_tlv(wmi_handle, mdns_info); + if (QDF_IS_STATUS_ERROR(ret)) + wmi_err_rl("Failed to send mDNS offload command. ret = %d", ret); + + return ret; + } + + ret = send_set_mdns_fqdn_cmd_tlv(wmi_handle, mdns_info); + if (QDF_IS_STATUS_ERROR(ret)) { + wmi_err_rl("Failed to send set fqdn command. ret = %d", ret); + return ret; + } + + ret = send_set_mdns_response_cmd_tlv(wmi_handle, mdns_info); + if (QDF_IS_STATUS_ERROR(ret)) { + wmi_err_rl("Failed to send set mDNS response command. ret = %d", ret); + return ret; + } + + ret = send_set_mdns_offload_cmd_tlv(wmi_handle, mdns_info); + if (QDF_IS_STATUS_ERROR(ret)) { + wmi_err_rl("Failed to send set mDNS offload command. ret = %d", ret); + return ret; + } + + return ret; +} + +static void wmi_fwol_attach_mdns_tlv(struct wmi_ops *ops) +{ + ops->send_set_mdns_config_cmd = send_set_mdns_config_cmd_tlv; +} +#else +static void wmi_fwol_attach_mdns_tlv(struct wmi_ops *ops) +{ +} +#endif /* WLAN_FEATURE_MDNS_OFFLOAD */ + void wmi_fwol_attach_tlv(wmi_unified_t wmi_handle) { struct wmi_ops *ops = wmi_handle->ops; wmi_fwol_attach_elna_tlv(ops); wmi_fwol_attach_dscp_tid_tlv(ops); + wmi_fwol_attach_mdns_tlv(ops); }