diff --git a/drivers/net/wireless/cnss2/bus.c b/drivers/net/wireless/cnss2/bus.c index f97c3f0d3d1d..c590f53af8f2 100644 --- a/drivers/net/wireless/cnss2/bus.c +++ b/drivers/net/wireless/cnss2/bus.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include "bus.h" #include "debug.h" @@ -451,3 +451,34 @@ int cnss_bus_debug_reg_write(struct cnss_plat_data *plat_priv, u32 offset, return 0; } } + +int cnss_bus_get_iova(struct cnss_plat_data *plat_priv, u64 *addr, u64 *size) +{ + if (!plat_priv) + return -ENODEV; + + switch (plat_priv->bus_type) { + case CNSS_BUS_PCI: + return cnss_pci_get_iova(plat_priv->bus_priv, addr, size); + default: + cnss_pr_err("Unsupported bus type: %d\n", + plat_priv->bus_type); + return -EINVAL; + } +} + +int cnss_bus_get_iova_ipa(struct cnss_plat_data *plat_priv, u64 *addr, + u64 *size) +{ + if (!plat_priv) + return -ENODEV; + + switch (plat_priv->bus_type) { + case CNSS_BUS_PCI: + return cnss_pci_get_iova_ipa(plat_priv->bus_priv, addr, size); + default: + cnss_pr_err("Unsupported bus type: %d\n", + plat_priv->bus_type); + return -EINVAL; + } +} diff --git a/drivers/net/wireless/cnss2/bus.h b/drivers/net/wireless/cnss2/bus.h index 7c719f5f263e..4b9e91f5e0e8 100644 --- a/drivers/net/wireless/cnss2/bus.h +++ b/drivers/net/wireless/cnss2/bus.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CNSS_BUS_H #define _CNSS_BUS_H @@ -52,5 +52,7 @@ int cnss_bus_debug_reg_read(struct cnss_plat_data *plat_priv, u32 offset, u32 *val); int cnss_bus_debug_reg_write(struct cnss_plat_data *plat_priv, u32 offset, u32 val); - +int cnss_bus_get_iova(struct cnss_plat_data *plat_priv, u64 *addr, u64 *size); +int cnss_bus_get_iova_ipa(struct cnss_plat_data *plat_priv, u64 *addr, + u64 *size); #endif /* _CNSS_BUS_H */ diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index fb7ffb264396..00193d50e849 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -3297,6 +3297,34 @@ static void cnss_pci_deinit_smmu(struct cnss_pci_data *pci_priv) pci_priv->iommu_domain = NULL; } +int cnss_pci_get_iova(struct cnss_pci_data *pci_priv, u64 *addr, u64 *size) +{ + if (!pci_priv) + return -ENODEV; + + if (!pci_priv->smmu_iova_len) + return -EINVAL; + + *addr = pci_priv->smmu_iova_start; + *size = pci_priv->smmu_iova_len; + + return 0; +} + +int cnss_pci_get_iova_ipa(struct cnss_pci_data *pci_priv, u64 *addr, u64 *size) +{ + if (!pci_priv) + return -ENODEV; + + if (!pci_priv->smmu_iova_ipa_len) + return -EINVAL; + + *addr = pci_priv->smmu_iova_ipa_start; + *size = pci_priv->smmu_iova_ipa_len; + + return 0; +} + struct iommu_domain *cnss_smmu_get_domain(struct device *dev) { struct cnss_pci_data *pci_priv = cnss_get_pci_priv(to_pci_dev(dev)); diff --git a/drivers/net/wireless/cnss2/pci.h b/drivers/net/wireless/cnss2/pci.h index 3dfa83499e6d..3e872d17c19d 100644 --- a/drivers/net/wireless/cnss2/pci.h +++ b/drivers/net/wireless/cnss2/pci.h @@ -205,5 +205,8 @@ int cnss_pci_debug_reg_read(struct cnss_pci_data *pci_priv, u32 offset, u32 *val); int cnss_pci_debug_reg_write(struct cnss_pci_data *pci_priv, u32 offset, u32 val); +int cnss_pci_get_iova(struct cnss_pci_data *pci_priv, u64 *addr, u64 *size); +int cnss_pci_get_iova_ipa(struct cnss_pci_data *pci_priv, u64 *addr, + u64 *size); #endif /* _CNSS_PCI_H */ diff --git a/drivers/net/wireless/cnss2/qmi.c b/drivers/net/wireless/cnss2/qmi.c index 3904b2c59213..ea73016bf466 100644 --- a/drivers/net/wireless/cnss2/qmi.c +++ b/drivers/net/wireless/cnss2/qmi.c @@ -157,6 +157,8 @@ static int cnss_wlfw_host_cap_send_sync(struct cnss_plat_data *plat_priv) struct wlfw_host_cap_resp_msg_v01 *resp; struct qmi_txn txn; int ret = 0; + u64 iova_start = 0, iova_size = 0, + iova_ipa_start = 0, iova_ipa_size = 0; cnss_pr_dbg("Sending host capability message, state: 0x%lx\n", plat_priv->driver_state); @@ -198,6 +200,16 @@ static int cnss_wlfw_host_cap_send_sync(struct cnss_plat_data *plat_priv) req->cal_done = plat_priv->cal_done; cnss_pr_dbg("Calibration done is %d\n", plat_priv->cal_done); + if (!cnss_bus_get_iova(plat_priv, &iova_start, &iova_size) && + !cnss_bus_get_iova_ipa(plat_priv, &iova_ipa_start, + &iova_ipa_size)) { + req->ddr_range_valid = 1; + req->ddr_range[0].start = iova_start; + req->ddr_range[0].size = iova_size + iova_ipa_size; + cnss_pr_dbg("Sending iova starting 0x%llx with size 0x%llx\n", + req->ddr_range[0].start, req->ddr_range[0].size); + } + ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, wlfw_host_cap_resp_msg_v01_ei, resp); if (ret < 0) { diff --git a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c index 682a20b88950..2a24cd25878b 100644 --- a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c +++ b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #include "wlan_firmware_service_v01.h" @@ -431,6 +431,32 @@ static struct qmi_elem_info wlfw_fw_version_info_s_v01_ei[] = { }, }; +static struct qmi_elem_info wlfw_host_ddr_range_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_host_ddr_range_s_v01, + start), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_host_ddr_range_s_v01, + size), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { { .data_type = QMI_OPT_FLAG, @@ -2559,6 +2585,25 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .offset = offsetof(struct wlfw_host_cap_req_msg_v01, cal_duration), }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1E, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + ddr_range_valid), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_HOST_DDR_RANGE_SIZE_V01, + .elem_size = sizeof(struct wlfw_host_ddr_range_s_v01), + .array_type = STATIC_ARRAY, + .tlv_type = 0x1E, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + ddr_range), + .ei_array = wlfw_host_ddr_range_s_v01_ei, + }, { .data_type = QMI_EOTI, .array_type = NO_ARRAY, diff --git a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h index 0e18d8000c3f..5ca2866c4d2c 100644 --- a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h +++ b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #ifndef WLAN_FIRMWARE_SERVICE_V01_H #define WLAN_FIRMWARE_SERVICE_V01_H @@ -89,6 +89,7 @@ #define QMI_WLFW_MAX_DATA_SIZE_V01 6144 #define QMI_WLFW_FUNCTION_NAME_LEN_V01 128 #define QMI_WLFW_MAX_NUM_CE_V01 12 +#define QMI_WLFW_MAX_HOST_DDR_RANGE_SIZE_V01 3 #define QMI_WLFW_MAX_TIMESTAMP_LEN_V01 32 #define QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01 6144 #define QMI_WLFW_MAX_WFC_CALL_STATUS_DATA_SIZE_V01 256 @@ -244,6 +245,11 @@ struct wlfw_fw_version_info_s_v01 { char fw_build_timestamp[QMI_WLFW_MAX_TIMESTAMP_LEN_V01 + 1]; }; +struct wlfw_host_ddr_range_s_v01 { + u64 start; + u64 size; +}; + struct wlfw_ind_register_req_msg_v01 { u8 fw_ready_enable_valid; u8 fw_ready_enable; @@ -661,9 +667,12 @@ struct wlfw_host_cap_req_msg_v01 { u8 mem_cfg_mode; u8 cal_duration_valid; u16 cal_duration; + u8 ddr_range_valid; + struct wlfw_host_ddr_range_s_v01 + ddr_range[QMI_WLFW_MAX_HOST_DDR_RANGE_SIZE_V01]; }; -#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 194 +#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 245 extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[]; struct wlfw_host_cap_resp_msg_v01 {