Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: MIT
0002 /*
0003  * Copyright(c) 2020 Intel Corporation.
0004  */
0005 
0006 #include <linux/component.h>
0007 
0008 #include <drm/i915_pxp_tee_interface.h>
0009 #include <drm/i915_component.h>
0010 
0011 #include "i915_drv.h"
0012 #include "intel_pxp.h"
0013 #include "intel_pxp_session.h"
0014 #include "intel_pxp_tee.h"
0015 #include "intel_pxp_tee_interface.h"
0016 
0017 static inline struct intel_pxp *i915_dev_to_pxp(struct device *i915_kdev)
0018 {
0019     struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
0020 
0021     return &to_gt(i915)->pxp;
0022 }
0023 
0024 static int intel_pxp_tee_io_message(struct intel_pxp *pxp,
0025                     void *msg_in, u32 msg_in_size,
0026                     void *msg_out, u32 msg_out_max_size,
0027                     u32 *msg_out_rcv_size)
0028 {
0029     struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915;
0030     struct i915_pxp_component *pxp_component = pxp->pxp_component;
0031     int ret = 0;
0032 
0033     mutex_lock(&pxp->tee_mutex);
0034 
0035     /*
0036      * The binding of the component is asynchronous from i915 probe, so we
0037      * can't be sure it has happened.
0038      */
0039     if (!pxp_component) {
0040         ret = -ENODEV;
0041         goto unlock;
0042     }
0043 
0044     ret = pxp_component->ops->send(pxp_component->tee_dev, msg_in, msg_in_size);
0045     if (ret) {
0046         drm_err(&i915->drm, "Failed to send PXP TEE message\n");
0047         goto unlock;
0048     }
0049 
0050     ret = pxp_component->ops->recv(pxp_component->tee_dev, msg_out, msg_out_max_size);
0051     if (ret < 0) {
0052         drm_err(&i915->drm, "Failed to receive PXP TEE message\n");
0053         goto unlock;
0054     }
0055 
0056     if (ret > msg_out_max_size) {
0057         drm_err(&i915->drm,
0058             "Failed to receive PXP TEE message due to unexpected output size\n");
0059         ret = -ENOSPC;
0060         goto unlock;
0061     }
0062 
0063     if (msg_out_rcv_size)
0064         *msg_out_rcv_size = ret;
0065 
0066     ret = 0;
0067 unlock:
0068     mutex_unlock(&pxp->tee_mutex);
0069     return ret;
0070 }
0071 
0072 /**
0073  * i915_pxp_tee_component_bind - bind function to pass the function pointers to pxp_tee
0074  * @i915_kdev: pointer to i915 kernel device
0075  * @tee_kdev: pointer to tee kernel device
0076  * @data: pointer to pxp_tee_master containing the function pointers
0077  *
0078  * This bind function is called during the system boot or resume from system sleep.
0079  *
0080  * Return: return 0 if successful.
0081  */
0082 static int i915_pxp_tee_component_bind(struct device *i915_kdev,
0083                        struct device *tee_kdev, void *data)
0084 {
0085     struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
0086     struct intel_pxp *pxp = i915_dev_to_pxp(i915_kdev);
0087     intel_wakeref_t wakeref;
0088 
0089     mutex_lock(&pxp->tee_mutex);
0090     pxp->pxp_component = data;
0091     pxp->pxp_component->tee_dev = tee_kdev;
0092     mutex_unlock(&pxp->tee_mutex);
0093 
0094     /* if we are suspended, the HW will be re-initialized on resume */
0095     wakeref = intel_runtime_pm_get_if_in_use(&i915->runtime_pm);
0096     if (!wakeref)
0097         return 0;
0098 
0099     /* the component is required to fully start the PXP HW */
0100     intel_pxp_init_hw(pxp);
0101 
0102     intel_runtime_pm_put(&i915->runtime_pm, wakeref);
0103 
0104     return 0;
0105 }
0106 
0107 static void i915_pxp_tee_component_unbind(struct device *i915_kdev,
0108                       struct device *tee_kdev, void *data)
0109 {
0110     struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
0111     struct intel_pxp *pxp = i915_dev_to_pxp(i915_kdev);
0112     intel_wakeref_t wakeref;
0113 
0114     with_intel_runtime_pm_if_in_use(&i915->runtime_pm, wakeref)
0115         intel_pxp_fini_hw(pxp);
0116 
0117     mutex_lock(&pxp->tee_mutex);
0118     pxp->pxp_component = NULL;
0119     mutex_unlock(&pxp->tee_mutex);
0120 }
0121 
0122 static const struct component_ops i915_pxp_tee_component_ops = {
0123     .bind   = i915_pxp_tee_component_bind,
0124     .unbind = i915_pxp_tee_component_unbind,
0125 };
0126 
0127 int intel_pxp_tee_component_init(struct intel_pxp *pxp)
0128 {
0129     int ret;
0130     struct intel_gt *gt = pxp_to_gt(pxp);
0131     struct drm_i915_private *i915 = gt->i915;
0132 
0133     ret = component_add_typed(i915->drm.dev, &i915_pxp_tee_component_ops,
0134                   I915_COMPONENT_PXP);
0135     if (ret < 0) {
0136         drm_err(&i915->drm, "Failed to add PXP component (%d)\n", ret);
0137         return ret;
0138     }
0139 
0140     pxp->pxp_component_added = true;
0141 
0142     return 0;
0143 }
0144 
0145 void intel_pxp_tee_component_fini(struct intel_pxp *pxp)
0146 {
0147     struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915;
0148 
0149     if (!pxp->pxp_component_added)
0150         return;
0151 
0152     component_del(i915->drm.dev, &i915_pxp_tee_component_ops);
0153     pxp->pxp_component_added = false;
0154 }
0155 
0156 int intel_pxp_tee_cmd_create_arb_session(struct intel_pxp *pxp,
0157                      int arb_session_id)
0158 {
0159     struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915;
0160     struct pxp_tee_create_arb_in msg_in = {0};
0161     struct pxp_tee_create_arb_out msg_out = {0};
0162     int ret;
0163 
0164     msg_in.header.api_version = PXP_TEE_APIVER;
0165     msg_in.header.command_id = PXP_TEE_ARB_CMDID;
0166     msg_in.header.buffer_len = sizeof(msg_in) - sizeof(msg_in.header);
0167     msg_in.protection_mode = PXP_TEE_ARB_PROTECTION_MODE;
0168     msg_in.session_id = arb_session_id;
0169 
0170     ret = intel_pxp_tee_io_message(pxp,
0171                        &msg_in, sizeof(msg_in),
0172                        &msg_out, sizeof(msg_out),
0173                        NULL);
0174 
0175     if (ret)
0176         drm_err(&i915->drm, "Failed to send tee msg ret=[%d]\n", ret);
0177 
0178     return ret;
0179 }