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

Commit bba237ba authored by Mohammed Siddiq's avatar Mohammed Siddiq Committed by Gerrit - the friendly Code Review server
Browse files

icnss2: 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: I9663d9405bdb5907bcc1ca36e2d743d1ef8cb279
Signed-off-by: default avatarMohammed Siddiq <msiddiq@codeaurora.org>
parent 156dde9a
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -2911,6 +2911,12 @@ static int icnss_smmu_dt_parse(struct icnss_priv *priv)
	if (ret) {
		icnss_pr_err("SMMU IOVA base not found\n");
	} else {
		priv->smmu_iova_start = addr_win[0];
		priv->smmu_iova_len = addr_win[1];
		icnss_pr_dbg("SMMU IOVA start: %pa, len: %zx\n",
			     &priv->smmu_iova_start,
			     priv->smmu_iova_len);

		priv->iommu_domain =
			iommu_get_domain_for_dev(&pdev->dev);

@@ -2931,6 +2937,34 @@ static int icnss_smmu_dt_parse(struct icnss_priv *priv)
	return 0;
}

int icnss_get_iova(struct icnss_priv *priv, u64 *addr, u64 *size)
{
	if (!priv)
		return -ENODEV;

	if (!priv->smmu_iova_len)
		return -EINVAL;

	*addr = priv->smmu_iova_start;
	*size = priv->smmu_iova_len;

	return 0;
}

int icnss_get_iova_ipa(struct icnss_priv *priv, u64 *addr, u64 *size)
{
	if (!priv)
		return -ENODEV;

	if (!priv->smmu_iova_ipa_len)
		return -EINVAL;

	*addr = priv->smmu_iova_ipa_start;
	*size = priv->smmu_iova_ipa_len;

	return 0;
}

static const struct platform_device_id icnss_platform_id_table[] = {
	{ .name = "wcn6750", .driver_data = WCN6750_DEVICE_ID, },
	{ .name = "adrastea", .driver_data = ADRASTEA_DEVICE_ID, },
+4 −0
Original line number Diff line number Diff line
@@ -302,6 +302,8 @@ struct icnss_priv {
	void __iomem *mem_base_va;
	u32 mem_base_size;
	struct iommu_domain *iommu_domain;
	dma_addr_t smmu_iova_start;
	size_t smmu_iova_len;
	dma_addr_t smmu_iova_ipa_start;
	size_t smmu_iova_ipa_len;
	struct qmi_handle qmi;
@@ -394,5 +396,7 @@ char *icnss_soc_wake_event_to_str(enum icnss_soc_wake_event_type type);
int icnss_soc_wake_event_post(struct icnss_priv *priv,
			      enum icnss_soc_wake_event_type type,
			      u32 flags, void *data);
int icnss_get_iova(struct icnss_priv *priv, u64 *addr, u64 *size);
int icnss_get_iova_ipa(struct icnss_priv *priv, u64 *addr, u64 *size);
#endif
+12 −0
Original line number Diff line number Diff line
@@ -2225,6 +2225,8 @@ int wlfw_host_cap_send_sync(struct icnss_priv *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;

	icnss_pr_dbg("Sending host capability message, state: 0x%lx\n",
		    priv->state);
@@ -2254,6 +2256,16 @@ int wlfw_host_cap_send_sync(struct icnss_priv *priv)
	req->cal_done = priv->cal_done;
	icnss_pr_dbg("Calibration done is %d\n", priv->cal_done);

	if (!icnss_get_iova(priv, &iova_start, &iova_size) &&
	    !icnss_get_iova_ipa(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;
		icnss_pr_dbg("Sending iova starting 0x%llx with size 0x%llx\n",
			    req->ddr_range[0].start, req->ddr_range[0].size);
	}

	req->host_build_type_valid = 1;
	req->host_build_type = icnss_get_host_build_type();