gxp: [Copybara Auto Merge] Merge branch 'zuma' into 'android14-gs-pixel-5.15-udc-qpr1'

gxp: deactivate context on domain detaching
Introduce gxp_soc_deactivate_context to disable context that not in use.
Note this function would be meaningless if SSMT is clamp-mode, under
which case we have no way to disable contexts since we don't know which
(physical) core will be scheduled to use by MCU.
Test: gxp_smoke_test * 4 passed. Can see faults if without calling
soc_activacte_context as expected.
Bug: 290708708
(cherry picked from commit 4696e2562571d007c839dd9e575281ab407ac9ac)
GitOrigin-RevId: e678afd3102c5ee61bc9c8b149a1683c51df37f0
Change-Id: I17453f940adb0656ee720bed155daa16ea1b41af
diff --git a/gxp-dma-iommu.c b/gxp-dma-iommu.c
index 1d60888..5aa8b5d 100644
--- a/gxp-dma-iommu.c
+++ b/gxp-dma-iommu.c
@@ -68,17 +68,16 @@
 	}
 }
 
-static int gxp_dma_ssmt_program(struct gxp_dev *gxp,
-				struct iommu_domain *domain, uint core_list)
+static int gxp_dma_ssmt_activate(struct gxp_dev *gxp,
+				 struct iommu_domain *domain, uint core_list)
 {
 	struct gxp_dma_iommu_manager *mgr = container_of(
 		gxp->dma_mgr, struct gxp_dma_iommu_manager, dma_mgr);
-	int pasid;
 	uint core;
+	int pasid = iommu_aux_get_pasid(domain, gxp->dev);
 
 	/* Program VID only when cores are managed by us. */
 	if (gxp_is_direct_mode(gxp) || gxp_core_boot(gxp)) {
-		pasid = iommu_aux_get_pasid(domain, gxp->dev);
 		for (core = 0; core < GXP_NUM_CORES; core++)
 			if (BIT(core) & core_list) {
 				dev_dbg(gxp->dev, "Assign core%u to PASID %d\n",
@@ -86,11 +85,30 @@
 				gxp_ssmt_set_core_vid(&mgr->ssmt, core, pasid);
 			}
 	} else {
-		gxp_ssmt_set_bypass(&mgr->ssmt);
+		gxp_ssmt_activate_scid(&mgr->ssmt, pasid);
 	}
 	return 0;
 }
 
+static void gxp_dma_ssmt_deactivate(struct gxp_dev *gxp,
+				    struct iommu_domain *domain, uint core_list)
+{
+	struct gxp_dma_iommu_manager *mgr = container_of(
+		gxp->dma_mgr, struct gxp_dma_iommu_manager, dma_mgr);
+	uint core;
+	int pasid = iommu_aux_get_pasid(domain, gxp->dev);
+
+	/* Program VID only when cores are managed by us. */
+	if (gxp_is_direct_mode(gxp) || gxp_core_boot(gxp)) {
+		for (core = 0; core < GXP_NUM_CORES; core++) {
+			if (BIT(core) & core_list)
+				gxp_ssmt_set_core_vid(&mgr->ssmt, core, 0);
+		}
+	} else {
+		gxp_ssmt_deactivate_scid(&mgr->ssmt, pasid);
+	}
+}
+
 /* Fault handler */
 
 static int sysmmu_fault_handler(struct iommu_fault *fault, void *token)
@@ -284,14 +302,15 @@
 	ret = iommu_aux_attach_device(gdomain->domain, gxp->dev);
 	if (ret)
 		goto out;
-	gxp_dma_ssmt_program(gxp, gdomain->domain, core_list);
+	gxp_dma_ssmt_activate(gxp, gdomain->domain, core_list);
 out:
 	return ret;
 }
 
-void gxp_dma_domain_detach_device(struct gxp_dev *gxp,
-				  struct gcip_iommu_domain *gdomain)
+void gxp_dma_domain_detach_device(struct gxp_dev *gxp, struct gcip_iommu_domain *gdomain,
+				  uint core_list)
 {
+	gxp_dma_ssmt_deactivate(gxp, gdomain->domain, core_list);
 	iommu_aux_detach_device(gdomain->domain, gxp->dev);
 }
 
diff --git a/gxp-dma.h b/gxp-dma.h
index a489ef1..c88405d 100644
--- a/gxp-dma.h
+++ b/gxp-dma.h
@@ -102,11 +102,12 @@
  * gxp_dma_domain_detach_device() - Detach the page table from the device.
  * @gxp: The GXP device to detach
  * @gdomain: The IOMMU domain to be detached
+ * @core_list: The physical cores to detach.
  *
  * Caller ensures a BLOCK wakelock is hold for the iommu detaching.
  */
