LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/amdgpu - amdgpu_psp_ta.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 2 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 1 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2022 Advanced Micro Devices, Inc.
       3             :  *
       4             :  * Permission is hereby granted, free of charge, to any person obtaining a
       5             :  * copy of this software and associated documentation files (the "Software"),
       6             :  * to deal in the Software without restriction, including without limitation
       7             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8             :  * and/or sell copies of the Software, and to permit persons to whom the
       9             :  * Software is furnished to do so, subject to the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice shall be included in
      12             :  * all copies or substantial portions of the Software.
      13             :  *
      14             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      17             :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      18             :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      19             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      20             :  * OTHER DEALINGS IN THE SOFTWARE.
      21             :  *
      22             :  */
      23             : 
      24             : #include "amdgpu.h"
      25             : #include "amdgpu_psp_ta.h"
      26             : 
      27             : #if defined(CONFIG_DEBUG_FS)
      28             : 
      29             : static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf,
      30             :                                             size_t len, loff_t *off);
      31             : static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf,
      32             :                                             size_t len, loff_t *off);
      33             : static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf,
      34             :                                             size_t len, loff_t *off);
      35             : 
      36             : static uint32_t get_bin_version(const uint8_t *bin)
      37             : {
      38             :         const struct common_firmware_header *hdr =
      39             :                              (const struct common_firmware_header *)bin;
      40             : 
      41             :         return hdr->ucode_version;
      42             : }
      43             : 
      44             : static void prep_ta_mem_context(struct psp_context *psp,
      45             :                                              struct ta_context *context,
      46             :                                              uint8_t *shared_buf,
      47             :                                              uint32_t shared_buf_len)
      48             : {
      49             :         context->mem_context.shared_mem_size = PAGE_ALIGN(shared_buf_len);
      50             :         psp_ta_init_shared_buf(psp, &context->mem_context);
      51             : 
      52             :         memcpy((void *)context->mem_context.shared_buf, shared_buf, shared_buf_len);
      53             : }
      54             : 
      55             : static bool is_ta_type_valid(enum ta_type_id ta_type)
      56             : {
      57             :         bool ret = false;
      58             : 
      59             :         switch (ta_type) {
      60             :         case TA_TYPE_RAS:
      61             :                 ret = true;
      62             :                 break;
      63             :         default:
      64             :                 break;
      65             :         }
      66             : 
      67             :         return ret;
      68             : }
      69             : 
      70             : static const struct file_operations ta_load_debugfs_fops = {
      71             :         .write  = ta_if_load_debugfs_write,
      72             :         .llseek = default_llseek,
      73             :         .owner  = THIS_MODULE
      74             : };
      75             : 
      76             : static const struct file_operations ta_unload_debugfs_fops = {
      77             :         .write  = ta_if_unload_debugfs_write,
      78             :         .llseek = default_llseek,
      79             :         .owner  = THIS_MODULE
      80             : };
      81             : 
      82             : static const struct file_operations ta_invoke_debugfs_fops = {
      83             :         .write  = ta_if_invoke_debugfs_write,
      84             :         .llseek = default_llseek,
      85             :         .owner  = THIS_MODULE
      86             : };
      87             : 
      88             : 
      89             : /**
      90             :  * DOC: AMDGPU TA debugfs interfaces
      91             :  *
      92             :  * Three debugfs interfaces can be opened by a program to
      93             :  * load/invoke/unload TA,
      94             :  *
      95             :  * - /sys/kernel/debug/dri/<N>/ta_if/ta_load
      96             :  * - /sys/kernel/debug/dri/<N>/ta_if/ta_invoke
      97             :  * - /sys/kernel/debug/dri/<N>/ta_if/ta_unload
      98             :  *
      99             :  * How to use the interfaces in a program?
     100             :  *
     101             :  * A program needs to provide transmit buffer to the interfaces
     102             :  * and will receive buffer from the interfaces below,
     103             :  *
     104             :  * - For TA load debugfs interface:
     105             :  *   Transmit buffer:
     106             :  *    - TA type (4bytes)
     107             :  *    - TA bin length (4bytes)
     108             :  *    - TA bin
     109             :  *   Receive buffer:
     110             :  *    - TA ID (4bytes)
     111             :  *
     112             :  * - For TA invoke debugfs interface:
     113             :  *   Transmit buffer:
     114             :  *    - TA ID (4bytes)
     115             :  *    - TA CMD ID (4bytes)
     116             :  *    - TA shard buf length (4bytes)
     117             :  *    - TA shared buf
     118             :  *   Receive buffer:
     119             :  *    - TA shared buf
     120             :  *
     121             :  * - For TA unload debugfs interface:
     122             :  *   Transmit buffer:
     123             :  *    - TA ID (4bytes)
     124             :  */
     125             : 
     126             : static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
     127             : {
     128             :         uint32_t ta_type    = 0;
     129             :         uint32_t ta_bin_len = 0;
     130             :         uint8_t  *ta_bin    = NULL;
     131             :         uint32_t copy_pos   = 0;
     132             :         int      ret        = 0;
     133             : 
     134             :         struct amdgpu_device *adev   = (struct amdgpu_device *)file_inode(fp)->i_private;
     135             :         struct psp_context   *psp    = &adev->psp;
     136             :         struct ta_context    context = {0};
     137             : 
     138             :         if (!buf)
     139             :                 return -EINVAL;
     140             : 
     141             :         ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t));
     142             :         if (ret || (!is_ta_type_valid(ta_type)))
     143             :                 return -EINVAL;
     144             : 
     145             :         copy_pos += sizeof(uint32_t);
     146             : 
     147             :         ret = copy_from_user((void *)&ta_bin_len, &buf[copy_pos], sizeof(uint32_t));
     148             :         if (ret)
     149             :                 return -EINVAL;
     150             : 
     151             :         copy_pos += sizeof(uint32_t);
     152             : 
     153             :         ta_bin = kzalloc(ta_bin_len, GFP_KERNEL);
     154             :         if (!ta_bin)
     155             :                 ret = -ENOMEM;
     156             :         if (copy_from_user((void *)ta_bin, &buf[copy_pos], ta_bin_len)) {
     157             :                 ret = -EFAULT;
     158             :                 goto err_free_bin;
     159             :         }
     160             : 
     161             :         ret = psp_ras_terminate(psp);
     162             :         if (ret) {
     163             :                 dev_err(adev->dev, "Failed to unload embedded RAS TA\n");
     164             :                 goto err_free_bin;
     165             :         }
     166             : 
     167             :         context.ta_type             = ta_type;
     168             :         context.ta_load_type        = GFX_CMD_ID_LOAD_TA;
     169             :         context.bin_desc.fw_version = get_bin_version(ta_bin);
     170             :         context.bin_desc.size_bytes = ta_bin_len;
     171             :         context.bin_desc.start_addr = ta_bin;
     172             : 
     173             :         ret = psp_ta_load(psp, &context);
     174             : 
     175             :         if (ret || context.resp_status) {
     176             :                 dev_err(adev->dev, "TA load via debugfs failed (%d) status %d\n",
     177             :                          ret, context.resp_status);
     178             :                 if (!ret)
     179             :                         ret = -EINVAL;
     180             :                 goto err_free_bin;
     181             :         }
     182             : 
     183             :         context.initialized = true;
     184             :         if (copy_to_user((char *)buf, (void *)&context.session_id, sizeof(uint32_t)))
     185             :                 ret = -EFAULT;
     186             : 
     187             : err_free_bin:
     188             :         kfree(ta_bin);
     189             : 
     190             :         return ret;
     191             : }
     192             : 
     193             : static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
     194             : {
     195             :         uint32_t ta_id  = 0;
     196             :         int      ret    = 0;
     197             : 
     198             :         struct amdgpu_device *adev   = (struct amdgpu_device *)file_inode(fp)->i_private;
     199             :         struct psp_context   *psp    = &adev->psp;
     200             :         struct ta_context    context = {0};
     201             : 
     202             :         if (!buf)
     203             :                 return -EINVAL;
     204             : 
     205             :         ret = copy_from_user((void *)&ta_id, buf, sizeof(uint32_t));
     206             :         if (ret)
     207             :                 return -EINVAL;
     208             : 
     209             :         context.session_id = ta_id;
     210             : 
     211             :         ret = psp_ta_unload(psp, &context);
     212             :         if (!ret)
     213             :                 context.initialized = false;
     214             : 
     215             :         return ret;
     216             : }
     217             : 
     218             : static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
     219             : {
     220             :         uint32_t ta_id          = 0;
     221             :         uint32_t cmd_id         = 0;
     222             :         uint32_t shared_buf_len = 0;
     223             :         uint8_t  *shared_buf    = NULL;
     224             :         uint32_t copy_pos       = 0;
     225             :         int      ret            = 0;
     226             : 
     227             :         struct amdgpu_device *adev   = (struct amdgpu_device *)file_inode(fp)->i_private;
     228             :         struct psp_context   *psp    = &adev->psp;
     229             :         struct ta_context    context = {0};
     230             : 
     231             :         if (!buf)
     232             :                 return -EINVAL;
     233             : 
     234             :         ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t));
     235             :         if (ret)
     236             :                 return -EINVAL;
     237             :         copy_pos += sizeof(uint32_t);
     238             : 
     239             :         ret = copy_from_user((void *)&cmd_id, &buf[copy_pos], sizeof(uint32_t));
     240             :         if (ret)
     241             :                 return -EINVAL;
     242             :         copy_pos += sizeof(uint32_t);
     243             : 
     244             :         ret = copy_from_user((void *)&shared_buf_len, &buf[copy_pos], sizeof(uint32_t));
     245             :         if (ret)
     246             :                 return -EINVAL;
     247             :         copy_pos += sizeof(uint32_t);
     248             : 
     249             :         shared_buf = kzalloc(shared_buf_len, GFP_KERNEL);
     250             :         if (!shared_buf)
     251             :                 return -ENOMEM;
     252             :         if (copy_from_user((void *)shared_buf, &buf[copy_pos], shared_buf_len)) {
     253             :                 ret = -EFAULT;
     254             :                 goto err_free_shared_buf;
     255             :         }
     256             : 
     257             :         context.session_id = ta_id;
     258             : 
     259             :         prep_ta_mem_context(psp, &context, shared_buf, shared_buf_len);
     260             : 
     261             :         ret = psp_ta_invoke_indirect(psp, cmd_id, &context);
     262             : 
     263             :         if (ret || context.resp_status) {
     264             :                 dev_err(adev->dev, "TA invoke via debugfs failed (%d) status %d\n",
     265             :                          ret, context.resp_status);
     266             :                 if (!ret)
     267             :                         ret = -EINVAL;
     268             :                 goto err_free_ta_shared_buf;
     269             :         }
     270             : 
     271             :         if (copy_to_user((char *)buf, context.mem_context.shared_buf, shared_buf_len))
     272             :                 ret = -EFAULT;
     273             : 
     274             : err_free_ta_shared_buf:
     275             :         psp_ta_free_shared_buf(&context.mem_context);
     276             : 
     277             : err_free_shared_buf:
     278             :         kfree(shared_buf);
     279             : 
     280             :         return ret;
     281             : }
     282             : 
     283             : void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev)
     284             : {
     285             :         struct drm_minor *minor = adev_to_drm(adev)->primary;
     286             : 
     287             :         struct dentry *dir = debugfs_create_dir("ta_if", minor->debugfs_root);
     288             : 
     289             :         debugfs_create_file("ta_load", 0200, dir, adev,
     290             :                                      &ta_load_debugfs_fops);
     291             : 
     292             :         debugfs_create_file("ta_unload", 0200, dir,
     293             :                                      adev, &ta_unload_debugfs_fops);
     294             : 
     295             :         debugfs_create_file("ta_invoke", 0200, dir,
     296             :                                      adev, &ta_invoke_debugfs_fops);
     297             : }
     298             : 
     299             : #else
     300           0 : void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev)
     301             : {
     302             : 
     303           0 : }
     304             : #endif

Generated by: LCOV version 1.14