From 9370bb92b2d16684ee45cf24e879c93c509162da Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 19 Dec 2024 01:47:39 +0000
Subject: [PATCH] add wifi6 8852be driver

---
 kernel/drivers/video/rockchip/mpp/mpp_vepu2.c |   83 +++++++++++++++++++++++++++++++----------
 1 files changed, 63 insertions(+), 20 deletions(-)

diff --git a/kernel/drivers/video/rockchip/mpp/mpp_vepu2.c b/kernel/drivers/video/rockchip/mpp/mpp_vepu2.c
index 12aef5e..fb5f5e5 100644
--- a/kernel/drivers/video/rockchip/mpp/mpp_vepu2.c
+++ b/kernel/drivers/video/rockchip/mpp/mpp_vepu2.c
@@ -22,6 +22,7 @@
 #include <linux/proc_fs.h>
 #include <linux/nospec.h>
 #include <soc/rockchip/pm_domains.h>
+#include <soc/rockchip/rockchip_iommu.h>
 
 #include "mpp_debug.h"
 #include "mpp_common.h"
@@ -314,43 +315,40 @@
 
 static void *vepu_prepare(struct mpp_dev *mpp, struct mpp_task *mpp_task)
 {
-	struct mpp_taskqueue *queue = mpp->queue;
 	struct vepu_dev *enc = to_vepu_dev(mpp);
 	struct vepu_ccu *ccu = enc->ccu;
 	unsigned long core_idle;
 	unsigned long flags;
-	u32 core_id_max;
 	s32 core_id;
 	u32 i;
 
 	spin_lock_irqsave(&ccu->lock, flags);
 
-	core_idle = queue->core_idle;
-	core_id_max = queue->core_id_max;
+	core_idle = ccu->core_idle;
 
-	for (i = 0; i <= core_id_max; i++) {
-		struct mpp_dev *mpp = queue->cores[i];
+	for (i = 0; i < ccu->core_num; i++) {
+		struct mpp_dev *mpp = ccu->cores[i];
 
 		if (mpp && mpp->disable)
-			clear_bit(i, &core_idle);
+			clear_bit(mpp->core_id, &core_idle);
 	}
 
-	core_id = find_first_bit(&ccu->core_idle, ccu->core_num);
-	core_id = array_index_nospec(core_id, MPP_MAX_CORE_NUM);
-	if (core_id >= core_id_max + 1 || !queue->cores[core_id]) {
+	core_id = find_first_bit(&core_idle, ccu->core_num);
+	if (core_id >= ARRAY_SIZE(ccu->cores)) {
 		mpp_task = NULL;
 		mpp_dbg_core("core %d all busy %lx\n", core_id, ccu->core_idle);
-	} else {
-		unsigned long core_idle = ccu->core_idle;
-
-		clear_bit(core_id, &ccu->core_idle);
-		mpp_task->mpp = ccu->cores[core_id];
-		mpp_task->core_id = core_id;
-
-		mpp_dbg_core("core cnt %d core %d set idle %lx -> %lx\n",
-			     ccu->core_num, core_id, core_idle, ccu->core_idle);
+		goto done;
 	}
 
+	core_id = array_index_nospec(core_id, MPP_MAX_CORE_NUM);
+	clear_bit(core_id, &ccu->core_idle);
+	mpp_task->mpp = ccu->cores[core_id];
+	mpp_task->core_id = core_id;
+
+	mpp_dbg_core("core cnt %d core %d set idle %lx -> %lx\n",
+		     ccu->core_num, core_id, core_idle, ccu->core_idle);
+
+done:
 	spin_unlock_irqrestore(&ccu->lock, flags);
 
 	return mpp_task;
@@ -885,6 +883,48 @@
 	return 0;
 }
 
+static int vepu2_iommu_fault_handle(struct iommu_domain *iommu, struct device *iommu_dev,
+				    unsigned long iova, int status, void *arg)
+{
+	struct mpp_dev *mpp = (struct mpp_dev *)arg;
+	struct mpp_task *mpp_task;
+	struct vepu_dev *enc = to_vepu_dev(mpp);
+	struct vepu_ccu *ccu = enc->ccu;
+
+	dev_err(iommu_dev, "fault addr 0x%08lx status %x arg %p\n",
+		iova, status, arg);
+
+	if (ccu) {
+		int i;
+		struct mpp_dev *core;
+
+		for (i = 0; i < ccu->core_num; i++) {
+			core = ccu->cores[i];
+			if (core->iommu_info && (&core->iommu_info->pdev->dev == iommu_dev)) {
+				mpp = core;
+				break;
+			}
+		}
+	}
+
+	if (!mpp) {
+		dev_err(iommu_dev, "pagefault without device to handle\n");
+		return 0;
+	}
+	mpp_task = mpp->cur_task;
+	if (mpp_task)
+		mpp_task_dump_mem_region(mpp, mpp_task);
+
+	mpp_task_dump_hw_reg(mpp);
+	/*
+	 * Mask iommu irq, in order for iommu not repeatedly trigger pagefault.
+	 * Until the pagefault task finish by hw timeout.
+	 */
+	rockchip_iommu_mask_irq(mpp->dev);
+
+	return 0;
+}
+
 static struct mpp_hw_ops vepu_v2_hw_ops = {
 	.init = vepu_init,
 	.clk_on = vepu_clk_on,
@@ -1050,7 +1090,8 @@
 		ccu_info = ccu->main_core->iommu_info;
 		cur_info = enc->mpp.iommu_info;
 
-		cur_info->domain = ccu_info->domain;
+		if (cur_info)
+			cur_info->domain = ccu_info->domain;
 		mpp_iommu_attach(cur_info);
 	}
 	enc->ccu = ccu;
@@ -1102,6 +1143,7 @@
 		return -EINVAL;
 	}
 
+	mpp->fault_handler = vepu2_iommu_fault_handle;
 	mpp->session_max_buffers = VEPU2_SESSION_MAX_BUFFERS;
 	vepu_procfs_init(mpp);
 	vepu_procfs_ccu_init(mpp);
@@ -1151,6 +1193,7 @@
 		return -EINVAL;
 	}
 
+	mpp->fault_handler = vepu2_iommu_fault_handle;
 	mpp->session_max_buffers = VEPU2_SESSION_MAX_BUFFERS;
 	vepu_procfs_init(mpp);
 	/* register current device to mpp service */

--
Gitblit v1.6.2