-void gxp_dma_domain_detach_device(struct gxp_dev *gxp,
-				  struct gcip_iommu_domain *gdomain);
+void gxp_dma_domain_detach_device(struct gxp_dev *gxp, struct gcip_iommu_domain *gdomain,
+				  uint core_list);
 
 /**
  * gxp_dma_init_default_resources() - Set the various buffers/registers with
diff --git a/gxp-ssmt.c b/gxp-ssmt.c
index 403da5d..5b06c60 100644
--- a/gxp-ssmt.c
+++ b/gxp-ssmt.c
@@ -11,6 +11,11 @@
 #include "gxp-internal.h"
 #include "gxp-ssmt.h"
 
+static inline bool ssmt_is_client_driven(struct gxp_ssmt *ssmt)
+{
+	return readl(ssmt->idma_ssmt_base + SSMT_CFG_OFFSET) == SSMT_MODE_CLIENT;
+}
+
 static inline void ssmt_set_vid_for_idx(void __iomem *ssmt, uint vid, uint idx)
 {
 	/* NS_READ_STREAM_VID_<sid> */
@@ -74,20 +79,38 @@
 	}
 }
 
-void gxp_ssmt_set_bypass(struct gxp_ssmt *ssmt)
+/*
+ * Programs SSMT to always use SCIDs as VIDs.
+ * Assumes clamp mode.
+ */
+static void gxp_ssmt_set_bypass(struct gxp_ssmt *ssmt)
 {
-	u32 mode;
-	uint core, i;
+	uint core;
 
-	mode = readl(ssmt->idma_ssmt_base + SSMT_CFG_OFFSET);
-	if (mode == SSMT_MODE_CLIENT) {
-		for (i = 0; i < MAX_NUM_CONTEXTS; i++) {
-			ssmt_set_vid_for_idx(ssmt->idma_ssmt_base, i, i);
-			ssmt_set_vid_for_idx(ssmt->inst_data_ssmt_base, i, i);
-		}
+	for (core = 0; core < GXP_NUM_CORES; core++)
+		gxp_ssmt_set_core_vid(ssmt, core, SSMT_CLAMP_MODE_BYPASS);
+}
+
+void gxp_ssmt_activate_scid(struct gxp_ssmt *ssmt, uint scid)
+{
+	if (ssmt_is_client_driven(ssmt)) {
+		ssmt_set_vid_for_idx(ssmt->idma_ssmt_base, scid, scid);
+		ssmt_set_vid_for_idx(ssmt->inst_data_ssmt_base, scid, scid);
 	} else {
-		for (core = 0; core < GXP_NUM_CORES; core++)
-			gxp_ssmt_set_core_vid(ssmt, core,
-					      SSMT_CLAMP_MODE_BYPASS);
+		/*
+		 * In clamp mode, we can't configure specific SCID. We can only mark all
+		 * transactions as "bypassed" which have all streams to use their SCID as VID.
+		 */
+		gxp_ssmt_set_bypass(ssmt);
+	}
+}
+
+void gxp_ssmt_deactivate_scid(struct gxp_ssmt *ssmt, uint scid)
+{
+	if (ssmt_is_client_driven(ssmt)) {
+		ssmt_set_vid_for_idx(ssmt->idma_ssmt_base, scid, 0);
+		ssmt_set_vid_for_idx(ssmt->inst_data_ssmt_base, scid, 0);
+	} else {
+		dev_warn_once(ssmt->gxp->dev, "Unable to deactivate context on clamp mode");
 	}
 }
diff --git a/gxp-ssmt.h b/gxp-ssmt.h
index b35829d..e68897d 100644
--- a/gxp-ssmt.h
+++ b/gxp-ssmt.h
@@ -38,10 +38,19 @@
  */
 void gxp_ssmt_set_core_vid(struct gxp_ssmt *ssmt, uint core, uint vid);
 
-/*
- * Programs SSMT to always use SCIDs as VIDs.
- * Supports both client-driven and clamp mode.
+/**
+ * gxp_ssmt_activate_scid() - Activates the transactions with SCID @scid.
+ *
+ * SSMT will be configured as streams with SCID=@scid to have VID=@scid for memory transactions.
  */
-void gxp_ssmt_set_bypass(struct gxp_ssmt *ssmt);
+void gxp_ssmt_activate_scid(struct gxp_ssmt *ssmt, uint scid);
+
+/**
+ * gxp_ssmt_deactivate_scid() - Deactivates the transactions with SCID @scid.
+ *
+ * SSMT will be configured as streams with SCID=@scid to have VID=0 signal for memory
+ * transactions.
+ */
+void gxp_ssmt_deactivate_scid(struct gxp_ssmt *ssmt, uint scid);
 
 #endif /* __GXP_SSMT_H__ */
diff --git a/gxp-vd.c b/gxp-vd.c
index 5c0fb86..b50a852 100644
--- a/gxp-vd.c
+++ b/gxp-vd.c
@@ -787,7 +787,7 @@
 	if (gxp->after_vd_block_ready) {
 		ret = gxp->after_vd_block_ready(gxp, vd);
 		if (ret) {
-			gxp_dma_domain_detach_device(gxp, vd->domain);
+			gxp_dma_domain_detach_device(gxp, vd->domain, vd->core_list);
 			vd->state = orig_state;
 			return ret;
 		}
@@ -816,7 +816,7 @@
 		gxp->before_vd_block_unready(gxp, vd);
 	if (vd->state == GXP_VD_READY)
 		vd->state = GXP_VD_OFF;
-	gxp_dma_domain_detach_device(gxp, vd->domain);
+	gxp_dma_domain_detach_device(gxp, vd->domain, vd->core_list);
 
 	if (vd->is_secure)
 		gxp_pm_idle(gxp);