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