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);