Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2022 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  */
0023 
0024 #include "amdgpu.h"
0025 #include "amdgpu_psp_ta.h"
0026 
0027 #if defined(CONFIG_DEBUG_FS)
0028 
0029 static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf,
0030                         size_t len, loff_t *off);
0031 static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf,
0032                         size_t len, loff_t *off);
0033 static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf,
0034                         size_t len, loff_t *off);
0035 
0036 static uint32_t get_bin_version(const uint8_t *bin)
0037 {
0038     const struct common_firmware_header *hdr =
0039                  (const struct common_firmware_header *)bin;
0040 
0041     return hdr->ucode_version;
0042 }
0043 
0044 static void prep_ta_mem_context(struct psp_context *psp,
0045                          struct ta_context *context,
0046                          uint8_t *shared_buf,
0047                          uint32_t shared_buf_len)
0048 {
0049     context->mem_context.shared_mem_size = PAGE_ALIGN(shared_buf_len);
0050     psp_ta_init_shared_buf(psp, &context->mem_context);
0051 
0052     memcpy((void *)context->mem_context.shared_buf, shared_buf, shared_buf_len);
0053 }
0054 
0055 static bool is_ta_type_valid(enum ta_type_id ta_type)
0056 {
0057     bool ret = false;
0058 
0059     switch (ta_type) {
0060     case TA_TYPE_RAS:
0061         ret = true;
0062         break;
0063     default:
0064         break;
0065     }
0066 
0067     return ret;
0068 }
0069 
0070 static const struct file_operations ta_load_debugfs_fops = {
0071     .write  = ta_if_load_debugfs_write,
0072     .llseek = default_llseek,
0073     .owner  = THIS_MODULE
0074 };
0075 
0076 static const struct file_operations ta_unload_debugfs_fops = {
0077     .write  = ta_if_unload_debugfs_write,
0078     .llseek = default_llseek,
0079     .owner  = THIS_MODULE
0080 };
0081 
0082 static const struct file_operations ta_invoke_debugfs_fops = {
0083     .write  = ta_if_invoke_debugfs_write,
0084     .llseek = default_llseek,
0085     .owner  = THIS_MODULE
0086 };
0087 
0088 
0089 /**
0090  * DOC: AMDGPU TA debugfs interfaces
0091  *
0092  * Three debugfs interfaces can be opened by a program to
0093  * load/invoke/unload TA,
0094  *
0095  * - /sys/kernel/debug/dri/<N>/ta_if/ta_load
0096  * - /sys/kernel/debug/dri/<N>/ta_if/ta_invoke
0097  * - /sys/kernel/debug/dri/<N>/ta_if/ta_unload
0098  *
0099  * How to use the interfaces in a program?
0100  *
0101  * A program needs to provide transmit buffer to the interfaces
0102  * and will receive buffer from the interfaces below,
0103  *
0104  * - For TA load debugfs interface:
0105  *   Transmit buffer:
0106  *    - TA type (4bytes)
0107  *    - TA bin length (4bytes)
0108  *    - TA bin
0109  *   Receive buffer:
0110  *    - TA ID (4bytes)
0111  *
0112  * - For TA invoke debugfs interface:
0113  *   Transmit buffer:
0114  *    - TA ID (4bytes)
0115  *    - TA CMD ID (4bytes)
0116  *    - TA shard buf length (4bytes)
0117  *    - TA shared buf
0118  *   Receive buffer:
0119  *    - TA shared buf
0120  *
0121  * - For TA unload debugfs interface:
0122  *   Transmit buffer:
0123  *    - TA ID (4bytes)
0124  */
0125 
0126 static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
0127 {
0128     uint32_t ta_type    = 0;
0129     uint32_t ta_bin_len = 0;
0130     uint8_t  *ta_bin    = NULL;
0131     uint32_t copy_pos   = 0;
0132     int      ret        = 0;
0133 
0134     struct amdgpu_device *adev   = (struct amdgpu_device *)file_inode(fp)->i_private;
0135     struct psp_context   *psp    = &adev->psp;
0136     struct ta_context    context = {0};
0137 
0138     if (!buf)
0139         return -EINVAL;
0140 
0141     ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t));
0142     if (ret || (!is_ta_type_valid(ta_type)))
0143         return -EINVAL;
0144 
0145     copy_pos += sizeof(uint32_t);
0146 
0147     ret = copy_from_user((void *)&ta_bin_len, &buf[copy_pos], sizeof(uint32_t));
0148     if (ret)
0149         return -EINVAL;
0150 
0151     copy_pos += sizeof(uint32_t);
0152 
0153     ta_bin = kzalloc(ta_bin_len, GFP_KERNEL);
0154     if (!ta_bin)
0155         ret = -ENOMEM;
0156     if (copy_from_user((void *)ta_bin, &buf[copy_pos], ta_bin_len)) {
0157         ret = -EFAULT;
0158         goto err_free_bin;
0159     }
0160 
0161     ret = psp_ras_terminate(psp);
0162     if (ret) {
0163         dev_err(adev->dev, "Failed to unload embedded RAS TA\n");
0164         goto err_free_bin;
0165     }
0166 
0167     context.ta_type             = ta_type;
0168     context.ta_load_type        = GFX_CMD_ID_LOAD_TA;
0169     context.bin_desc.fw_version = get_bin_version(ta_bin);
0170     context.bin_desc.size_bytes = ta_bin_len;
0171     context.bin_desc.start_addr = ta_bin;
0172 
0173     ret = psp_ta_load(psp, &context);
0174 
0175     if (ret || context.resp_status) {
0176         dev_err(adev->dev, "TA load via debugfs failed (%d) status %d\n",
0177              ret, context.resp_status);
0178         if (!ret)
0179             ret = -EINVAL;
0180         goto err_free_bin;
0181     }
0182 
0183     context.initialized = true;
0184     if (copy_to_user((char *)buf, (void *)&context.session_id, sizeof(uint32_t)))
0185         ret = -EFAULT;
0186 
0187 err_free_bin:
0188     kfree(ta_bin);
0189 
0190     return ret;
0191 }
0192 
0193 static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
0194 {
0195     uint32_t ta_id  = 0;
0196     int      ret    = 0;
0197 
0198     struct amdgpu_device *adev   = (struct amdgpu_device *)file_inode(fp)->i_private;
0199     struct psp_context   *psp    = &adev->psp;
0200     struct ta_context    context = {0};
0201 
0202     if (!buf)
0203         return -EINVAL;
0204 
0205     ret = copy_from_user((void *)&ta_id, buf, sizeof(uint32_t));
0206     if (ret)
0207         return -EINVAL;
0208 
0209     context.session_id = ta_id;
0210 
0211     ret = psp_ta_unload(psp, &context);
0212     if (!ret)
0213         context.initialized = false;
0214 
0215     return ret;
0216 }
0217 
0218 static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
0219 {
0220     uint32_t ta_id          = 0;
0221     uint32_t cmd_id         = 0;
0222     uint32_t shared_buf_len = 0;
0223     uint8_t  *shared_buf    = NULL;
0224     uint32_t copy_pos       = 0;
0225     int      ret            = 0;
0226 
0227     struct amdgpu_device *adev   = (struct amdgpu_device *)file_inode(fp)->i_private;
0228     struct psp_context   *psp    = &adev->psp;
0229     struct ta_context    context = {0};
0230 
0231     if (!buf)
0232         return -EINVAL;
0233 
0234     ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t));
0235     if (ret)
0236         return -EINVAL;
0237     copy_pos += sizeof(uint32_t);
0238 
0239     ret = copy_from_user((void *)&cmd_id, &buf[copy_pos], sizeof(uint32_t));
0240     if (ret)
0241         return -EINVAL;
0242     copy_pos += sizeof(uint32_t);
0243 
0244     ret = copy_from_user((void *)&shared_buf_len, &buf[copy_pos], sizeof(uint32_t));
0245     if (ret)
0246         return -EINVAL;
0247     copy_pos += sizeof(uint32_t);
0248 
0249     shared_buf = kzalloc(shared_buf_len, GFP_KERNEL);
0250     if (!shared_buf)
0251         return -ENOMEM;
0252     if (copy_from_user((void *)shared_buf, &buf[copy_pos], shared_buf_len)) {
0253         ret = -EFAULT;
0254         goto err_free_shared_buf;
0255     }
0256 
0257     context.session_id = ta_id;
0258 
0259     prep_ta_mem_context(psp, &context, shared_buf, shared_buf_len);
0260 
0261     ret = psp_ta_invoke_indirect(psp, cmd_id, &context);
0262 
0263     if (ret || context.resp_status) {
0264         dev_err(adev->dev, "TA invoke via debugfs failed (%d) status %d\n",
0265              ret, context.resp_status);
0266         if (!ret)
0267             ret = -EINVAL;
0268         goto err_free_ta_shared_buf;
0269     }
0270 
0271     if (copy_to_user((char *)buf, context.mem_context.shared_buf, shared_buf_len))
0272         ret = -EFAULT;
0273 
0274 err_free_ta_shared_buf:
0275     psp_ta_free_shared_buf(&context.mem_context);
0276 
0277 err_free_shared_buf:
0278     kfree(shared_buf);
0279 
0280     return ret;
0281 }
0282 
0283 void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev)
0284 {
0285     struct drm_minor *minor = adev_to_drm(adev)->primary;
0286 
0287     struct dentry *dir = debugfs_create_dir("ta_if", minor->debugfs_root);
0288 
0289     debugfs_create_file("ta_load", 0200, dir, adev,
0290                      &ta_load_debugfs_fops);
0291 
0292     debugfs_create_file("ta_unload", 0200, dir,
0293                      adev, &ta_unload_debugfs_fops);
0294 
0295     debugfs_create_file("ta_invoke", 0200, dir,
0296                      adev, &ta_invoke_debugfs_fops);
0297 }
0298 
0299 #else
0300 void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev)
0301 {
0302 
0303 }
0304 #endif