@@ -273,6 +273,7 @@ i915-$(CONFIG_DRM_I915_PXP) += \
pxp/intel_pxp.o \
pxp/intel_pxp_cmd.o \
pxp/intel_pxp_irq.o \
+ pxp/intel_pxp_pm.o \
pxp/intel_pxp_session.o \
pxp/intel_pxp_tee.o
@@ -19,6 +19,7 @@
#include "intel_rc6.h"
#include "intel_rps.h"
#include "intel_wakeref.h"
+#include "pxp/intel_pxp_pm.h"
static void user_forcewake(struct intel_gt *gt, bool suspend)
{
@@ -260,6 +261,8 @@ int intel_gt_resume(struct intel_gt *gt)
intel_uc_resume(>->uc);
+ intel_pxp_pm_resume(>->pxp);
+
user_forcewake(gt, false);
out_fw:
@@ -294,6 +297,7 @@ void intel_gt_suspend_prepare(struct intel_gt *gt)
user_forcewake(gt, true);
wait_for_suspend(gt);
+ intel_pxp_pm_prepare_suspend(>->pxp);
intel_uc_suspend(>->uc);
}
@@ -355,6 +359,8 @@ int intel_gt_runtime_resume(struct intel_gt *gt)
intel_gt_init_swizzling(gt);
intel_ggtt_restore_fences(gt->ggtt);
+ intel_pxp_runtime_resume(>->pxp);
+
return intel_uc_runtime_resume(>->uc);
}
@@ -70,6 +70,8 @@
#include "gt/intel_gt_pm.h"
#include "gt/intel_rc6.h"
+#include "pxp/intel_pxp_pm.h"
+
#include "i915_debugfs.h"
#include "i915_drm_client.h"
#include "i915_drv.h"
@@ -1364,6 +1366,8 @@ static int i915_drm_resume_early(struct drm_device *dev)
intel_power_domains_resume(dev_priv);
+ intel_pxp_pm_resume_early(&dev_priv->gt.pxp);
+
enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
return ret;
@@ -119,11 +119,13 @@ void intel_pxp_irq_enable(struct intel_pxp *pxp)
struct intel_gt *gt = pxp_to_gt(pxp);
spin_lock_irq(>->irq_lock);
- if (!pxp->irq_enabled) {
+
+ if (!pxp->irq_enabled)
WARN_ON_ONCE(gen11_gt_reset_one_iir(gt, 0, GEN11_KCR));
- __pxp_set_interrupts(gt, GEN12_PXP_INTERRUPTS);
- pxp->irq_enabled = true;
- }
+
+ __pxp_set_interrupts(gt, GEN12_PXP_INTERRUPTS);
+ pxp->irq_enabled = true;
+
spin_unlock_irq(>->irq_lock);
}
new file mode 100644
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright(c) 2020 Intel Corporation.
+ */
+
+#include "intel_pxp.h"
+#include "intel_pxp_irq.h"
+#include "intel_pxp_pm.h"
+#include "intel_pxp_session.h"
+
+void intel_pxp_pm_prepare_suspend(struct intel_pxp *pxp)
+{
+ if (!intel_pxp_is_enabled(pxp))
+ return;
+
+ mutex_lock(&pxp->mutex);
+
+ /* Mark PXP ops as disabled */
+ pxp->global_state_in_suspend = true;
+
+ mutex_unlock(&pxp->mutex);
+
+ intel_pxp_irq_disable(pxp);
+}
+
+void intel_pxp_pm_resume_early(struct intel_pxp *pxp)
+{
+ if (!intel_pxp_is_enabled(pxp))
+ return;
+
+ mutex_lock(&pxp->mutex);
+
+ /* reset the attacked flag even if there was a pending */
+ if (pxp->global_state_in_suspend)
+ pxp->global_state_attacked = false;
+
+ mutex_unlock(&pxp->mutex);
+}
+
+int intel_pxp_pm_resume(struct intel_pxp *pxp)
+{
+ int ret = 0;
+ struct intel_gt *gt = pxp_to_gt(pxp);
+
+ if (!intel_pxp_is_enabled(pxp))
+ return 0;
+
+ intel_pxp_irq_enable(pxp);
+
+ mutex_lock(&pxp->mutex);
+
+ /* Re-enable PXP ops */
+ if (pxp->global_state_in_suspend) {
+ /*
+ * Note: we won't re-create the session as part of the irq
+ * generated by this termination because
+ * pxp->global_state_attacked is not set. The session
+ * will be recreated as part of the mei component re-binding.
+ */
+ ret = intel_pxp_arb_terminate_session_with_global_terminate(pxp);
+ if (ret) {
+ drm_err(>->i915->drm,
+ "Failed to terminate the arb session on resume\n");
+ goto end;
+ }
+
+ pxp->global_state_in_suspend = false;
+ }
+
+end:
+ mutex_unlock(&pxp->mutex);
+
+ if (!ret) {
+ ret = wait_for(!pxp->termination_in_progress, 10);
+ if (ret) {
+ drm_err(>->i915->drm,
+ "Didn't recevive the PXP termination irq\n");
+ }
+ }
+
+ return ret;
+}
+
+void intel_pxp_runtime_resume(struct intel_pxp *pxp)
+{
+ if (!intel_pxp_is_enabled(pxp))
+ return;
+
+ /* interrupts are reset in the rpm resume path, so turn them back on */
+ intel_pxp_irq_enable(pxp);
+
+ return;
+}
+
new file mode 100644
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright(c) 2020, Intel Corporation. All rights reserved.
+ */
+
+#ifndef __INTEL_PXP_PM_H__
+#define __INTEL_PXP_PM_H__
+
+#include "i915_drv.h"
+
+#ifdef CONFIG_DRM_I915_PXP
+void intel_pxp_pm_prepare_suspend(struct intel_pxp *pxp);
+
+void intel_pxp_pm_resume_early(struct intel_pxp *pxp);
+int intel_pxp_pm_resume(struct intel_pxp *pxp);
+void intel_pxp_runtime_resume(struct intel_pxp *pxp);
+#else
+static inline void intel_pxp_pm_prepare_suspend(struct intel_pxp *pxp)
+{
+}
+
+static inline void intel_pxp_pm_resume_early(struct intel_pxp *pxp)
+{
+}
+
+static inline int intel_pxp_pm_resume(struct intel_pxp *pxp)
+{
+ return 0;
+}
+
+static inline void intel_pxp_runtime_resume(struct intel_pxp *pxp)
+{
+}
+#endif
+
+#endif /* __INTEL_PXP_PM_H__ */
@@ -19,6 +19,7 @@ struct intel_pxp {
bool arb_is_in_play;
bool termination_in_progress;
bool global_state_attacked;
+ bool global_state_in_suspend;
struct work_struct irq_work;
bool irq_enabled;