1e65e175bSOded Gabbay // SPDX-License-Identifier: GPL-2.0 2e65e175bSOded Gabbay 3e65e175bSOded Gabbay /* 4e65e175bSOded Gabbay * Copyright 2016-2022 HabanaLabs, Ltd. 5e65e175bSOded Gabbay * All Rights Reserved. 6e65e175bSOded Gabbay */ 7e65e175bSOded Gabbay 8e65e175bSOded Gabbay #define pr_fmt(fmt) "habanalabs: " fmt 9e65e175bSOded Gabbay 10e65e175bSOded Gabbay #include <uapi/drm/habanalabs_accel.h> 11e65e175bSOded Gabbay #include "habanalabs.h" 12e65e175bSOded Gabbay 13e65e175bSOded Gabbay #include <linux/fs.h> 14e65e175bSOded Gabbay #include <linux/kernel.h> 15e65e175bSOded Gabbay #include <linux/pci.h> 16e65e175bSOded Gabbay #include <linux/slab.h> 17e65e175bSOded Gabbay #include <linux/uaccess.h> 18e65e175bSOded Gabbay #include <linux/vmalloc.h> 19e65e175bSOded Gabbay 20e65e175bSOded Gabbay static u32 hl_debug_struct_size[HL_DEBUG_OP_TIMESTAMP + 1] = { 21e65e175bSOded Gabbay [HL_DEBUG_OP_ETR] = sizeof(struct hl_debug_params_etr), 22e65e175bSOded Gabbay [HL_DEBUG_OP_ETF] = sizeof(struct hl_debug_params_etf), 23e65e175bSOded Gabbay [HL_DEBUG_OP_STM] = sizeof(struct hl_debug_params_stm), 24e65e175bSOded Gabbay [HL_DEBUG_OP_FUNNEL] = 0, 25e65e175bSOded Gabbay [HL_DEBUG_OP_BMON] = sizeof(struct hl_debug_params_bmon), 26e65e175bSOded Gabbay [HL_DEBUG_OP_SPMU] = sizeof(struct hl_debug_params_spmu), 27e65e175bSOded Gabbay [HL_DEBUG_OP_TIMESTAMP] = 0 28e65e175bSOded Gabbay 29e65e175bSOded Gabbay }; 30e65e175bSOded Gabbay 31e65e175bSOded Gabbay static int device_status_info(struct hl_device *hdev, struct hl_info_args *args) 32e65e175bSOded Gabbay { 33e65e175bSOded Gabbay struct hl_info_device_status dev_stat = {0}; 34e65e175bSOded Gabbay u32 size = args->return_size; 35e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 36e65e175bSOded Gabbay 37e65e175bSOded Gabbay if ((!size) || (!out)) 38e65e175bSOded Gabbay return -EINVAL; 39e65e175bSOded Gabbay 40e65e175bSOded Gabbay dev_stat.status = hl_device_status(hdev); 41e65e175bSOded Gabbay 42e65e175bSOded Gabbay return copy_to_user(out, &dev_stat, 43e65e175bSOded Gabbay min((size_t)size, sizeof(dev_stat))) ? -EFAULT : 0; 44e65e175bSOded Gabbay } 45e65e175bSOded Gabbay 46e65e175bSOded Gabbay static int hw_ip_info(struct hl_device *hdev, struct hl_info_args *args) 47e65e175bSOded Gabbay { 48e65e175bSOded Gabbay struct hl_info_hw_ip_info hw_ip = {0}; 49e65e175bSOded Gabbay u32 size = args->return_size; 50e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 51e65e175bSOded Gabbay struct asic_fixed_properties *prop = &hdev->asic_prop; 52e65e175bSOded Gabbay u64 sram_kmd_size, dram_kmd_size, dram_available_size; 53e65e175bSOded Gabbay 54e65e175bSOded Gabbay if ((!size) || (!out)) 55e65e175bSOded Gabbay return -EINVAL; 56e65e175bSOded Gabbay 57e65e175bSOded Gabbay sram_kmd_size = (prop->sram_user_base_address - 58e65e175bSOded Gabbay prop->sram_base_address); 59e65e175bSOded Gabbay dram_kmd_size = (prop->dram_user_base_address - 60e65e175bSOded Gabbay prop->dram_base_address); 61e65e175bSOded Gabbay 62e65e175bSOded Gabbay hw_ip.device_id = hdev->asic_funcs->get_pci_id(hdev); 63e65e175bSOded Gabbay hw_ip.sram_base_address = prop->sram_user_base_address; 64e65e175bSOded Gabbay hw_ip.dram_base_address = 65e65e175bSOded Gabbay hdev->mmu_enable && prop->dram_supports_virtual_memory ? 66e65e175bSOded Gabbay prop->dmmu.start_addr : prop->dram_user_base_address; 67e65e175bSOded Gabbay hw_ip.tpc_enabled_mask = prop->tpc_enabled_mask & 0xFF; 68e65e175bSOded Gabbay hw_ip.tpc_enabled_mask_ext = prop->tpc_enabled_mask; 69e65e175bSOded Gabbay 70e65e175bSOded Gabbay hw_ip.sram_size = prop->sram_size - sram_kmd_size; 71e65e175bSOded Gabbay 72e65e175bSOded Gabbay dram_available_size = prop->dram_size - dram_kmd_size; 73e65e175bSOded Gabbay 74e65e175bSOded Gabbay if (hdev->mmu_enable == MMU_EN_ALL) 75e65e175bSOded Gabbay hw_ip.dram_size = DIV_ROUND_DOWN_ULL(dram_available_size, 76e65e175bSOded Gabbay prop->dram_page_size) * prop->dram_page_size; 77e65e175bSOded Gabbay else 78e65e175bSOded Gabbay hw_ip.dram_size = dram_available_size; 79e65e175bSOded Gabbay 80e65e175bSOded Gabbay if (hw_ip.dram_size > PAGE_SIZE) 81e65e175bSOded Gabbay hw_ip.dram_enabled = 1; 82e65e175bSOded Gabbay 83e65e175bSOded Gabbay hw_ip.dram_page_size = prop->dram_page_size; 84e65e175bSOded Gabbay hw_ip.device_mem_alloc_default_page_size = prop->device_mem_alloc_default_page_size; 85e65e175bSOded Gabbay hw_ip.num_of_events = prop->num_of_events; 86e65e175bSOded Gabbay 87e65e175bSOded Gabbay memcpy(hw_ip.cpucp_version, prop->cpucp_info.cpucp_version, 88e65e175bSOded Gabbay min(VERSION_MAX_LEN, HL_INFO_VERSION_MAX_LEN)); 89e65e175bSOded Gabbay 90e65e175bSOded Gabbay memcpy(hw_ip.card_name, prop->cpucp_info.card_name, 91e65e175bSOded Gabbay min(CARD_NAME_MAX_LEN, HL_INFO_CARD_NAME_MAX_LEN)); 92e65e175bSOded Gabbay 93e65e175bSOded Gabbay hw_ip.cpld_version = le32_to_cpu(prop->cpucp_info.cpld_version); 94e65e175bSOded Gabbay hw_ip.module_id = le32_to_cpu(prop->cpucp_info.card_location); 95e65e175bSOded Gabbay 96e65e175bSOded Gabbay hw_ip.psoc_pci_pll_nr = prop->psoc_pci_pll_nr; 97e65e175bSOded Gabbay hw_ip.psoc_pci_pll_nf = prop->psoc_pci_pll_nf; 98e65e175bSOded Gabbay hw_ip.psoc_pci_pll_od = prop->psoc_pci_pll_od; 99e65e175bSOded Gabbay hw_ip.psoc_pci_pll_div_factor = prop->psoc_pci_pll_div_factor; 100e65e175bSOded Gabbay 101e65e175bSOded Gabbay hw_ip.decoder_enabled_mask = prop->decoder_enabled_mask; 102e65e175bSOded Gabbay hw_ip.mme_master_slave_mode = prop->mme_master_slave_mode; 103e65e175bSOded Gabbay hw_ip.first_available_interrupt_id = prop->first_available_user_interrupt; 104e65e175bSOded Gabbay hw_ip.number_of_user_interrupts = prop->user_interrupt_count; 1054713ace3SOfir Bitton hw_ip.tpc_interrupt_id = prop->tpc_interrupt_id; 106e65e175bSOded Gabbay 107e65e175bSOded Gabbay hw_ip.edma_enabled_mask = prop->edma_enabled_mask; 108e65e175bSOded Gabbay hw_ip.server_type = prop->server_type; 109e65e175bSOded Gabbay hw_ip.security_enabled = prop->fw_security_enabled; 110e65e175bSOded Gabbay hw_ip.revision_id = hdev->pdev->revision; 111958e4797SOfir Bitton hw_ip.rotator_enabled_mask = prop->rotator_enabled_mask; 1127fc0d011SOfir Bitton hw_ip.engine_core_interrupt_reg_addr = prop->engine_core_interrupt_reg_addr; 11376e1ff37SOfir Bitton hw_ip.reserved_dram_size = dram_kmd_size; 114e65e175bSOded Gabbay 115e65e175bSOded Gabbay return copy_to_user(out, &hw_ip, 116e65e175bSOded Gabbay min((size_t) size, sizeof(hw_ip))) ? -EFAULT : 0; 117e65e175bSOded Gabbay } 118e65e175bSOded Gabbay 119e65e175bSOded Gabbay static int hw_events_info(struct hl_device *hdev, bool aggregate, 120e65e175bSOded Gabbay struct hl_info_args *args) 121e65e175bSOded Gabbay { 122e65e175bSOded Gabbay u32 size, max_size = args->return_size; 123e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 124e65e175bSOded Gabbay void *arr; 125e65e175bSOded Gabbay 126e65e175bSOded Gabbay if ((!max_size) || (!out)) 127e65e175bSOded Gabbay return -EINVAL; 128e65e175bSOded Gabbay 129e65e175bSOded Gabbay arr = hdev->asic_funcs->get_events_stat(hdev, aggregate, &size); 130e65e175bSOded Gabbay if (!arr) { 131e65e175bSOded Gabbay dev_err(hdev->dev, "Events info not supported\n"); 132e65e175bSOded Gabbay return -EOPNOTSUPP; 133e65e175bSOded Gabbay } 134e65e175bSOded Gabbay 135e65e175bSOded Gabbay return copy_to_user(out, arr, min(max_size, size)) ? -EFAULT : 0; 136e65e175bSOded Gabbay } 137e65e175bSOded Gabbay 138e65e175bSOded Gabbay static int events_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 139e65e175bSOded Gabbay { 140e65e175bSOded Gabbay u32 max_size = args->return_size; 141e65e175bSOded Gabbay u64 events_mask; 142e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 143e65e175bSOded Gabbay 144e65e175bSOded Gabbay if ((max_size < sizeof(u64)) || (!out)) 145e65e175bSOded Gabbay return -EINVAL; 146e65e175bSOded Gabbay 147e65e175bSOded Gabbay mutex_lock(&hpriv->notifier_event.lock); 148e65e175bSOded Gabbay events_mask = hpriv->notifier_event.events_mask; 149e65e175bSOded Gabbay hpriv->notifier_event.events_mask = 0; 150e65e175bSOded Gabbay mutex_unlock(&hpriv->notifier_event.lock); 151e65e175bSOded Gabbay 152e65e175bSOded Gabbay return copy_to_user(out, &events_mask, sizeof(u64)) ? -EFAULT : 0; 153e65e175bSOded Gabbay } 154e65e175bSOded Gabbay 155e65e175bSOded Gabbay static int dram_usage_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 156e65e175bSOded Gabbay { 157e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 158e65e175bSOded Gabbay struct hl_info_dram_usage dram_usage = {0}; 159e65e175bSOded Gabbay u32 max_size = args->return_size; 160e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 161e65e175bSOded Gabbay struct asic_fixed_properties *prop = &hdev->asic_prop; 162e65e175bSOded Gabbay u64 dram_kmd_size; 163e65e175bSOded Gabbay 164e65e175bSOded Gabbay if ((!max_size) || (!out)) 165e65e175bSOded Gabbay return -EINVAL; 166e65e175bSOded Gabbay 167e65e175bSOded Gabbay dram_kmd_size = (prop->dram_user_base_address - 168e65e175bSOded Gabbay prop->dram_base_address); 169e65e175bSOded Gabbay dram_usage.dram_free_mem = (prop->dram_size - dram_kmd_size) - 170e65e175bSOded Gabbay atomic64_read(&hdev->dram_used_mem); 171e65e175bSOded Gabbay if (hpriv->ctx) 172e65e175bSOded Gabbay dram_usage.ctx_dram_mem = 173e65e175bSOded Gabbay atomic64_read(&hpriv->ctx->dram_phys_mem); 174e65e175bSOded Gabbay 175e65e175bSOded Gabbay return copy_to_user(out, &dram_usage, 176e65e175bSOded Gabbay min((size_t) max_size, sizeof(dram_usage))) ? -EFAULT : 0; 177e65e175bSOded Gabbay } 178e65e175bSOded Gabbay 179e65e175bSOded Gabbay static int hw_idle(struct hl_device *hdev, struct hl_info_args *args) 180e65e175bSOded Gabbay { 181e65e175bSOded Gabbay struct hl_info_hw_idle hw_idle = {0}; 182e65e175bSOded Gabbay u32 max_size = args->return_size; 183e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 184e65e175bSOded Gabbay 185e65e175bSOded Gabbay if ((!max_size) || (!out)) 186e65e175bSOded Gabbay return -EINVAL; 187e65e175bSOded Gabbay 188e65e175bSOded Gabbay hw_idle.is_idle = hdev->asic_funcs->is_device_idle(hdev, 189e65e175bSOded Gabbay hw_idle.busy_engines_mask_ext, 190e65e175bSOded Gabbay HL_BUSY_ENGINES_MASK_EXT_SIZE, NULL); 191e65e175bSOded Gabbay hw_idle.busy_engines_mask = 192e65e175bSOded Gabbay lower_32_bits(hw_idle.busy_engines_mask_ext[0]); 193e65e175bSOded Gabbay 194e65e175bSOded Gabbay return copy_to_user(out, &hw_idle, 195e65e175bSOded Gabbay min((size_t) max_size, sizeof(hw_idle))) ? -EFAULT : 0; 196e65e175bSOded Gabbay } 197e65e175bSOded Gabbay 198e65e175bSOded Gabbay static int debug_coresight(struct hl_device *hdev, struct hl_ctx *ctx, struct hl_debug_args *args) 199e65e175bSOded Gabbay { 200e65e175bSOded Gabbay struct hl_debug_params *params; 201e65e175bSOded Gabbay void *input = NULL, *output = NULL; 202e65e175bSOded Gabbay int rc; 203e65e175bSOded Gabbay 204e65e175bSOded Gabbay params = kzalloc(sizeof(*params), GFP_KERNEL); 205e65e175bSOded Gabbay if (!params) 206e65e175bSOded Gabbay return -ENOMEM; 207e65e175bSOded Gabbay 208e65e175bSOded Gabbay params->reg_idx = args->reg_idx; 209e65e175bSOded Gabbay params->enable = args->enable; 210e65e175bSOded Gabbay params->op = args->op; 211e65e175bSOded Gabbay 212e65e175bSOded Gabbay if (args->input_ptr && args->input_size) { 213e65e175bSOded Gabbay input = kzalloc(hl_debug_struct_size[args->op], GFP_KERNEL); 214e65e175bSOded Gabbay if (!input) { 215e65e175bSOded Gabbay rc = -ENOMEM; 216e65e175bSOded Gabbay goto out; 217e65e175bSOded Gabbay } 218e65e175bSOded Gabbay 219e65e175bSOded Gabbay if (copy_from_user(input, u64_to_user_ptr(args->input_ptr), 220e65e175bSOded Gabbay args->input_size)) { 221e65e175bSOded Gabbay rc = -EFAULT; 222e65e175bSOded Gabbay dev_err(hdev->dev, "failed to copy input debug data\n"); 223e65e175bSOded Gabbay goto out; 224e65e175bSOded Gabbay } 225e65e175bSOded Gabbay 226e65e175bSOded Gabbay params->input = input; 227e65e175bSOded Gabbay } 228e65e175bSOded Gabbay 229e65e175bSOded Gabbay if (args->output_ptr && args->output_size) { 230e65e175bSOded Gabbay output = kzalloc(args->output_size, GFP_KERNEL); 231e65e175bSOded Gabbay if (!output) { 232e65e175bSOded Gabbay rc = -ENOMEM; 233e65e175bSOded Gabbay goto out; 234e65e175bSOded Gabbay } 235e65e175bSOded Gabbay 236e65e175bSOded Gabbay params->output = output; 237e65e175bSOded Gabbay params->output_size = args->output_size; 238e65e175bSOded Gabbay } 239e65e175bSOded Gabbay 240e65e175bSOded Gabbay rc = hdev->asic_funcs->debug_coresight(hdev, ctx, params); 241e65e175bSOded Gabbay if (rc) { 242e65e175bSOded Gabbay dev_err(hdev->dev, 243e65e175bSOded Gabbay "debug coresight operation failed %d\n", rc); 244e65e175bSOded Gabbay goto out; 245e65e175bSOded Gabbay } 246e65e175bSOded Gabbay 247e65e175bSOded Gabbay if (output && copy_to_user((void __user *) (uintptr_t) args->output_ptr, 248e65e175bSOded Gabbay output, args->output_size)) { 249e65e175bSOded Gabbay dev_err(hdev->dev, "copy to user failed in debug ioctl\n"); 250e65e175bSOded Gabbay rc = -EFAULT; 251e65e175bSOded Gabbay goto out; 252e65e175bSOded Gabbay } 253e65e175bSOded Gabbay 254e65e175bSOded Gabbay 255e65e175bSOded Gabbay out: 256e65e175bSOded Gabbay kfree(params); 257e65e175bSOded Gabbay kfree(output); 258e65e175bSOded Gabbay kfree(input); 259e65e175bSOded Gabbay 260e65e175bSOded Gabbay return rc; 261e65e175bSOded Gabbay } 262e65e175bSOded Gabbay 263e65e175bSOded Gabbay static int device_utilization(struct hl_device *hdev, struct hl_info_args *args) 264e65e175bSOded Gabbay { 265e65e175bSOded Gabbay struct hl_info_device_utilization device_util = {0}; 266e65e175bSOded Gabbay u32 max_size = args->return_size; 267e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 268e65e175bSOded Gabbay int rc; 269e65e175bSOded Gabbay 270e65e175bSOded Gabbay if ((!max_size) || (!out)) 271e65e175bSOded Gabbay return -EINVAL; 272e65e175bSOded Gabbay 273e65e175bSOded Gabbay rc = hl_device_utilization(hdev, &device_util.utilization); 274e65e175bSOded Gabbay if (rc) 275e65e175bSOded Gabbay return -EINVAL; 276e65e175bSOded Gabbay 277e65e175bSOded Gabbay return copy_to_user(out, &device_util, 278e65e175bSOded Gabbay min((size_t) max_size, sizeof(device_util))) ? -EFAULT : 0; 279e65e175bSOded Gabbay } 280e65e175bSOded Gabbay 281e65e175bSOded Gabbay static int get_clk_rate(struct hl_device *hdev, struct hl_info_args *args) 282e65e175bSOded Gabbay { 283e65e175bSOded Gabbay struct hl_info_clk_rate clk_rate = {0}; 284e65e175bSOded Gabbay u32 max_size = args->return_size; 285e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 286e65e175bSOded Gabbay int rc; 287e65e175bSOded Gabbay 288e65e175bSOded Gabbay if ((!max_size) || (!out)) 289e65e175bSOded Gabbay return -EINVAL; 290e65e175bSOded Gabbay 291e65e175bSOded Gabbay rc = hl_fw_get_clk_rate(hdev, &clk_rate.cur_clk_rate_mhz, &clk_rate.max_clk_rate_mhz); 292e65e175bSOded Gabbay if (rc) 293e65e175bSOded Gabbay return rc; 294e65e175bSOded Gabbay 295e65e175bSOded Gabbay return copy_to_user(out, &clk_rate, min_t(size_t, max_size, sizeof(clk_rate))) 296e65e175bSOded Gabbay ? -EFAULT : 0; 297e65e175bSOded Gabbay } 298e65e175bSOded Gabbay 299e65e175bSOded Gabbay static int get_reset_count(struct hl_device *hdev, struct hl_info_args *args) 300e65e175bSOded Gabbay { 301e65e175bSOded Gabbay struct hl_info_reset_count reset_count = {0}; 302e65e175bSOded Gabbay u32 max_size = args->return_size; 303e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 304e65e175bSOded Gabbay 305e65e175bSOded Gabbay if ((!max_size) || (!out)) 306e65e175bSOded Gabbay return -EINVAL; 307e65e175bSOded Gabbay 308e65e175bSOded Gabbay reset_count.hard_reset_cnt = hdev->reset_info.hard_reset_cnt; 309e65e175bSOded Gabbay reset_count.soft_reset_cnt = hdev->reset_info.compute_reset_cnt; 310e65e175bSOded Gabbay 311e65e175bSOded Gabbay return copy_to_user(out, &reset_count, 312e65e175bSOded Gabbay min((size_t) max_size, sizeof(reset_count))) ? -EFAULT : 0; 313e65e175bSOded Gabbay } 314e65e175bSOded Gabbay 315e65e175bSOded Gabbay static int time_sync_info(struct hl_device *hdev, struct hl_info_args *args) 316e65e175bSOded Gabbay { 317e65e175bSOded Gabbay struct hl_info_time_sync time_sync = {0}; 318e65e175bSOded Gabbay u32 max_size = args->return_size; 319e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 320e65e175bSOded Gabbay 321e65e175bSOded Gabbay if ((!max_size) || (!out)) 322e65e175bSOded Gabbay return -EINVAL; 323e65e175bSOded Gabbay 324e65e175bSOded Gabbay time_sync.device_time = hdev->asic_funcs->get_device_time(hdev); 325e65e175bSOded Gabbay time_sync.host_time = ktime_get_raw_ns(); 326e65e175bSOded Gabbay 327e65e175bSOded Gabbay return copy_to_user(out, &time_sync, 328e65e175bSOded Gabbay min((size_t) max_size, sizeof(time_sync))) ? -EFAULT : 0; 329e65e175bSOded Gabbay } 330e65e175bSOded Gabbay 331e65e175bSOded Gabbay static int pci_counters_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 332e65e175bSOded Gabbay { 333e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 334e65e175bSOded Gabbay struct hl_info_pci_counters pci_counters = {0}; 335e65e175bSOded Gabbay u32 max_size = args->return_size; 336e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 337e65e175bSOded Gabbay int rc; 338e65e175bSOded Gabbay 339e65e175bSOded Gabbay if ((!max_size) || (!out)) 340e65e175bSOded Gabbay return -EINVAL; 341e65e175bSOded Gabbay 342e65e175bSOded Gabbay rc = hl_fw_cpucp_pci_counters_get(hdev, &pci_counters); 343e65e175bSOded Gabbay if (rc) 344e65e175bSOded Gabbay return rc; 345e65e175bSOded Gabbay 346e65e175bSOded Gabbay return copy_to_user(out, &pci_counters, 347e65e175bSOded Gabbay min((size_t) max_size, sizeof(pci_counters))) ? -EFAULT : 0; 348e65e175bSOded Gabbay } 349e65e175bSOded Gabbay 350e65e175bSOded Gabbay static int clk_throttle_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 351e65e175bSOded Gabbay { 352e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 353e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 354e65e175bSOded Gabbay struct hl_info_clk_throttle clk_throttle = {0}; 355e65e175bSOded Gabbay ktime_t end_time, zero_time = ktime_set(0, 0); 356e65e175bSOded Gabbay u32 max_size = args->return_size; 357e65e175bSOded Gabbay int i; 358e65e175bSOded Gabbay 359e65e175bSOded Gabbay if ((!max_size) || (!out)) 360e65e175bSOded Gabbay return -EINVAL; 361e65e175bSOded Gabbay 362e65e175bSOded Gabbay mutex_lock(&hdev->clk_throttling.lock); 363e65e175bSOded Gabbay 364e65e175bSOded Gabbay clk_throttle.clk_throttling_reason = hdev->clk_throttling.current_reason; 365e65e175bSOded Gabbay 366e65e175bSOded Gabbay for (i = 0 ; i < HL_CLK_THROTTLE_TYPE_MAX ; i++) { 367e65e175bSOded Gabbay if (!(hdev->clk_throttling.aggregated_reason & BIT(i))) 368e65e175bSOded Gabbay continue; 369e65e175bSOded Gabbay 370e65e175bSOded Gabbay clk_throttle.clk_throttling_timestamp_us[i] = 371e65e175bSOded Gabbay ktime_to_us(hdev->clk_throttling.timestamp[i].start); 372e65e175bSOded Gabbay 373e65e175bSOded Gabbay if (ktime_compare(hdev->clk_throttling.timestamp[i].end, zero_time)) 374e65e175bSOded Gabbay end_time = hdev->clk_throttling.timestamp[i].end; 375e65e175bSOded Gabbay else 376e65e175bSOded Gabbay end_time = ktime_get(); 377e65e175bSOded Gabbay 378e65e175bSOded Gabbay clk_throttle.clk_throttling_duration_ns[i] = 379e65e175bSOded Gabbay ktime_to_ns(ktime_sub(end_time, 380e65e175bSOded Gabbay hdev->clk_throttling.timestamp[i].start)); 381e65e175bSOded Gabbay 382e65e175bSOded Gabbay } 383e65e175bSOded Gabbay mutex_unlock(&hdev->clk_throttling.lock); 384e65e175bSOded Gabbay 385e65e175bSOded Gabbay return copy_to_user(out, &clk_throttle, 386e65e175bSOded Gabbay min((size_t) max_size, sizeof(clk_throttle))) ? -EFAULT : 0; 387e65e175bSOded Gabbay } 388e65e175bSOded Gabbay 389e65e175bSOded Gabbay static int cs_counters_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 390e65e175bSOded Gabbay { 391e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 392e65e175bSOded Gabbay struct hl_info_cs_counters cs_counters = {0}; 393e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 394e65e175bSOded Gabbay struct hl_cs_counters_atomic *cntr; 395e65e175bSOded Gabbay u32 max_size = args->return_size; 396e65e175bSOded Gabbay 397e65e175bSOded Gabbay cntr = &hdev->aggregated_cs_counters; 398e65e175bSOded Gabbay 399e65e175bSOded Gabbay if ((!max_size) || (!out)) 400e65e175bSOded Gabbay return -EINVAL; 401e65e175bSOded Gabbay 402e65e175bSOded Gabbay cs_counters.total_out_of_mem_drop_cnt = 403e65e175bSOded Gabbay atomic64_read(&cntr->out_of_mem_drop_cnt); 404e65e175bSOded Gabbay cs_counters.total_parsing_drop_cnt = 405e65e175bSOded Gabbay atomic64_read(&cntr->parsing_drop_cnt); 406e65e175bSOded Gabbay cs_counters.total_queue_full_drop_cnt = 407e65e175bSOded Gabbay atomic64_read(&cntr->queue_full_drop_cnt); 408e65e175bSOded Gabbay cs_counters.total_device_in_reset_drop_cnt = 409e65e175bSOded Gabbay atomic64_read(&cntr->device_in_reset_drop_cnt); 410e65e175bSOded Gabbay cs_counters.total_max_cs_in_flight_drop_cnt = 411e65e175bSOded Gabbay atomic64_read(&cntr->max_cs_in_flight_drop_cnt); 412e65e175bSOded Gabbay cs_counters.total_validation_drop_cnt = 413e65e175bSOded Gabbay atomic64_read(&cntr->validation_drop_cnt); 414e65e175bSOded Gabbay 415e65e175bSOded Gabbay if (hpriv->ctx) { 416e65e175bSOded Gabbay cs_counters.ctx_out_of_mem_drop_cnt = 417e65e175bSOded Gabbay atomic64_read( 418e65e175bSOded Gabbay &hpriv->ctx->cs_counters.out_of_mem_drop_cnt); 419e65e175bSOded Gabbay cs_counters.ctx_parsing_drop_cnt = 420e65e175bSOded Gabbay atomic64_read( 421e65e175bSOded Gabbay &hpriv->ctx->cs_counters.parsing_drop_cnt); 422e65e175bSOded Gabbay cs_counters.ctx_queue_full_drop_cnt = 423e65e175bSOded Gabbay atomic64_read( 424e65e175bSOded Gabbay &hpriv->ctx->cs_counters.queue_full_drop_cnt); 425e65e175bSOded Gabbay cs_counters.ctx_device_in_reset_drop_cnt = 426e65e175bSOded Gabbay atomic64_read( 427e65e175bSOded Gabbay &hpriv->ctx->cs_counters.device_in_reset_drop_cnt); 428e65e175bSOded Gabbay cs_counters.ctx_max_cs_in_flight_drop_cnt = 429e65e175bSOded Gabbay atomic64_read( 430e65e175bSOded Gabbay &hpriv->ctx->cs_counters.max_cs_in_flight_drop_cnt); 431e65e175bSOded Gabbay cs_counters.ctx_validation_drop_cnt = 432e65e175bSOded Gabbay atomic64_read( 433e65e175bSOded Gabbay &hpriv->ctx->cs_counters.validation_drop_cnt); 434e65e175bSOded Gabbay } 435e65e175bSOded Gabbay 436e65e175bSOded Gabbay return copy_to_user(out, &cs_counters, 437e65e175bSOded Gabbay min((size_t) max_size, sizeof(cs_counters))) ? -EFAULT : 0; 438e65e175bSOded Gabbay } 439e65e175bSOded Gabbay 440e65e175bSOded Gabbay static int sync_manager_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 441e65e175bSOded Gabbay { 442e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 443e65e175bSOded Gabbay struct asic_fixed_properties *prop = &hdev->asic_prop; 444e65e175bSOded Gabbay struct hl_info_sync_manager sm_info = {0}; 445e65e175bSOded Gabbay u32 max_size = args->return_size; 446e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 447e65e175bSOded Gabbay 448e65e175bSOded Gabbay if ((!max_size) || (!out)) 449e65e175bSOded Gabbay return -EINVAL; 450e65e175bSOded Gabbay 451e65e175bSOded Gabbay if (args->dcore_id >= HL_MAX_DCORES) 452e65e175bSOded Gabbay return -EINVAL; 453e65e175bSOded Gabbay 454e65e175bSOded Gabbay sm_info.first_available_sync_object = 455e65e175bSOded Gabbay prop->first_available_user_sob[args->dcore_id]; 456e65e175bSOded Gabbay sm_info.first_available_monitor = 457e65e175bSOded Gabbay prop->first_available_user_mon[args->dcore_id]; 458e65e175bSOded Gabbay sm_info.first_available_cq = 459e65e175bSOded Gabbay prop->first_available_cq[args->dcore_id]; 460e65e175bSOded Gabbay 461e65e175bSOded Gabbay return copy_to_user(out, &sm_info, min_t(size_t, (size_t) max_size, 462e65e175bSOded Gabbay sizeof(sm_info))) ? -EFAULT : 0; 463e65e175bSOded Gabbay } 464e65e175bSOded Gabbay 465e65e175bSOded Gabbay static int total_energy_consumption_info(struct hl_fpriv *hpriv, 466e65e175bSOded Gabbay struct hl_info_args *args) 467e65e175bSOded Gabbay { 468e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 469e65e175bSOded Gabbay struct hl_info_energy total_energy = {0}; 470e65e175bSOded Gabbay u32 max_size = args->return_size; 471e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 472e65e175bSOded Gabbay int rc; 473e65e175bSOded Gabbay 474e65e175bSOded Gabbay if ((!max_size) || (!out)) 475e65e175bSOded Gabbay return -EINVAL; 476e65e175bSOded Gabbay 477e65e175bSOded Gabbay rc = hl_fw_cpucp_total_energy_get(hdev, 478e65e175bSOded Gabbay &total_energy.total_energy_consumption); 479e65e175bSOded Gabbay if (rc) 480e65e175bSOded Gabbay return rc; 481e65e175bSOded Gabbay 482e65e175bSOded Gabbay return copy_to_user(out, &total_energy, 483e65e175bSOded Gabbay min((size_t) max_size, sizeof(total_energy))) ? -EFAULT : 0; 484e65e175bSOded Gabbay } 485e65e175bSOded Gabbay 486e65e175bSOded Gabbay static int pll_frequency_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 487e65e175bSOded Gabbay { 488e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 489e65e175bSOded Gabbay struct hl_pll_frequency_info freq_info = { {0} }; 490e65e175bSOded Gabbay u32 max_size = args->return_size; 491e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 492e65e175bSOded Gabbay int rc; 493e65e175bSOded Gabbay 494e65e175bSOded Gabbay if ((!max_size) || (!out)) 495e65e175bSOded Gabbay return -EINVAL; 496e65e175bSOded Gabbay 497e65e175bSOded Gabbay rc = hl_fw_cpucp_pll_info_get(hdev, args->pll_index, freq_info.output); 498e65e175bSOded Gabbay if (rc) 499e65e175bSOded Gabbay return rc; 500e65e175bSOded Gabbay 501e65e175bSOded Gabbay return copy_to_user(out, &freq_info, 502e65e175bSOded Gabbay min((size_t) max_size, sizeof(freq_info))) ? -EFAULT : 0; 503e65e175bSOded Gabbay } 504e65e175bSOded Gabbay 505e65e175bSOded Gabbay static int power_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 506e65e175bSOded Gabbay { 507e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 508e65e175bSOded Gabbay u32 max_size = args->return_size; 509e65e175bSOded Gabbay struct hl_power_info power_info = {0}; 510e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 511e65e175bSOded Gabbay int rc; 512e65e175bSOded Gabbay 513e65e175bSOded Gabbay if ((!max_size) || (!out)) 514e65e175bSOded Gabbay return -EINVAL; 515e65e175bSOded Gabbay 516e65e175bSOded Gabbay rc = hl_fw_cpucp_power_get(hdev, &power_info.power); 517e65e175bSOded Gabbay if (rc) 518e65e175bSOded Gabbay return rc; 519e65e175bSOded Gabbay 520e65e175bSOded Gabbay return copy_to_user(out, &power_info, 521e65e175bSOded Gabbay min((size_t) max_size, sizeof(power_info))) ? -EFAULT : 0; 522e65e175bSOded Gabbay } 523e65e175bSOded Gabbay 524e65e175bSOded Gabbay static int open_stats_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 525e65e175bSOded Gabbay { 526e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 527e65e175bSOded Gabbay u32 max_size = args->return_size; 528e65e175bSOded Gabbay struct hl_open_stats_info open_stats_info = {0}; 529e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 530e65e175bSOded Gabbay 531e65e175bSOded Gabbay if ((!max_size) || (!out)) 532e65e175bSOded Gabbay return -EINVAL; 533e65e175bSOded Gabbay 534e65e175bSOded Gabbay open_stats_info.last_open_period_ms = jiffies64_to_msecs( 535e65e175bSOded Gabbay hdev->last_open_session_duration_jif); 536e65e175bSOded Gabbay open_stats_info.open_counter = hdev->open_counter; 537e65e175bSOded Gabbay open_stats_info.is_compute_ctx_active = hdev->is_compute_ctx_active; 538e65e175bSOded Gabbay open_stats_info.compute_ctx_in_release = hdev->compute_ctx_in_release; 539e65e175bSOded Gabbay 540e65e175bSOded Gabbay return copy_to_user(out, &open_stats_info, 541e65e175bSOded Gabbay min((size_t) max_size, sizeof(open_stats_info))) ? -EFAULT : 0; 542e65e175bSOded Gabbay } 543e65e175bSOded Gabbay 544e65e175bSOded Gabbay static int dram_pending_rows_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 545e65e175bSOded Gabbay { 546e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 547e65e175bSOded Gabbay u32 max_size = args->return_size; 548e65e175bSOded Gabbay u32 pend_rows_num = 0; 549e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 550e65e175bSOded Gabbay int rc; 551e65e175bSOded Gabbay 552e65e175bSOded Gabbay if ((!max_size) || (!out)) 553e65e175bSOded Gabbay return -EINVAL; 554e65e175bSOded Gabbay 555e65e175bSOded Gabbay rc = hl_fw_dram_pending_row_get(hdev, &pend_rows_num); 556e65e175bSOded Gabbay if (rc) 557e65e175bSOded Gabbay return rc; 558e65e175bSOded Gabbay 559e65e175bSOded Gabbay return copy_to_user(out, &pend_rows_num, 560e65e175bSOded Gabbay min_t(size_t, max_size, sizeof(pend_rows_num))) ? -EFAULT : 0; 561e65e175bSOded Gabbay } 562e65e175bSOded Gabbay 563e65e175bSOded Gabbay static int dram_replaced_rows_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 564e65e175bSOded Gabbay { 565e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 566e65e175bSOded Gabbay u32 max_size = args->return_size; 567e65e175bSOded Gabbay struct cpucp_hbm_row_info info = {0}; 568e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 569e65e175bSOded Gabbay int rc; 570e65e175bSOded Gabbay 571e65e175bSOded Gabbay if ((!max_size) || (!out)) 572e65e175bSOded Gabbay return -EINVAL; 573e65e175bSOded Gabbay 574e65e175bSOded Gabbay rc = hl_fw_dram_replaced_row_get(hdev, &info); 575e65e175bSOded Gabbay if (rc) 576e65e175bSOded Gabbay return rc; 577e65e175bSOded Gabbay 578e65e175bSOded Gabbay return copy_to_user(out, &info, min_t(size_t, max_size, sizeof(info))) ? -EFAULT : 0; 579e65e175bSOded Gabbay } 580e65e175bSOded Gabbay 581e65e175bSOded Gabbay static int last_err_open_dev_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 582e65e175bSOded Gabbay { 583e65e175bSOded Gabbay struct hl_info_last_err_open_dev_time info = {0}; 584e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 585e65e175bSOded Gabbay u32 max_size = args->return_size; 586e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 587e65e175bSOded Gabbay 588e65e175bSOded Gabbay if ((!max_size) || (!out)) 589e65e175bSOded Gabbay return -EINVAL; 590e65e175bSOded Gabbay 591e65e175bSOded Gabbay info.timestamp = ktime_to_ns(hdev->last_successful_open_ktime); 592e65e175bSOded Gabbay 593e65e175bSOded Gabbay return copy_to_user(out, &info, min_t(size_t, max_size, sizeof(info))) ? -EFAULT : 0; 594e65e175bSOded Gabbay } 595e65e175bSOded Gabbay 596e65e175bSOded Gabbay static int cs_timeout_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 597e65e175bSOded Gabbay { 598e65e175bSOded Gabbay struct hl_info_cs_timeout_event info = {0}; 599e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 600e65e175bSOded Gabbay u32 max_size = args->return_size; 601e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 602e65e175bSOded Gabbay 603e65e175bSOded Gabbay if ((!max_size) || (!out)) 604e65e175bSOded Gabbay return -EINVAL; 605e65e175bSOded Gabbay 606e65e175bSOded Gabbay info.seq = hdev->captured_err_info.cs_timeout.seq; 607e65e175bSOded Gabbay info.timestamp = ktime_to_ns(hdev->captured_err_info.cs_timeout.timestamp); 608e65e175bSOded Gabbay 609e65e175bSOded Gabbay return copy_to_user(out, &info, min_t(size_t, max_size, sizeof(info))) ? -EFAULT : 0; 610e65e175bSOded Gabbay } 611e65e175bSOded Gabbay 612e65e175bSOded Gabbay static int razwi_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 613e65e175bSOded Gabbay { 614571d1a72SKoby Elbaz void __user *out = (void __user *) (uintptr_t) args->return_pointer; 615e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 616e65e175bSOded Gabbay u32 max_size = args->return_size; 617571d1a72SKoby Elbaz struct razwi_info *razwi_info; 618e65e175bSOded Gabbay 619e65e175bSOded Gabbay if ((!max_size) || (!out)) 620e65e175bSOded Gabbay return -EINVAL; 621e65e175bSOded Gabbay 622571d1a72SKoby Elbaz razwi_info = &hdev->captured_err_info.razwi_info; 623571d1a72SKoby Elbaz if (!razwi_info->razwi_info_available) 624571d1a72SKoby Elbaz return 0; 625571d1a72SKoby Elbaz 626571d1a72SKoby Elbaz return copy_to_user(out, &razwi_info->razwi, 627571d1a72SKoby Elbaz min_t(size_t, max_size, sizeof(struct hl_info_razwi_event))) ? -EFAULT : 0; 628e65e175bSOded Gabbay } 629e65e175bSOded Gabbay 630e65e175bSOded Gabbay static int undefined_opcode_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 631e65e175bSOded Gabbay { 632e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 633e65e175bSOded Gabbay u32 max_size = args->return_size; 634e65e175bSOded Gabbay struct hl_info_undefined_opcode_event info = {0}; 635e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 636e65e175bSOded Gabbay 637e65e175bSOded Gabbay if ((!max_size) || (!out)) 638e65e175bSOded Gabbay return -EINVAL; 639e65e175bSOded Gabbay 640e65e175bSOded Gabbay info.timestamp = ktime_to_ns(hdev->captured_err_info.undef_opcode.timestamp); 641e65e175bSOded Gabbay info.engine_id = hdev->captured_err_info.undef_opcode.engine_id; 642e65e175bSOded Gabbay info.cq_addr = hdev->captured_err_info.undef_opcode.cq_addr; 643e65e175bSOded Gabbay info.cq_size = hdev->captured_err_info.undef_opcode.cq_size; 644e65e175bSOded Gabbay info.stream_id = hdev->captured_err_info.undef_opcode.stream_id; 645e65e175bSOded Gabbay info.cb_addr_streams_len = hdev->captured_err_info.undef_opcode.cb_addr_streams_len; 646e65e175bSOded Gabbay memcpy(info.cb_addr_streams, hdev->captured_err_info.undef_opcode.cb_addr_streams, 647e65e175bSOded Gabbay sizeof(info.cb_addr_streams)); 648e65e175bSOded Gabbay 649e65e175bSOded Gabbay return copy_to_user(out, &info, min_t(size_t, max_size, sizeof(info))) ? -EFAULT : 0; 650e65e175bSOded Gabbay } 651e65e175bSOded Gabbay 652e65e175bSOded Gabbay static int dev_mem_alloc_page_sizes_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 653e65e175bSOded Gabbay { 654e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 655e65e175bSOded Gabbay struct hl_info_dev_memalloc_page_sizes info = {0}; 656e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 657e65e175bSOded Gabbay u32 max_size = args->return_size; 658e65e175bSOded Gabbay 659e65e175bSOded Gabbay if ((!max_size) || (!out)) 660e65e175bSOded Gabbay return -EINVAL; 661e65e175bSOded Gabbay 662e65e175bSOded Gabbay /* 663e65e175bSOded Gabbay * Future ASICs that will support multiple DRAM page sizes will support only "powers of 2" 664e65e175bSOded Gabbay * pages (unlike some of the ASICs before supporting multiple page sizes). 665e65e175bSOded Gabbay * For this reason for all ASICs that not support multiple page size the function will 666e65e175bSOded Gabbay * return an empty bitmask indicating that multiple page sizes is not supported. 667e65e175bSOded Gabbay */ 668e65e175bSOded Gabbay info.page_order_bitmask = hdev->asic_prop.dmmu.supported_pages_mask; 669e65e175bSOded Gabbay 670e65e175bSOded Gabbay return copy_to_user(out, &info, min_t(size_t, max_size, sizeof(info))) ? -EFAULT : 0; 671e65e175bSOded Gabbay } 672e65e175bSOded Gabbay 673e65e175bSOded Gabbay static int sec_attest_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 674e65e175bSOded Gabbay { 675e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 676e65e175bSOded Gabbay struct cpucp_sec_attest_info *sec_attest_info; 677e65e175bSOded Gabbay struct hl_info_sec_attest *info; 678e65e175bSOded Gabbay u32 max_size = args->return_size; 679e65e175bSOded Gabbay int rc; 680e65e175bSOded Gabbay 681e65e175bSOded Gabbay if ((!max_size) || (!out)) 682e65e175bSOded Gabbay return -EINVAL; 683e65e175bSOded Gabbay 684e65e175bSOded Gabbay sec_attest_info = kmalloc(sizeof(*sec_attest_info), GFP_KERNEL); 685e65e175bSOded Gabbay if (!sec_attest_info) 686e65e175bSOded Gabbay return -ENOMEM; 687e65e175bSOded Gabbay 688e65e175bSOded Gabbay info = kmalloc(sizeof(*info), GFP_KERNEL); 689e65e175bSOded Gabbay if (!info) { 690e65e175bSOded Gabbay rc = -ENOMEM; 691e65e175bSOded Gabbay goto free_sec_attest_info; 692e65e175bSOded Gabbay } 693e65e175bSOded Gabbay 694e65e175bSOded Gabbay rc = hl_fw_get_sec_attest_info(hpriv->hdev, sec_attest_info, args->sec_attest_nonce); 695e65e175bSOded Gabbay if (rc) 696e65e175bSOded Gabbay goto free_info; 697e65e175bSOded Gabbay 698e65e175bSOded Gabbay info->nonce = le32_to_cpu(sec_attest_info->nonce); 699e65e175bSOded Gabbay info->pcr_quote_len = le16_to_cpu(sec_attest_info->pcr_quote_len); 700e65e175bSOded Gabbay info->pub_data_len = le16_to_cpu(sec_attest_info->pub_data_len); 701e65e175bSOded Gabbay info->certificate_len = le16_to_cpu(sec_attest_info->certificate_len); 702e65e175bSOded Gabbay info->pcr_num_reg = sec_attest_info->pcr_num_reg; 703e65e175bSOded Gabbay info->pcr_reg_len = sec_attest_info->pcr_reg_len; 704e65e175bSOded Gabbay info->quote_sig_len = sec_attest_info->quote_sig_len; 705e65e175bSOded Gabbay memcpy(&info->pcr_data, &sec_attest_info->pcr_data, sizeof(info->pcr_data)); 706e65e175bSOded Gabbay memcpy(&info->pcr_quote, &sec_attest_info->pcr_quote, sizeof(info->pcr_quote)); 707e65e175bSOded Gabbay memcpy(&info->public_data, &sec_attest_info->public_data, sizeof(info->public_data)); 708e65e175bSOded Gabbay memcpy(&info->certificate, &sec_attest_info->certificate, sizeof(info->certificate)); 709e65e175bSOded Gabbay memcpy(&info->quote_sig, &sec_attest_info->quote_sig, sizeof(info->quote_sig)); 710e65e175bSOded Gabbay 711e65e175bSOded Gabbay rc = copy_to_user(out, info, 712e65e175bSOded Gabbay min_t(size_t, max_size, sizeof(*info))) ? -EFAULT : 0; 713e65e175bSOded Gabbay 714e65e175bSOded Gabbay free_info: 715e65e175bSOded Gabbay kfree(info); 716e65e175bSOded Gabbay free_sec_attest_info: 717e65e175bSOded Gabbay kfree(sec_attest_info); 718e65e175bSOded Gabbay 719e65e175bSOded Gabbay return rc; 720e65e175bSOded Gabbay } 721e65e175bSOded Gabbay 722e65e175bSOded Gabbay static int eventfd_register(struct hl_fpriv *hpriv, struct hl_info_args *args) 723e65e175bSOded Gabbay { 724e65e175bSOded Gabbay int rc; 725e65e175bSOded Gabbay 726e65e175bSOded Gabbay /* check if there is already a registered on that process */ 727e65e175bSOded Gabbay mutex_lock(&hpriv->notifier_event.lock); 728e65e175bSOded Gabbay if (hpriv->notifier_event.eventfd) { 729e65e175bSOded Gabbay mutex_unlock(&hpriv->notifier_event.lock); 730e65e175bSOded Gabbay return -EINVAL; 731e65e175bSOded Gabbay } 732e65e175bSOded Gabbay 733e65e175bSOded Gabbay hpriv->notifier_event.eventfd = eventfd_ctx_fdget(args->eventfd); 734e65e175bSOded Gabbay if (IS_ERR(hpriv->notifier_event.eventfd)) { 735e65e175bSOded Gabbay rc = PTR_ERR(hpriv->notifier_event.eventfd); 736e65e175bSOded Gabbay hpriv->notifier_event.eventfd = NULL; 737e65e175bSOded Gabbay mutex_unlock(&hpriv->notifier_event.lock); 738e65e175bSOded Gabbay return rc; 739e65e175bSOded Gabbay } 740e65e175bSOded Gabbay 741e65e175bSOded Gabbay mutex_unlock(&hpriv->notifier_event.lock); 742e65e175bSOded Gabbay return 0; 743e65e175bSOded Gabbay } 744e65e175bSOded Gabbay 745e65e175bSOded Gabbay static int eventfd_unregister(struct hl_fpriv *hpriv, struct hl_info_args *args) 746e65e175bSOded Gabbay { 747e65e175bSOded Gabbay mutex_lock(&hpriv->notifier_event.lock); 748e65e175bSOded Gabbay if (!hpriv->notifier_event.eventfd) { 749e65e175bSOded Gabbay mutex_unlock(&hpriv->notifier_event.lock); 750e65e175bSOded Gabbay return -EINVAL; 751e65e175bSOded Gabbay } 752e65e175bSOded Gabbay 753e65e175bSOded Gabbay eventfd_ctx_put(hpriv->notifier_event.eventfd); 754e65e175bSOded Gabbay hpriv->notifier_event.eventfd = NULL; 755e65e175bSOded Gabbay mutex_unlock(&hpriv->notifier_event.lock); 756e65e175bSOded Gabbay return 0; 757e65e175bSOded Gabbay } 758e65e175bSOded Gabbay 759e65e175bSOded Gabbay static int engine_status_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 760e65e175bSOded Gabbay { 761e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 762e65e175bSOded Gabbay u32 status_buf_size = args->return_size; 763e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 764e65e175bSOded Gabbay struct engines_data eng_data; 765e65e175bSOded Gabbay int rc; 766e65e175bSOded Gabbay 767e65e175bSOded Gabbay if ((status_buf_size < SZ_1K) || (status_buf_size > HL_ENGINES_DATA_MAX_SIZE) || (!out)) 768e65e175bSOded Gabbay return -EINVAL; 769e65e175bSOded Gabbay 770e65e175bSOded Gabbay eng_data.actual_size = 0; 771e65e175bSOded Gabbay eng_data.allocated_buf_size = status_buf_size; 772e65e175bSOded Gabbay eng_data.buf = vmalloc(status_buf_size); 773e65e175bSOded Gabbay if (!eng_data.buf) 774e65e175bSOded Gabbay return -ENOMEM; 775e65e175bSOded Gabbay 776e65e175bSOded Gabbay hdev->asic_funcs->is_device_idle(hdev, NULL, 0, &eng_data); 777e65e175bSOded Gabbay 778e65e175bSOded Gabbay if (eng_data.actual_size > eng_data.allocated_buf_size) { 779e65e175bSOded Gabbay dev_err(hdev->dev, 780e65e175bSOded Gabbay "Engines data size (%d Bytes) is bigger than allocated size (%u Bytes)\n", 781e65e175bSOded Gabbay eng_data.actual_size, status_buf_size); 782e65e175bSOded Gabbay vfree(eng_data.buf); 783e65e175bSOded Gabbay return -ENOMEM; 784e65e175bSOded Gabbay } 785e65e175bSOded Gabbay 786e65e175bSOded Gabbay args->user_buffer_actual_size = eng_data.actual_size; 787e65e175bSOded Gabbay rc = copy_to_user(out, eng_data.buf, min_t(size_t, status_buf_size, eng_data.actual_size)) ? 788e65e175bSOded Gabbay -EFAULT : 0; 789e65e175bSOded Gabbay 790e65e175bSOded Gabbay vfree(eng_data.buf); 791e65e175bSOded Gabbay 792e65e175bSOded Gabbay return rc; 793e65e175bSOded Gabbay } 794e65e175bSOded Gabbay 795e65e175bSOded Gabbay static int page_fault_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 796e65e175bSOded Gabbay { 797571d1a72SKoby Elbaz void __user *out = (void __user *) (uintptr_t) args->return_pointer; 798e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 799e65e175bSOded Gabbay u32 max_size = args->return_size; 800571d1a72SKoby Elbaz struct page_fault_info *pgf_info; 801e65e175bSOded Gabbay 802e65e175bSOded Gabbay if ((!max_size) || (!out)) 803e65e175bSOded Gabbay return -EINVAL; 804e65e175bSOded Gabbay 805571d1a72SKoby Elbaz pgf_info = &hdev->captured_err_info.page_fault_info; 806571d1a72SKoby Elbaz if (!pgf_info->page_fault_info_available) 807571d1a72SKoby Elbaz return 0; 808571d1a72SKoby Elbaz 809571d1a72SKoby Elbaz return copy_to_user(out, &pgf_info->page_fault, 810571d1a72SKoby Elbaz min_t(size_t, max_size, sizeof(struct hl_page_fault_info))) ? -EFAULT : 0; 811e65e175bSOded Gabbay } 812e65e175bSOded Gabbay 813e65e175bSOded Gabbay static int user_mappings_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 814e65e175bSOded Gabbay { 815e65e175bSOded Gabbay void __user *out = (void __user *) (uintptr_t) args->return_pointer; 816e65e175bSOded Gabbay u32 user_buf_size = args->return_size; 817e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 818e65e175bSOded Gabbay struct page_fault_info *pgf_info; 819e65e175bSOded Gabbay u64 actual_size; 820e65e175bSOded Gabbay 821e65e175bSOded Gabbay if (!out) 822e65e175bSOded Gabbay return -EINVAL; 823e65e175bSOded Gabbay 824571d1a72SKoby Elbaz pgf_info = &hdev->captured_err_info.page_fault_info; 825571d1a72SKoby Elbaz if (!pgf_info->page_fault_info_available) 826571d1a72SKoby Elbaz return 0; 827571d1a72SKoby Elbaz 828571d1a72SKoby Elbaz args->array_size = pgf_info->num_of_user_mappings; 829571d1a72SKoby Elbaz 830e65e175bSOded Gabbay actual_size = pgf_info->num_of_user_mappings * sizeof(struct hl_user_mapping); 831e65e175bSOded Gabbay if (user_buf_size < actual_size) 832e65e175bSOded Gabbay return -ENOMEM; 833e65e175bSOded Gabbay 834571d1a72SKoby Elbaz return copy_to_user(out, pgf_info->user_mappings, actual_size) ? -EFAULT : 0; 835e65e175bSOded Gabbay } 836e65e175bSOded Gabbay 837313e9f63SMoti Haimovski static int hw_err_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 838313e9f63SMoti Haimovski { 839313e9f63SMoti Haimovski void __user *user_buf = (void __user *) (uintptr_t) args->return_pointer; 840313e9f63SMoti Haimovski struct hl_device *hdev = hpriv->hdev; 841313e9f63SMoti Haimovski u32 user_buf_size = args->return_size; 842313e9f63SMoti Haimovski struct hw_err_info *info; 843313e9f63SMoti Haimovski int rc; 844313e9f63SMoti Haimovski 845*04729b41SMoti Haimovski if (!user_buf) 846313e9f63SMoti Haimovski return -EINVAL; 847313e9f63SMoti Haimovski 848313e9f63SMoti Haimovski info = &hdev->captured_err_info.hw_err; 849313e9f63SMoti Haimovski if (!info->event_info_available) 850*04729b41SMoti Haimovski return 0; 851*04729b41SMoti Haimovski 852*04729b41SMoti Haimovski if (user_buf_size < sizeof(struct hl_info_hw_err_event)) 853*04729b41SMoti Haimovski return -ENOMEM; 854313e9f63SMoti Haimovski 855313e9f63SMoti Haimovski rc = copy_to_user(user_buf, &info->event, sizeof(struct hl_info_hw_err_event)); 856313e9f63SMoti Haimovski return rc ? -EFAULT : 0; 857313e9f63SMoti Haimovski } 858313e9f63SMoti Haimovski 859313e9f63SMoti Haimovski static int fw_err_info(struct hl_fpriv *hpriv, struct hl_info_args *args) 860313e9f63SMoti Haimovski { 861313e9f63SMoti Haimovski void __user *user_buf = (void __user *) (uintptr_t) args->return_pointer; 862313e9f63SMoti Haimovski struct hl_device *hdev = hpriv->hdev; 863313e9f63SMoti Haimovski u32 user_buf_size = args->return_size; 864313e9f63SMoti Haimovski struct fw_err_info *info; 865313e9f63SMoti Haimovski int rc; 866313e9f63SMoti Haimovski 867*04729b41SMoti Haimovski if (!user_buf) 868313e9f63SMoti Haimovski return -EINVAL; 869313e9f63SMoti Haimovski 870313e9f63SMoti Haimovski info = &hdev->captured_err_info.fw_err; 871313e9f63SMoti Haimovski if (!info->event_info_available) 872*04729b41SMoti Haimovski return 0; 873*04729b41SMoti Haimovski 874*04729b41SMoti Haimovski if (user_buf_size < sizeof(struct hl_info_fw_err_event)) 875*04729b41SMoti Haimovski return -ENOMEM; 876313e9f63SMoti Haimovski 877313e9f63SMoti Haimovski rc = copy_to_user(user_buf, &info->event, sizeof(struct hl_info_fw_err_event)); 878313e9f63SMoti Haimovski return rc ? -EFAULT : 0; 879313e9f63SMoti Haimovski } 880313e9f63SMoti Haimovski 881e65e175bSOded Gabbay static int send_fw_generic_request(struct hl_device *hdev, struct hl_info_args *info_args) 882e65e175bSOded Gabbay { 883e65e175bSOded Gabbay void __user *buff = (void __user *) (uintptr_t) info_args->return_pointer; 884e65e175bSOded Gabbay u32 size = info_args->return_size; 885e65e175bSOded Gabbay dma_addr_t dma_handle; 886e65e175bSOded Gabbay bool need_input_buff; 887e65e175bSOded Gabbay void *fw_buff; 888e65e175bSOded Gabbay int rc = 0; 889e65e175bSOded Gabbay 890e65e175bSOded Gabbay switch (info_args->fw_sub_opcode) { 891e65e175bSOded Gabbay case HL_PASSTHROUGH_VERSIONS: 892e65e175bSOded Gabbay need_input_buff = false; 893e65e175bSOded Gabbay break; 894e65e175bSOded Gabbay default: 895e65e175bSOded Gabbay return -EINVAL; 896e65e175bSOded Gabbay } 897e65e175bSOded Gabbay 898e65e175bSOded Gabbay if (size > SZ_1M) { 899e65e175bSOded Gabbay dev_err(hdev->dev, "buffer size cannot exceed 1MB\n"); 900e65e175bSOded Gabbay return -EINVAL; 901e65e175bSOded Gabbay } 902e65e175bSOded Gabbay 903e65e175bSOded Gabbay fw_buff = hl_cpu_accessible_dma_pool_alloc(hdev, size, &dma_handle); 904e65e175bSOded Gabbay if (!fw_buff) 905e65e175bSOded Gabbay return -ENOMEM; 906e65e175bSOded Gabbay 907e65e175bSOded Gabbay 908e65e175bSOded Gabbay if (need_input_buff && copy_from_user(fw_buff, buff, size)) { 909e65e175bSOded Gabbay dev_dbg(hdev->dev, "Failed to copy from user FW buff\n"); 910e65e175bSOded Gabbay rc = -EFAULT; 911e65e175bSOded Gabbay goto free_buff; 912e65e175bSOded Gabbay } 913e65e175bSOded Gabbay 914e65e175bSOded Gabbay rc = hl_fw_send_generic_request(hdev, info_args->fw_sub_opcode, dma_handle, &size); 915e65e175bSOded Gabbay if (rc) 916e65e175bSOded Gabbay goto free_buff; 917e65e175bSOded Gabbay 918e65e175bSOded Gabbay if (copy_to_user(buff, fw_buff, min(size, info_args->return_size))) { 919e65e175bSOded Gabbay dev_dbg(hdev->dev, "Failed to copy to user FW generic req output\n"); 920e65e175bSOded Gabbay rc = -EFAULT; 921e65e175bSOded Gabbay } 922e65e175bSOded Gabbay 923e65e175bSOded Gabbay free_buff: 924e65e175bSOded Gabbay hl_cpu_accessible_dma_pool_free(hdev, info_args->return_size, fw_buff); 925e65e175bSOded Gabbay 926e65e175bSOded Gabbay return rc; 927e65e175bSOded Gabbay } 928e65e175bSOded Gabbay 929e65e175bSOded Gabbay static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data, 930e65e175bSOded Gabbay struct device *dev) 931e65e175bSOded Gabbay { 932e65e175bSOded Gabbay enum hl_device_status status; 933e65e175bSOded Gabbay struct hl_info_args *args = data; 934e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 935e65e175bSOded Gabbay int rc; 936e65e175bSOded Gabbay 93772848de0Sfarah kassabri if (args->pad) { 93872848de0Sfarah kassabri dev_dbg(hdev->dev, "Padding bytes must be 0\n"); 93972848de0Sfarah kassabri return -EINVAL; 94072848de0Sfarah kassabri } 94172848de0Sfarah kassabri 942e65e175bSOded Gabbay /* 943e65e175bSOded Gabbay * Information is returned for the following opcodes even if the device 944e65e175bSOded Gabbay * is disabled or in reset. 945e65e175bSOded Gabbay */ 946e65e175bSOded Gabbay switch (args->op) { 947e65e175bSOded Gabbay case HL_INFO_HW_IP_INFO: 948e65e175bSOded Gabbay return hw_ip_info(hdev, args); 949e65e175bSOded Gabbay 950e65e175bSOded Gabbay case HL_INFO_DEVICE_STATUS: 951e65e175bSOded Gabbay return device_status_info(hdev, args); 952e65e175bSOded Gabbay 953e65e175bSOded Gabbay case HL_INFO_RESET_COUNT: 954e65e175bSOded Gabbay return get_reset_count(hdev, args); 955e65e175bSOded Gabbay 956e65e175bSOded Gabbay case HL_INFO_HW_EVENTS: 957e65e175bSOded Gabbay return hw_events_info(hdev, false, args); 958e65e175bSOded Gabbay 959e65e175bSOded Gabbay case HL_INFO_HW_EVENTS_AGGREGATE: 960e65e175bSOded Gabbay return hw_events_info(hdev, true, args); 961e65e175bSOded Gabbay 962e65e175bSOded Gabbay case HL_INFO_CS_COUNTERS: 963e65e175bSOded Gabbay return cs_counters_info(hpriv, args); 964e65e175bSOded Gabbay 965e65e175bSOded Gabbay case HL_INFO_CLK_THROTTLE_REASON: 966e65e175bSOded Gabbay return clk_throttle_info(hpriv, args); 967e65e175bSOded Gabbay 968e65e175bSOded Gabbay case HL_INFO_SYNC_MANAGER: 969e65e175bSOded Gabbay return sync_manager_info(hpriv, args); 970e65e175bSOded Gabbay 971e65e175bSOded Gabbay case HL_INFO_OPEN_STATS: 972e65e175bSOded Gabbay return open_stats_info(hpriv, args); 973e65e175bSOded Gabbay 974e65e175bSOded Gabbay case HL_INFO_LAST_ERR_OPEN_DEV_TIME: 975e65e175bSOded Gabbay return last_err_open_dev_info(hpriv, args); 976e65e175bSOded Gabbay 977e65e175bSOded Gabbay case HL_INFO_CS_TIMEOUT_EVENT: 978e65e175bSOded Gabbay return cs_timeout_info(hpriv, args); 979e65e175bSOded Gabbay 980e65e175bSOded Gabbay case HL_INFO_RAZWI_EVENT: 981e65e175bSOded Gabbay return razwi_info(hpriv, args); 982e65e175bSOded Gabbay 983e65e175bSOded Gabbay case HL_INFO_UNDEFINED_OPCODE_EVENT: 984e65e175bSOded Gabbay return undefined_opcode_info(hpriv, args); 985e65e175bSOded Gabbay 986e65e175bSOded Gabbay case HL_INFO_DEV_MEM_ALLOC_PAGE_SIZES: 987e65e175bSOded Gabbay return dev_mem_alloc_page_sizes_info(hpriv, args); 988e65e175bSOded Gabbay 989e65e175bSOded Gabbay case HL_INFO_GET_EVENTS: 990e65e175bSOded Gabbay return events_info(hpriv, args); 991e65e175bSOded Gabbay 992e65e175bSOded Gabbay case HL_INFO_PAGE_FAULT_EVENT: 993e65e175bSOded Gabbay return page_fault_info(hpriv, args); 994e65e175bSOded Gabbay 995e65e175bSOded Gabbay case HL_INFO_USER_MAPPINGS: 996e65e175bSOded Gabbay return user_mappings_info(hpriv, args); 997e65e175bSOded Gabbay 998e65e175bSOded Gabbay case HL_INFO_UNREGISTER_EVENTFD: 999e65e175bSOded Gabbay return eventfd_unregister(hpriv, args); 1000e65e175bSOded Gabbay 1001313e9f63SMoti Haimovski case HL_INFO_HW_ERR_EVENT: 1002313e9f63SMoti Haimovski return hw_err_info(hpriv, args); 1003313e9f63SMoti Haimovski 1004313e9f63SMoti Haimovski case HL_INFO_FW_ERR_EVENT: 1005313e9f63SMoti Haimovski return fw_err_info(hpriv, args); 1006313e9f63SMoti Haimovski 1007c7ac65c8SDafna Hirschfeld case HL_INFO_DRAM_USAGE: 1008c7ac65c8SDafna Hirschfeld return dram_usage_info(hpriv, args); 1009e65e175bSOded Gabbay default: 1010e65e175bSOded Gabbay break; 1011e65e175bSOded Gabbay } 1012e65e175bSOded Gabbay 1013e65e175bSOded Gabbay if (!hl_device_operational(hdev, &status)) { 1014e1e8e747SOded Gabbay dev_dbg_ratelimited(dev, 1015e65e175bSOded Gabbay "Device is %s. Can't execute INFO IOCTL\n", 1016e65e175bSOded Gabbay hdev->status[status]); 1017e65e175bSOded Gabbay return -EBUSY; 1018e65e175bSOded Gabbay } 1019e65e175bSOded Gabbay 1020e65e175bSOded Gabbay switch (args->op) { 1021e65e175bSOded Gabbay case HL_INFO_HW_IDLE: 1022e65e175bSOded Gabbay rc = hw_idle(hdev, args); 1023e65e175bSOded Gabbay break; 1024e65e175bSOded Gabbay 1025e65e175bSOded Gabbay case HL_INFO_DEVICE_UTILIZATION: 1026e65e175bSOded Gabbay rc = device_utilization(hdev, args); 1027e65e175bSOded Gabbay break; 1028e65e175bSOded Gabbay 1029e65e175bSOded Gabbay case HL_INFO_CLK_RATE: 1030e65e175bSOded Gabbay rc = get_clk_rate(hdev, args); 1031e65e175bSOded Gabbay break; 1032e65e175bSOded Gabbay 1033e65e175bSOded Gabbay case HL_INFO_TIME_SYNC: 1034e65e175bSOded Gabbay return time_sync_info(hdev, args); 1035e65e175bSOded Gabbay 1036e65e175bSOded Gabbay case HL_INFO_PCI_COUNTERS: 1037e65e175bSOded Gabbay return pci_counters_info(hpriv, args); 1038e65e175bSOded Gabbay 1039e65e175bSOded Gabbay case HL_INFO_TOTAL_ENERGY: 1040e65e175bSOded Gabbay return total_energy_consumption_info(hpriv, args); 1041e65e175bSOded Gabbay 1042e65e175bSOded Gabbay case HL_INFO_PLL_FREQUENCY: 1043e65e175bSOded Gabbay return pll_frequency_info(hpriv, args); 1044e65e175bSOded Gabbay 1045e65e175bSOded Gabbay case HL_INFO_POWER: 1046e65e175bSOded Gabbay return power_info(hpriv, args); 1047e65e175bSOded Gabbay 1048e65e175bSOded Gabbay 1049e65e175bSOded Gabbay case HL_INFO_DRAM_REPLACED_ROWS: 1050e65e175bSOded Gabbay return dram_replaced_rows_info(hpriv, args); 1051e65e175bSOded Gabbay 1052e65e175bSOded Gabbay case HL_INFO_DRAM_PENDING_ROWS: 1053e65e175bSOded Gabbay return dram_pending_rows_info(hpriv, args); 1054e65e175bSOded Gabbay 1055e65e175bSOded Gabbay case HL_INFO_SECURED_ATTESTATION: 1056e65e175bSOded Gabbay return sec_attest_info(hpriv, args); 1057e65e175bSOded Gabbay 1058e65e175bSOded Gabbay case HL_INFO_REGISTER_EVENTFD: 1059e65e175bSOded Gabbay return eventfd_register(hpriv, args); 1060e65e175bSOded Gabbay 1061e65e175bSOded Gabbay case HL_INFO_ENGINE_STATUS: 1062e65e175bSOded Gabbay return engine_status_info(hpriv, args); 1063e65e175bSOded Gabbay 1064e65e175bSOded Gabbay case HL_INFO_FW_GENERIC_REQ: 1065e65e175bSOded Gabbay return send_fw_generic_request(hdev, args); 1066e65e175bSOded Gabbay 1067e65e175bSOded Gabbay default: 1068e65e175bSOded Gabbay dev_err(dev, "Invalid request %d\n", args->op); 1069e65e175bSOded Gabbay rc = -EINVAL; 1070e65e175bSOded Gabbay break; 1071e65e175bSOded Gabbay } 1072e65e175bSOded Gabbay 1073e65e175bSOded Gabbay return rc; 1074e65e175bSOded Gabbay } 1075e65e175bSOded Gabbay 1076e65e175bSOded Gabbay static int hl_info_ioctl(struct hl_fpriv *hpriv, void *data) 1077e65e175bSOded Gabbay { 1078e65e175bSOded Gabbay return _hl_info_ioctl(hpriv, data, hpriv->hdev->dev); 1079e65e175bSOded Gabbay } 1080e65e175bSOded Gabbay 1081e65e175bSOded Gabbay static int hl_info_ioctl_control(struct hl_fpriv *hpriv, void *data) 1082e65e175bSOded Gabbay { 1083e65e175bSOded Gabbay return _hl_info_ioctl(hpriv, data, hpriv->hdev->dev_ctrl); 1084e65e175bSOded Gabbay } 1085e65e175bSOded Gabbay 1086e65e175bSOded Gabbay static int hl_debug_ioctl(struct hl_fpriv *hpriv, void *data) 1087e65e175bSOded Gabbay { 1088e65e175bSOded Gabbay struct hl_debug_args *args = data; 1089e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 1090e65e175bSOded Gabbay enum hl_device_status status; 1091e65e175bSOded Gabbay 1092e65e175bSOded Gabbay int rc = 0; 1093e65e175bSOded Gabbay 1094e65e175bSOded Gabbay if (!hl_device_operational(hdev, &status)) { 1095e1e8e747SOded Gabbay dev_dbg_ratelimited(hdev->dev, 1096e65e175bSOded Gabbay "Device is %s. Can't execute DEBUG IOCTL\n", 1097e65e175bSOded Gabbay hdev->status[status]); 1098e65e175bSOded Gabbay return -EBUSY; 1099e65e175bSOded Gabbay } 1100e65e175bSOded Gabbay 1101e65e175bSOded Gabbay switch (args->op) { 1102e65e175bSOded Gabbay case HL_DEBUG_OP_ETR: 1103e65e175bSOded Gabbay case HL_DEBUG_OP_ETF: 1104e65e175bSOded Gabbay case HL_DEBUG_OP_STM: 1105e65e175bSOded Gabbay case HL_DEBUG_OP_FUNNEL: 1106e65e175bSOded Gabbay case HL_DEBUG_OP_BMON: 1107e65e175bSOded Gabbay case HL_DEBUG_OP_SPMU: 1108e65e175bSOded Gabbay case HL_DEBUG_OP_TIMESTAMP: 1109e65e175bSOded Gabbay if (!hdev->in_debug) { 1110e65e175bSOded Gabbay dev_err_ratelimited(hdev->dev, 1111e65e175bSOded Gabbay "Rejecting debug configuration request because device not in debug mode\n"); 1112e65e175bSOded Gabbay return -EFAULT; 1113e65e175bSOded Gabbay } 1114e65e175bSOded Gabbay args->input_size = min(args->input_size, hl_debug_struct_size[args->op]); 1115e65e175bSOded Gabbay rc = debug_coresight(hdev, hpriv->ctx, args); 1116e65e175bSOded Gabbay break; 1117e65e175bSOded Gabbay 1118e65e175bSOded Gabbay case HL_DEBUG_OP_SET_MODE: 1119e65e175bSOded Gabbay rc = hl_device_set_debug_mode(hdev, hpriv->ctx, (bool) args->enable); 1120e65e175bSOded Gabbay break; 1121e65e175bSOded Gabbay 1122e65e175bSOded Gabbay default: 1123e65e175bSOded Gabbay dev_err(hdev->dev, "Invalid request %d\n", args->op); 1124e65e175bSOded Gabbay rc = -EINVAL; 1125e65e175bSOded Gabbay break; 1126e65e175bSOded Gabbay } 1127e65e175bSOded Gabbay 1128e65e175bSOded Gabbay return rc; 1129e65e175bSOded Gabbay } 1130e65e175bSOded Gabbay 1131e65e175bSOded Gabbay #define HL_IOCTL_DEF(ioctl, _func) \ 1132e65e175bSOded Gabbay [_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func} 1133e65e175bSOded Gabbay 1134e65e175bSOded Gabbay static const struct hl_ioctl_desc hl_ioctls[] = { 1135e65e175bSOded Gabbay HL_IOCTL_DEF(HL_IOCTL_INFO, hl_info_ioctl), 1136e65e175bSOded Gabbay HL_IOCTL_DEF(HL_IOCTL_CB, hl_cb_ioctl), 1137e65e175bSOded Gabbay HL_IOCTL_DEF(HL_IOCTL_CS, hl_cs_ioctl), 1138e65e175bSOded Gabbay HL_IOCTL_DEF(HL_IOCTL_WAIT_CS, hl_wait_ioctl), 1139e65e175bSOded Gabbay HL_IOCTL_DEF(HL_IOCTL_MEMORY, hl_mem_ioctl), 1140e65e175bSOded Gabbay HL_IOCTL_DEF(HL_IOCTL_DEBUG, hl_debug_ioctl) 1141e65e175bSOded Gabbay }; 1142e65e175bSOded Gabbay 1143e65e175bSOded Gabbay static const struct hl_ioctl_desc hl_ioctls_control[] = { 1144e65e175bSOded Gabbay HL_IOCTL_DEF(HL_IOCTL_INFO, hl_info_ioctl_control) 1145e65e175bSOded Gabbay }; 1146e65e175bSOded Gabbay 1147e65e175bSOded Gabbay static long _hl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg, 1148e65e175bSOded Gabbay const struct hl_ioctl_desc *ioctl, struct device *dev) 1149e65e175bSOded Gabbay { 1150e65e175bSOded Gabbay struct hl_fpriv *hpriv = filep->private_data; 1151e65e175bSOded Gabbay unsigned int nr = _IOC_NR(cmd); 1152e65e175bSOded Gabbay char stack_kdata[128] = {0}; 1153e65e175bSOded Gabbay char *kdata = NULL; 1154e65e175bSOded Gabbay unsigned int usize, asize; 1155e65e175bSOded Gabbay hl_ioctl_t *func; 1156e65e175bSOded Gabbay u32 hl_size; 1157e65e175bSOded Gabbay int retcode; 1158e65e175bSOded Gabbay 1159e65e175bSOded Gabbay /* Do not trust userspace, use our own definition */ 1160e65e175bSOded Gabbay func = ioctl->func; 1161e65e175bSOded Gabbay 1162e65e175bSOded Gabbay if (unlikely(!func)) { 1163e65e175bSOded Gabbay dev_dbg(dev, "no function\n"); 1164e65e175bSOded Gabbay retcode = -ENOTTY; 1165e65e175bSOded Gabbay goto out_err; 1166e65e175bSOded Gabbay } 1167e65e175bSOded Gabbay 1168e65e175bSOded Gabbay hl_size = _IOC_SIZE(ioctl->cmd); 1169e65e175bSOded Gabbay usize = asize = _IOC_SIZE(cmd); 1170e65e175bSOded Gabbay if (hl_size > asize) 1171e65e175bSOded Gabbay asize = hl_size; 1172e65e175bSOded Gabbay 1173e65e175bSOded Gabbay cmd = ioctl->cmd; 1174e65e175bSOded Gabbay 1175e65e175bSOded Gabbay if (cmd & (IOC_IN | IOC_OUT)) { 1176e65e175bSOded Gabbay if (asize <= sizeof(stack_kdata)) { 1177e65e175bSOded Gabbay kdata = stack_kdata; 1178e65e175bSOded Gabbay } else { 1179e65e175bSOded Gabbay kdata = kzalloc(asize, GFP_KERNEL); 1180e65e175bSOded Gabbay if (!kdata) { 1181e65e175bSOded Gabbay retcode = -ENOMEM; 1182e65e175bSOded Gabbay goto out_err; 1183e65e175bSOded Gabbay } 1184e65e175bSOded Gabbay } 1185e65e175bSOded Gabbay } 1186e65e175bSOded Gabbay 1187e65e175bSOded Gabbay if (cmd & IOC_IN) { 1188e65e175bSOded Gabbay if (copy_from_user(kdata, (void __user *)arg, usize)) { 1189e65e175bSOded Gabbay retcode = -EFAULT; 1190e65e175bSOded Gabbay goto out_err; 1191e65e175bSOded Gabbay } 1192e65e175bSOded Gabbay } 1193e65e175bSOded Gabbay 1194e65e175bSOded Gabbay retcode = func(hpriv, kdata); 1195e65e175bSOded Gabbay 1196e65e175bSOded Gabbay if ((cmd & IOC_OUT) && copy_to_user((void __user *)arg, kdata, usize)) 1197e65e175bSOded Gabbay retcode = -EFAULT; 1198e65e175bSOded Gabbay 1199e65e175bSOded Gabbay out_err: 1200e65e175bSOded Gabbay if (retcode) 1201e65e175bSOded Gabbay dev_dbg(dev, "error in ioctl: pid=%d, cmd=0x%02x, nr=0x%02x\n", 1202e65e175bSOded Gabbay task_pid_nr(current), cmd, nr); 1203e65e175bSOded Gabbay 1204e65e175bSOded Gabbay if (kdata != stack_kdata) 1205e65e175bSOded Gabbay kfree(kdata); 1206e65e175bSOded Gabbay 1207e65e175bSOded Gabbay return retcode; 1208e65e175bSOded Gabbay } 1209e65e175bSOded Gabbay 1210e65e175bSOded Gabbay long hl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) 1211e65e175bSOded Gabbay { 1212e65e175bSOded Gabbay struct hl_fpriv *hpriv = filep->private_data; 1213e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 1214e65e175bSOded Gabbay const struct hl_ioctl_desc *ioctl = NULL; 1215e65e175bSOded Gabbay unsigned int nr = _IOC_NR(cmd); 1216e65e175bSOded Gabbay 1217e65e175bSOded Gabbay if (!hdev) { 1218e65e175bSOded Gabbay pr_err_ratelimited("Sending ioctl after device was removed! Please close FD\n"); 1219e65e175bSOded Gabbay return -ENODEV; 1220e65e175bSOded Gabbay } 1221e65e175bSOded Gabbay 1222e65e175bSOded Gabbay if ((nr >= HL_COMMAND_START) && (nr < HL_COMMAND_END)) { 1223e65e175bSOded Gabbay ioctl = &hl_ioctls[nr]; 1224e65e175bSOded Gabbay } else { 1225e65e175bSOded Gabbay dev_err(hdev->dev, "invalid ioctl: pid=%d, nr=0x%02x\n", 1226e65e175bSOded Gabbay task_pid_nr(current), nr); 1227e65e175bSOded Gabbay return -ENOTTY; 1228e65e175bSOded Gabbay } 1229e65e175bSOded Gabbay 1230e65e175bSOded Gabbay return _hl_ioctl(filep, cmd, arg, ioctl, hdev->dev); 1231e65e175bSOded Gabbay } 1232e65e175bSOded Gabbay 1233e65e175bSOded Gabbay long hl_ioctl_control(struct file *filep, unsigned int cmd, unsigned long arg) 1234e65e175bSOded Gabbay { 1235e65e175bSOded Gabbay struct hl_fpriv *hpriv = filep->private_data; 1236e65e175bSOded Gabbay struct hl_device *hdev = hpriv->hdev; 1237e65e175bSOded Gabbay const struct hl_ioctl_desc *ioctl = NULL; 1238e65e175bSOded Gabbay unsigned int nr = _IOC_NR(cmd); 1239e65e175bSOded Gabbay 1240e65e175bSOded Gabbay if (!hdev) { 1241e65e175bSOded Gabbay pr_err_ratelimited("Sending ioctl after device was removed! Please close FD\n"); 1242e65e175bSOded Gabbay return -ENODEV; 1243e65e175bSOded Gabbay } 1244e65e175bSOded Gabbay 1245e65e175bSOded Gabbay if (nr == _IOC_NR(HL_IOCTL_INFO)) { 1246e65e175bSOded Gabbay ioctl = &hl_ioctls_control[nr]; 1247e65e175bSOded Gabbay } else { 1248e65e175bSOded Gabbay dev_err(hdev->dev_ctrl, "invalid ioctl: pid=%d, nr=0x%02x\n", 1249e65e175bSOded Gabbay task_pid_nr(current), nr); 1250e65e175bSOded Gabbay return -ENOTTY; 1251e65e175bSOded Gabbay } 1252e65e175bSOded Gabbay 1253e65e175bSOded Gabbay return _hl_ioctl(filep, cmd, arg, ioctl, hdev->dev_ctrl); 1254e65e175bSOded Gabbay } 1255