Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 09f6b649 authored by Yue Ma's avatar Yue Ma Committed by Yu Wang
Browse files

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: default avatarYue Ma <yuem@codeaurora.org>
parent 4e4be78d
Loading
Loading
Loading
Loading
+32 −1
Original line number Diff line number Diff line
// 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;
	}
}
+4 −2
Original line number Diff line number Diff line
/* 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 */
+28 −0
Original line number Diff line number Diff line
@@ -3196,6 +3196,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));
+4 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */
/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */

#ifndef _CNSS_PCI_H
#define _CNSS_PCI_H
@@ -206,5 +206,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 */
+12 −0
Original line number Diff line number Diff line
@@ -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) {
Loading