These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / amd / amdkfd / kfd_dbgmgr.c
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
37 static DEFINE_MUTEX(kfd_dbgmgr_mutex);
38
39 struct mutex *kfd_get_dbgmgr_mutex(void)
40 {
41         return &kfd_dbgmgr_mutex;
42 }
43
44
45 static 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
56 void kfd_dbgmgr_destroy(struct kfd_dbgmgr *pmgr)
57 {
58         if (pmgr != NULL) {
59                 kfd_dbgmgr_uninitialize(pmgr);
60                 kfree(pmgr);
61         }
62 }
63
64 bool 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
97 long 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
119 long 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
137 long 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
152 long 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