linux/drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.c
<<
>>
Prefs
   1/*
   2 * Copyright 2014 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#include <linux/types.h>
  24#include <linux/kernel.h>
  25#include <linux/log2.h>
  26#include <linux/sched.h>
  27#include <linux/slab.h>
  28#include <linux/device.h>
  29
  30#include "kfd_priv.h"
  31#include "cik_regs.h"
  32#include "kfd_pm4_headers.h"
  33#include "kfd_pm4_headers_diq.h"
  34#include "kfd_dbgmgr.h"
  35#include "kfd_dbgdev.h"
  36#include "kfd_device_queue_manager.h"
  37
  38static DEFINE_MUTEX(kfd_dbgmgr_mutex);
  39
  40struct mutex *kfd_get_dbgmgr_mutex(void)
  41{
  42        return &kfd_dbgmgr_mutex;
  43}
  44
  45
  46static void kfd_dbgmgr_uninitialize(struct kfd_dbgmgr *pmgr)
  47{
  48        kfree(pmgr->dbgdev);
  49
  50        pmgr->dbgdev = NULL;
  51        pmgr->pasid = 0;
  52        pmgr->dev = NULL;
  53}
  54
  55void kfd_dbgmgr_destroy(struct kfd_dbgmgr *pmgr)
  56{
  57        if (pmgr) {
  58                kfd_dbgmgr_uninitialize(pmgr);
  59                kfree(pmgr);
  60        }
  61}
  62
  63bool kfd_dbgmgr_create(struct kfd_dbgmgr **ppmgr, struct kfd_dev *pdev)
  64{
  65        enum DBGDEV_TYPE type = DBGDEV_TYPE_DIQ;
  66        struct kfd_dbgmgr *new_buff;
  67
  68        if (WARN_ON(!pdev->init_complete))
  69                return false;
  70
  71        new_buff = kfd_alloc_struct(new_buff);
  72        if (!new_buff) {
  73                pr_err("Failed to allocate dbgmgr instance\n");
  74                return false;
  75        }
  76
  77        new_buff->pasid = 0;
  78        new_buff->dev = pdev;
  79        new_buff->dbgdev = kfd_alloc_struct(new_buff->dbgdev);
  80        if (!new_buff->dbgdev) {
  81                pr_err("Failed to allocate dbgdev instance\n");
  82                kfree(new_buff);
  83                return false;
  84        }
  85
  86        /* get actual type of DBGDevice cpsch or not */
  87        if (pdev->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS)
  88                type = DBGDEV_TYPE_NODIQ;
  89
  90        kfd_dbgdev_init(new_buff->dbgdev, pdev, type);
  91        *ppmgr = new_buff;
  92
  93        return true;
  94}
  95
  96long kfd_dbgmgr_register(struct kfd_dbgmgr *pmgr, struct kfd_process *p)
  97{
  98        if (pmgr->pasid != 0) {
  99                pr_debug("H/W debugger is already active using pasid 0x%x\n",
 100                                pmgr->pasid);
 101                return -EBUSY;
 102        }
 103
 104        /* remember pasid */
 105        pmgr->pasid = p->pasid;
 106
 107        /* provide the pqm for diq generation */
 108        pmgr->dbgdev->pqm = &p->pqm;
 109
 110        /* activate the actual registering */
 111        pmgr->dbgdev->dbgdev_register(pmgr->dbgdev);
 112
 113        return 0;
 114}
 115
 116long kfd_dbgmgr_unregister(struct kfd_dbgmgr *pmgr, struct kfd_process *p)
 117{
 118        /* Is the requests coming from the already registered process? */
 119        if (pmgr->pasid != p->pasid) {
 120                pr_debug("H/W debugger is not registered by calling pasid 0x%x\n",
 121                                p->pasid);
 122                return -EINVAL;
 123        }
 124
 125        pmgr->dbgdev->dbgdev_unregister(pmgr->dbgdev);
 126
 127        pmgr->pasid = 0;
 128
 129        return 0;
 130}
 131
 132long kfd_dbgmgr_wave_control(struct kfd_dbgmgr *pmgr,
 133                                struct dbg_wave_control_info *wac_info)
 134{
 135        /* Is the requests coming from the already registered process? */
 136        if (pmgr->pasid != wac_info->process->pasid) {
 137                pr_debug("H/W debugger support was not registered for requester pasid 0x%x\n",
 138                                wac_info->process->pasid);
 139                return -EINVAL;
 140        }
 141
 142        return (long) pmgr->dbgdev->dbgdev_wave_control(pmgr->dbgdev, wac_info);
 143}
 144
 145long kfd_dbgmgr_address_watch(struct kfd_dbgmgr *pmgr,
 146                                struct dbg_address_watch_info *adw_info)
 147{
 148        /* Is the requests coming from the already registered process? */
 149        if (pmgr->pasid != adw_info->process->pasid) {
 150                pr_debug("H/W debugger support was not registered for requester pasid 0x%x\n",
 151                                adw_info->process->pasid);
 152                return -EINVAL;
 153        }
 154
 155        return (long) pmgr->dbgdev->dbgdev_address_watch(pmgr->dbgdev,
 156                                                        adw_info);
 157}
 158
 159