mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 13:49:24 -04:00
cnss2: Add support to send host SMMU IOVA range to firmware
With the valid SMMU IOVA range WLAN firmware is able to detect invalid host DDR access before SMMU fault happens. Change-Id: I3a3aac4e1da7bb7747bfe3b352df33fc87221860 Signed-off-by: Yue Ma <yuem@codeaurora.org>
This commit is contained in:
parent
304f2f125b
commit
e6437c634f
7 changed files with 136 additions and 6 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in a new issue