The HW will generate a teardown interrupt when session termination is required, which requires i915 to submit a terminating batch. Once the HW is done with the termination it will generate another interrupt, at which point it is safe to re-create the session. Since the termination and re-creation flow is something we want to trigger from the driver as well, use a common work function that can be called both from the irq handler and from the driver set-up flows, which has the addded benefit of allowing us to skip any extra locks because the work itself serializes the operations. v2: use struct completion instead of bool (Chris) v3: drop locks, clean up functions and improve comments (Chris), move to common work function. v4: improve comments, simplify wait logic (Rodrigo) v5: unconditionally set interrupts, rename state_attacked var (Rodrigo) v10: remove inclusion of intel_gt_types.h from intel_pxp.h (Jani)
Unified · Split
| @@ -282,6 +282,7 @@ i915-y += i915_perf.o · 281 unmodified lines | |||
| 282 | i915-$(CONFIG_DRM_I915_PXP) += \ | 282 | i915-$(CONFIG_DRM_I915_PXP) += \ |
| 283 | pxp/intel_pxp.o \ | 283 | pxp/intel_pxp.o \ |
| 284 | pxp/intel_pxp_cmd.o \ | 284 | pxp/intel_pxp_cmd.o \ |
| 285 | pxp/intel_pxp_irq.o \ | ||
| 285 | pxp/intel_pxp_session.o \ | 286 | pxp/intel_pxp_session.o \ |
| 286 | pxp/intel_pxp_tee.o | 287 | pxp/intel_pxp_tee.o |
| 287 | 288 | ||
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include "intel_lrc_reg.h" | 13 | #include "intel_lrc_reg.h" |
| 14 | #include "intel_uncore.h" | 14 | #include "intel_uncore.h" |
| 15 | #include "intel_rps.h" | 15 | #include "intel_rps.h" |
| 16 | #include "pxp/intel_pxp_irq.h" | ||
| 16 | 17 | ||
| 17 | static void guc_irq_handler(struct intel_guc *guc, u16 iir) | 18 | static void guc_irq_handler(struct intel_guc *guc, u16 iir) |
| 18 | { | 19 | { |
| @@ -64,6 +65,9 @@ gen11_other_irq_handler(struct intel_gt *gt, const u8 instance, · 45 unmodified lines | |||
| 64 | if (instance == OTHER_GTPM_INSTANCE) | 65 | if (instance == OTHER_GTPM_INSTANCE) |
| 65 | return gen11_rps_irq_handler(>->rps, iir); | 66 | return gen11_rps_irq_handler(>->rps, iir); |
| 66 | 67 | ||
| 68 | if (instance == OTHER_KCR_INSTANCE) | ||
| 69 | return intel_pxp_irq_handler(>->pxp, iir); | ||
| 70 | |||
| 67 | WARN_ONCE(1, "unhandled other interrupt instance=0x%x, iir=0x%x\n", | 71 | WARN_ONCE(1, "unhandled other interrupt instance=0x%x, iir=0x%x\n", |
| 68 | instance, iir); | 72 | instance, iir); |
| 69 | } | 73 | } |
| @@ -196,6 +200,9 @@ void gen11_gt_irq_reset(struct intel_gt *gt) · 126 unmodified lines | |||
| 196 | intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_MASK, ~0); | 200 | intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_MASK, ~0); |
| 197 | intel_uncore_write(uncore, GEN11_GUC_SG_INTR_ENABLE, 0); | 201 | intel_uncore_write(uncore, GEN11_GUC_SG_INTR_ENABLE, 0); |
| 198 | intel_uncore_write(uncore, GEN11_GUC_SG_INTR_MASK, ~0); | 202 | intel_uncore_write(uncore, GEN11_GUC_SG_INTR_MASK, ~0); |
| 203 | |||
| 204 | intel_uncore_write(uncore, GEN11_CRYPTO_RSVD_INTR_ENABLE, 0); | ||
| 205 | intel_uncore_write(uncore, GEN11_CRYPTO_RSVD_INTR_MASK, ~0); | ||
| 199 | } | 206 | } |
| 200 | 207 | ||
| 201 | void gen11_gt_irq_postinstall(struct intel_gt *gt) | 208 | void gen11_gt_irq_postinstall(struct intel_gt *gt) |
| @@ -8124,6 +8124,7 @@ enum { · 8123 unmodified lines | |||
| 8124 | /* irq instances for OTHER_CLASS */ | 8124 | /* irq instances for OTHER_CLASS */ |
| 8125 | #define OTHER_GUC_INSTANCE 0 | 8125 | #define OTHER_GUC_INSTANCE 0 |
| 8126 | #define OTHER_GTPM_INSTANCE 1 | 8126 | #define OTHER_GTPM_INSTANCE 1 |
| 8127 | #define OTHER_KCR_INSTANCE 4 | ||
| 8127 | 8128 | ||
| 8128 | #define GEN11_INTR_IDENTITY_REG(x) _MMIO(0x190060 + ((x) * 4)) | 8129 | #define GEN11_INTR_IDENTITY_REG(x) _MMIO(0x190060 + ((x) * 4)) |
| 8129 | 8130 | ||
| @@ -2,7 +2,9 @@ · 1 unmodified line | |||
| 2 | /* | 2 | /* |
| 3 | * Copyright(c) 2020 Intel Corporation. | 3 | * Copyright(c) 2020 Intel Corporation. |
| 4 | */ | 4 | */ |
| 5 | #include <linux/workqueue.h> | ||
| 5 | #include "intel_pxp.h" | 6 | #include "intel_pxp.h" |
| 7 | #include "intel_pxp_irq.h" | ||
| 6 | #include "intel_pxp_session.h" | 8 | #include "intel_pxp_session.h" |
| 7 | #include "intel_pxp_tee.h" | 9 | #include "intel_pxp_tee.h" |
| 8 | #include "gt/intel_context.h" | 10 | #include "gt/intel_context.h" |
| @@ -80,6 +82,16 @@ void intel_pxp_init(struct intel_pxp *pxp) · 71 unmodified lines | |||
| 80 | 82 | ||
| 81 | mutex_init(&pxp->tee_mutex); | 83 | mutex_init(&pxp->tee_mutex); |
| 82 | 84 | ||
| 85 | /* | ||
| 86 | * we'll use the completion to check if there is a termination pending, | ||
| 87 | * so we start it as completed and we reinit it when a termination | ||
| 88 | * is triggered. | ||
| 89 | */ | ||
| 90 | init_completion(&pxp->termination); | ||
| 91 | complete_all(&pxp->termination); | ||
| 92 | |||
| 93 | INIT_WORK(&pxp->session_work, intel_pxp_session_work); | ||
| 94 | |||
| 83 | ret = create_vcs_context(pxp); | 95 | ret = create_vcs_context(pxp); |
| 84 | if (ret) | 96 | if (ret) |
| 85 | return; | 97 | return; |
| @@ -108,19 +120,61 @@ void intel_pxp_fini(struct intel_pxp *pxp) · 22 unmodified lines | |||
| 108 | destroy_vcs_context(pxp); | 120 | destroy_vcs_context(pxp); |
| 109 | } | 121 | } |
| 110 | 122 | ||
| 111 | void intel_pxp_init_hw(struct intel_pxp *pxp) | 123 | void intel_pxp_mark_termination_in_progress(struct intel_pxp *pxp) |
| 112 | { | 124 | { |
| 113 | int ret; | 125 | pxp->arb_is_valid = false; |
| 126 | reinit_completion(&pxp->termination); | ||
| 127 | } | ||
| 128 | |||
| 129 | static void intel_pxp_queue_termination(struct intel_pxp *pxp) | ||
| 130 | { | ||
| 131 | struct intel_gt *gt = pxp_to_gt(pxp); | ||
| 132 | |||
| 133 | /* | ||
| 134 | * We want to get the same effect as if we received a termination | ||
| 135 | * interrupt, so just pretend that we did. | ||
| 136 | */ | ||
| 137 | spin_lock_irq(>->irq_lock); | ||
| 138 | intel_pxp_mark_termination_in_progress(pxp); | ||
| 139 | pxp->session_events |= PXP_TERMINATION_REQUEST; | ||
| 140 | queue_work(system_unbound_wq, &pxp->session_work); | ||
| 141 | spin_unlock_irq(>->irq_lock); | ||
| 142 | } | ||
| 114 | 143 | ||
| 144 | /* | ||
| 145 | * the arb session is restarted from the irq work when we receive the | ||
| 146 | * termination completion interrupt | ||
| 147 | */ | ||
| 148 | int intel_pxp_wait_for_arb_start(struct intel_pxp *pxp) | ||
| 149 | { | ||
| 150 | if (!intel_pxp_is_enabled(pxp)) | ||
| 151 | return 0; | ||
| 152 | |||
| 153 | if (!wait_for_completion_timeout(&pxp->termination, | ||
| 154 | msecs_to_jiffies(100))) | ||
| 155 | return -ETIMEDOUT; | ||
| 156 | |||
| 157 | if (!pxp->arb_is_valid) | ||
| 158 | return -EIO; | ||
| 159 | |||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | void intel_pxp_init_hw(struct intel_pxp *pxp) | ||
| 164 | { | ||
| 115 | kcr_pxp_enable(pxp_to_gt(pxp)); | 165 | kcr_pxp_enable(pxp_to_gt(pxp)); |
| 166 | intel_pxp_irq_enable(pxp); | ||
| 116 | 167 | ||
| 117 | /* always emit a full termination to clean the state */ | 168 | /* |
| 118 | ret = intel_pxp_terminate_arb_session_and_global(pxp); | 169 | * the session could've been attacked while we weren't loaded, so |
| 119 | if (!ret) | 170 | * handle it as if it was and re-create it. |
| 120 | intel_pxp_create_arb_session(pxp); | 171 | */ |
| 172 | intel_pxp_queue_termination(pxp); | ||
| 121 | } | 173 | } |
| 122 | 174 | ||
| 123 | void intel_pxp_fini_hw(struct intel_pxp *pxp) | 175 | void intel_pxp_fini_hw(struct intel_pxp *pxp) |
| 124 | { | 176 | { |
| 125 | kcr_pxp_disable(pxp_to_gt(pxp)); | 177 | kcr_pxp_disable(pxp_to_gt(pxp)); |
| 178 | |||
| 179 | intel_pxp_irq_disable(pxp); | ||
| 126 | } | 180 | } |
| @@ -22,6 +22,9 @@ void intel_pxp_fini(struct intel_pxp *pxp); · 21 unmodified lines | |||
| 22 | 22 | ||
| 23 | void intel_pxp_init_hw(struct intel_pxp *pxp); | 23 | void intel_pxp_init_hw(struct intel_pxp *pxp); |
| 24 | void intel_pxp_fini_hw(struct intel_pxp *pxp); | 24 | void intel_pxp_fini_hw(struct intel_pxp *pxp); |
| 25 | |||
| 26 | void intel_pxp_mark_termination_in_progress(struct intel_pxp *pxp); | ||
| 27 | int intel_pxp_wait_for_arb_start(struct intel_pxp *pxp); | ||
| 25 | #else | 28 | #else |
| 26 | static inline void intel_pxp_init(struct intel_pxp *pxp) | 29 | static inline void intel_pxp_init(struct intel_pxp *pxp) |
| 27 | { | 30 | { |
| @@ -30,6 +33,11 @@ static inline void intel_pxp_init(struct intel_pxp *pxp) · 2 unmodified lines | |||
| 30 | static inline void intel_pxp_fini(struct intel_pxp *pxp) | 33 | static inline void intel_pxp_fini(struct intel_pxp *pxp) |
| 31 | { | 34 | { |
| 32 | } | 35 | } |
| 36 | |||
| 37 | static inline int intel_pxp_wait_for_arb_start(struct intel_pxp *pxp) | ||
| 38 | { | ||
| 39 | return -ENODEV; | ||
| 40 | } | ||
| 33 | #endif | 41 | #endif |
| 34 | 42 | ||
| 35 | #endif /* __INTEL_PXP_H__ */ | 43 | #endif /* __INTEL_PXP_H__ */ |
| @@ -0,0 +1,100 @@ | |||
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | /* | ||
| 3 | * Copyright(c) 2020 Intel Corporation. | ||
| 4 | */ | ||
| 5 | #include <linux/workqueue.h> | ||
| 6 | #include "intel_pxp.h" | ||
| 7 | #include "intel_pxp_irq.h" | ||
| 8 | #include "intel_pxp_session.h" | ||
| 9 | #include "gt/intel_gt_irq.h" | ||
| 10 | #include "gt/intel_gt_types.h" | ||
| 11 | #include "i915_irq.h" | ||
| 12 | #include "i915_reg.h" | ||
| 13 | |||
| 14 | /** | ||
| 15 | * intel_pxp_irq_handler - Handles PXP interrupts. | ||
| 16 | * @pxp: pointer to pxp struct | ||
| 17 | * @iir: interrupt vector | ||
| 18 | */ | ||
| 19 | void intel_pxp_irq_handler(struct intel_pxp *pxp, u16 iir) | ||
| 20 | { | ||
| 21 | struct intel_gt *gt = pxp_to_gt(pxp); | ||
| 22 | |||
| 23 | if (GEM_WARN_ON(!intel_pxp_is_enabled(pxp))) | ||
| 24 | return; | ||
| 25 | |||
| 26 | lockdep_assert_held(>->irq_lock); | ||
| 27 | |||
| 28 | if (unlikely(!iir)) | ||
| 29 | return; | ||
| 30 | |||
| 31 | if (iir & (GEN12_DISPLAY_PXP_STATE_TERMINATED_INTERRUPT | | ||
| 32 | GEN12_DISPLAY_APP_TERMINATED_PER_FW_REQ_INTERRUPT)) { | ||
| 33 | /* immediately mark PXP as inactive on termination */ | ||
| 34 | intel_pxp_mark_termination_in_progress(pxp); | ||
| 35 | pxp->session_events |= PXP_TERMINATION_REQUEST; | ||
| 36 | } | ||
| 37 | |||
| 38 | if (iir & GEN12_DISPLAY_STATE_RESET_COMPLETE_INTERRUPT) | ||
| 39 | pxp->session_events |= PXP_TERMINATION_COMPLETE; | ||
| 40 | |||
| 41 | if (pxp->session_events) | ||
| 42 | queue_work(system_unbound_wq, &pxp->session_work); | ||
| 43 | } | ||
| 44 | |||
| 45 | static inline void __pxp_set_interrupts(struct intel_gt *gt, u32 interrupts) | ||
| 46 | { | ||
| 47 | struct intel_uncore *uncore = gt->uncore; | ||
| 48 | const u32 mask = interrupts << 16; | ||
| 49 | |||
| 50 | intel_uncore_write(uncore, GEN11_CRYPTO_RSVD_INTR_ENABLE, mask); | ||
| 51 | intel_uncore_write(uncore, GEN11_CRYPTO_RSVD_INTR_MASK, ~mask); | ||
| 52 | } | ||
| 53 | |||
| 54 | static inline void pxp_irq_reset(struct intel_gt *gt) | ||
| 55 | { | ||
| 56 | spin_lock_irq(>->irq_lock); | ||
| 57 | gen11_gt_reset_one_iir(gt, 0, GEN11_KCR); | ||
| 58 | spin_unlock_irq(>->irq_lock); | ||
| 59 | } | ||
| 60 | |||
| 61 | void intel_pxp_irq_enable(struct intel_pxp *pxp) | ||
| 62 | { | ||
| 63 | struct intel_gt *gt = pxp_to_gt(pxp); | ||
| 64 | |||
| 65 | spin_lock_irq(>->irq_lock); | ||
| 66 | |||
| 67 | if (!pxp->irq_enabled) | ||
| 68 | WARN_ON_ONCE(gen11_gt_reset_one_iir(gt, 0, GEN11_KCR)); | ||
| 69 | |||
| 70 | __pxp_set_interrupts(gt, GEN12_PXP_INTERRUPTS); | ||
| 71 | pxp->irq_enabled = true; | ||
| 72 | |||
| 73 | spin_unlock_irq(>->irq_lock); | ||
| 74 | } | ||
| 75 | |||
| 76 | void intel_pxp_irq_disable(struct intel_pxp *pxp) | ||
| 77 | { | ||
| 78 | struct intel_gt *gt = pxp_to_gt(pxp); | ||
| 79 | |||
| 80 | /* | ||
| 81 | * We always need to submit a global termination when we re-enable the | ||
| 82 | * interrupts, so there is no need to make sure that the session state | ||
| 83 | * makes sense at the end of this function. Just make sure this is not | ||
| 84 | * called in a path were the driver consider the session as valid and | ||
| 85 | * doesn't call a termination on restart. | ||
| 86 | */ | ||
| 87 | GEM_WARN_ON(intel_pxp_is_active(pxp)); | ||
| 88 | |||
| 89 | spin_lock_irq(>->irq_lock); | ||
| 90 | |||
| 91 | pxp->irq_enabled = false; | ||
| 92 | __pxp_set_interrupts(gt, 0); | ||
| 93 | |||
| 94 | spin_unlock_irq(>->irq_lock); | ||
| 95 | intel_synchronize_irq(gt->i915); | ||
| 96 | |||
| 97 | pxp_irq_reset(gt); | ||
| 98 | |||
| 99 | flush_work(&pxp->session_work); | ||
| 100 | } | ||
| @@ -0,0 +1,32 @@ | |||
| 1 | /* SPDX-License-Identifier: MIT */ | ||
| 2 | /* | ||
| 3 | * Copyright(c) 2020, Intel Corporation. All rights reserved. | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef __INTEL_PXP_IRQ_H__ | ||
| 7 | #define __INTEL_PXP_IRQ_H__ | ||
| 8 | |||
| 9 | #include <linux/types.h> | ||
| 10 | |||
| 11 | struct intel_pxp; | ||
| 12 | |||
| 13 | #define GEN12_DISPLAY_PXP_STATE_TERMINATED_INTERRUPT BIT(1) | ||
| 14 | #define GEN12_DISPLAY_APP_TERMINATED_PER_FW_REQ_INTERRUPT BIT(2) | ||
| 15 | #define GEN12_DISPLAY_STATE_RESET_COMPLETE_INTERRUPT BIT(3) | ||
| 16 | |||
| 17 | #define GEN12_PXP_INTERRUPTS \ | ||
| 18 | (GEN12_DISPLAY_PXP_STATE_TERMINATED_INTERRUPT | \ | ||
| 19 | GEN12_DISPLAY_APP_TERMINATED_PER_FW_REQ_INTERRUPT | \ | ||
| 20 | GEN12_DISPLAY_STATE_RESET_COMPLETE_INTERRUPT) | ||
| 21 | |||
| 22 | #ifdef CONFIG_DRM_I915_PXP | ||
| 23 | void intel_pxp_irq_enable(struct intel_pxp *pxp); | ||
| 24 | void intel_pxp_irq_disable(struct intel_pxp *pxp); | ||
| 25 | void intel_pxp_irq_handler(struct intel_pxp *pxp, u16 iir); | ||
| 26 | #else | ||
| 27 | static inline void intel_pxp_irq_handler(struct intel_pxp *pxp, u16 iir) | ||
| 28 | { | ||
| 29 | } | ||
| 30 | #endif | ||
| 31 | |||
| 32 | #endif /* __INTEL_PXP_IRQ_H__ */ | ||
| @@ -48,7 +48,7 @@ static int pxp_wait_for_session_state(struct intel_pxp *pxp, u32 id, bool in_pla · 47 unmodified lines | |||
| 48 | return ret; | 48 | return ret; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | int intel_pxp_create_arb_session(struct intel_pxp *pxp) | 51 | static int pxp_create_arb_session(struct intel_pxp *pxp) |
| 52 | { | 52 | { |
| 53 | struct intel_gt *gt = pxp_to_gt(pxp); | 53 | struct intel_gt *gt = pxp_to_gt(pxp); |
| 54 | int ret; | 54 | int ret; |
| @@ -77,12 +77,13 @@ int intel_pxp_create_arb_session(struct intel_pxp *pxp) · 22 unmodified lines | |||
| 77 | return 0; | 77 | return 0; |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | int intel_pxp_terminate_arb_session_and_global(struct intel_pxp *pxp) | 80 | static int pxp_terminate_arb_session_and_global(struct intel_pxp *pxp) |
| 81 | { | 81 | { |
| 82 | int ret; | 82 | int ret; |
| 83 | struct intel_gt *gt = pxp_to_gt(pxp); | 83 | struct intel_gt *gt = pxp_to_gt(pxp); |
| 84 | 84 | ||
| 85 | pxp->arb_is_valid = false; | 85 | /* must mark termination in progress calling this function */ |
| 86 | GEM_WARN_ON(pxp->arb_is_valid); | ||
| 86 | 87 | ||
| 87 | /* terminate the hw sessions */ | 88 | /* terminate the hw sessions */ |
| 88 | ret = intel_pxp_terminate_session(pxp, ARB_SESSION); | 89 | ret = intel_pxp_terminate_session(pxp, ARB_SESSION); |
| @@ -101,3 +102,50 @@ int intel_pxp_terminate_arb_session_and_global(struct intel_pxp *pxp) · 12 unmodified lines | |||
| 101 | 102 | ||
| 102 | return ret; | 103 | return ret; |
| 103 | } | 104 | } |
| 105 | |||
| 106 | static void pxp_terminate(struct intel_pxp *pxp) | ||
| 107 | { | ||
| 108 | int ret; | ||
| 109 | |||
| 110 | pxp->hw_state_invalidated = true; | ||
| 111 | |||
| 112 | /* | ||
| 113 | * if we fail to submit the termination there is no point in waiting for | ||
| 114 | * it to complete. PXP will be marked as non-active until the next | ||
| 115 | * termination is issued. | ||
| 116 | */ | ||
| 117 | ret = pxp_terminate_arb_session_and_global(pxp); | ||
| 118 | if (ret) | ||
| 119 | complete_all(&pxp->termination); | ||
| 120 | } | ||
| 121 | |||
| 122 | static void pxp_terminate_complete(struct intel_pxp *pxp) | ||
| 123 | { | ||
| 124 | /* Re-create the arb session after teardown handle complete */ | ||
| 125 | if (fetch_and_zero(&pxp->hw_state_invalidated)) | ||
| 126 | pxp_create_arb_session(pxp); | ||
| 127 | |||
| 128 | complete_all(&pxp->termination); | ||
| 129 | } | ||
| 130 | |||
| 131 | void intel_pxp_session_work(struct work_struct *work) | ||
| 132 | { | ||
| 133 | struct intel_pxp *pxp = container_of(work, typeof(*pxp), session_work); | ||
| 134 | struct intel_gt *gt = pxp_to_gt(pxp); | ||
| 135 | u32 events = 0; | ||
| 136 | |||
| 137 | spin_lock_irq(>->irq_lock); | ||
| 138 | events = fetch_and_zero(&pxp->session_events); | ||
| 139 | spin_unlock_irq(>->irq_lock); | ||
| 140 | |||
| 141 | if (!events) | ||
| 142 | return; | ||
| 143 | |||
| 144 | if (events & PXP_TERMINATION_REQUEST) { | ||
| 145 | events &= ~PXP_TERMINATION_COMPLETE; | ||
| 146 | pxp_terminate(pxp); | ||
| 147 | } | ||
| 148 | |||
| 149 | if (events & PXP_TERMINATION_COMPLETE) | ||
| 150 | pxp_terminate_complete(pxp); | ||
| 151 | } | ||
| @@ -8,9 +8,8 @@ · 7 unmodified lines | |||
| 8 | 8 | ||
| 9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
| 10 | 10 | ||
| 11 | struct intel_pxp; | 11 | struct work_struct; |
| 12 | 12 | ||
| 13 | int intel_pxp_create_arb_session(struct intel_pxp *pxp); | 13 | void intel_pxp_session_work(struct work_struct *work); |
| 14 | int intel_pxp_terminate_arb_session_and_global(struct intel_pxp *pxp); | ||
| 15 | 14 | ||
| 16 | #endif /* __INTEL_PXP_SESSION_H__ */ | 15 | #endif /* __INTEL_PXP_SESSION_H__ */ |
| @@ -80,6 +80,7 @@ static int i915_pxp_tee_component_bind(struct device *i915_kdev, · 79 unmodified lines | |||
| 80 | { | 80 | { |
| 81 | struct drm_i915_private *i915 = kdev_to_i915(i915_kdev); | 81 | struct drm_i915_private *i915 = kdev_to_i915(i915_kdev); |
| 82 | struct intel_pxp *pxp = i915_dev_to_pxp(i915_kdev); | 82 | struct intel_pxp *pxp = i915_dev_to_pxp(i915_kdev); |
| 83 | int ret; | ||
| 83 | 84 | ||
| 84 | mutex_lock(&pxp->tee_mutex); | 85 | mutex_lock(&pxp->tee_mutex); |
| 85 | pxp->pxp_component = data; | 86 | pxp->pxp_component = data; |
| @@ -88,15 +89,14 @@ static int i915_pxp_tee_component_bind(struct device *i915_kdev, · 2 unmodified lines | |||
| 88 | 89 | ||
| 89 | /* the component is required to fully start the PXP HW */ | 90 | /* the component is required to fully start the PXP HW */ |
| 90 | intel_pxp_init_hw(pxp); | 91 | intel_pxp_init_hw(pxp); |
| 91 | 92 | ret = intel_pxp_wait_for_arb_start(pxp); | |
| 92 | if (!pxp->arb_is_valid) { | 93 | if (ret) { |
| 93 | drm_err(&i915->drm, "Failed to create arb session during bind\n"); | 94 | drm_err(&i915->drm, "Failed to create arb session during bind\n"); |
| 94 | intel_pxp_fini_hw(pxp); | 95 | intel_pxp_fini_hw(pxp); |
| 95 | pxp->pxp_component = NULL; | 96 | pxp->pxp_component = NULL; |
| 96 | return -EIO; | ||
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | return 0; | 99 | return ret; |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | static void i915_pxp_tee_component_unbind(struct device *i915_kdev, | 102 | static void i915_pxp_tee_component_unbind(struct device *i915_kdev, |
| @@ -6,8 +6,10 @@ · 5 unmodified lines | |||
| 6 | #ifndef __INTEL_PXP_TYPES_H__ | 6 | #ifndef __INTEL_PXP_TYPES_H__ |
| 7 | #define __INTEL_PXP_TYPES_H__ | 7 | #define __INTEL_PXP_TYPES_H__ |
| 8 | 8 | ||
| 9 | #include <linux/completion.h> | ||
| 9 | #include <linux/mutex.h> | 10 | #include <linux/mutex.h> |
| 10 | #include <linux/types.h> | 11 | #include <linux/types.h> |
| 12 | #include <linux/workqueue.h> | ||
| 11 | 13 | ||
| 12 | struct intel_context; | 14 | struct intel_context; |
| 13 | struct i915_pxp_component; | 15 | struct i915_pxp_component; |
| @@ -26,6 +28,22 @@ struct intel_pxp { · 12 unmodified lines | |||
| 26 | bool arb_is_valid; | 28 | bool arb_is_valid; |
| 27 | 29 | ||
| 28 | struct mutex tee_mutex; /* protects the tee channel binding */ | 30 | struct mutex tee_mutex; /* protects the tee channel binding */ |
| 31 | |||
| 32 | /* | ||
| 33 | * If the HW perceives an attack on the integrity of the encryption it | ||
| 34 | * will invalidate the keys and expect SW to re-initialize the session. | ||
| 35 | * We keep track of this state to make sure we only re-start the arb | ||
| 36 | * session when required. | ||
| 37 | */ | ||
| 38 | bool hw_state_invalidated; | ||
| 39 | |||
| 40 | bool irq_enabled; | ||
| 41 | struct completion termination; | ||
| 42 | |||
| 43 | struct work_struct session_work; | ||
| 44 | u32 session_events; /* protected with gt->irq_lock */ | ||
| 45 | #define PXP_TERMINATION_REQUEST BIT(0) | ||
| 46 | #define PXP_TERMINATION_COMPLETE BIT(1) | ||
| 29 | }; | 47 | }; |
| 30 | 48 | ||
| 31 | #endif /* __INTEL_PXP_TYPES_H__ */ | 49 | #endif /* __INTEL_PXP_TYPES_H__ */ |