amdgpu_irq.c revision 1.1.1.1 1 /* $NetBSD: amdgpu_irq.c,v 1.1.1.1 2018/08/27 01:34:44 riastradh Exp $ */
2
3 /*
4 * Copyright 2008 Advanced Micro Devices, Inc.
5 * Copyright 2008 Red Hat Inc.
6 * Copyright 2009 Jerome Glisse.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * Authors: Dave Airlie
27 * Alex Deucher
28 * Jerome Glisse
29 */
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: amdgpu_irq.c,v 1.1.1.1 2018/08/27 01:34:44 riastradh Exp $");
32
33 #include <linux/irq.h>
34 #include <drm/drmP.h>
35 #include <drm/drm_crtc_helper.h>
36 #include <drm/amdgpu_drm.h>
37 #include "amdgpu.h"
38 #include "amdgpu_ih.h"
39 #include "atom.h"
40 #include "amdgpu_connectors.h"
41
42 #include <linux/pm_runtime.h>
43
44 #define AMDGPU_WAIT_IDLE_TIMEOUT 200
45
46 /*
47 * Handle hotplug events outside the interrupt handler proper.
48 */
49 /**
50 * amdgpu_hotplug_work_func - display hotplug work handler
51 *
52 * @work: work struct
53 *
54 * This is the hot plug event work handler (all asics).
55 * The work gets scheduled from the irq handler if there
56 * was a hot plug interrupt. It walks the connector table
57 * and calls the hotplug handler for each one, then sends
58 * a drm hotplug event to alert userspace.
59 */
60 static void amdgpu_hotplug_work_func(struct work_struct *work)
61 {
62 struct amdgpu_device *adev = container_of(work, struct amdgpu_device,
63 hotplug_work);
64 struct drm_device *dev = adev->ddev;
65 struct drm_mode_config *mode_config = &dev->mode_config;
66 struct drm_connector *connector;
67
68 mutex_lock(&mode_config->mutex);
69 if (mode_config->num_connector) {
70 list_for_each_entry(connector, &mode_config->connector_list, head)
71 amdgpu_connector_hotplug(connector);
72 }
73 mutex_unlock(&mode_config->mutex);
74 /* Just fire off a uevent and let userspace tell us what to do */
75 drm_helper_hpd_irq_event(dev);
76 }
77
78 /**
79 * amdgpu_irq_reset_work_func - execute gpu reset
80 *
81 * @work: work struct
82 *
83 * Execute scheduled gpu reset (cayman+).
84 * This function is called when the irq handler
85 * thinks we need a gpu reset.
86 */
87 static void amdgpu_irq_reset_work_func(struct work_struct *work)
88 {
89 struct amdgpu_device *adev = container_of(work, struct amdgpu_device,
90 reset_work);
91
92 amdgpu_gpu_reset(adev);
93 }
94
95 /* Disable *all* interrupts */
96 static void amdgpu_irq_disable_all(struct amdgpu_device *adev)
97 {
98 unsigned long irqflags;
99 unsigned i, j;
100 int r;
101
102 spin_lock_irqsave(&adev->irq.lock, irqflags);
103 for (i = 0; i < AMDGPU_MAX_IRQ_SRC_ID; ++i) {
104 struct amdgpu_irq_src *src = adev->irq.sources[i];
105
106 if (!src || !src->funcs->set || !src->num_types)
107 continue;
108
109 for (j = 0; j < src->num_types; ++j) {
110 atomic_set(&src->enabled_types[j], 0);
111 r = src->funcs->set(adev, src, j,
112 AMDGPU_IRQ_STATE_DISABLE);
113 if (r)
114 DRM_ERROR("error disabling interrupt (%d)\n",
115 r);
116 }
117 }
118 spin_unlock_irqrestore(&adev->irq.lock, irqflags);
119 }
120
121 /**
122 * amdgpu_irq_preinstall - drm irq preinstall callback
123 *
124 * @dev: drm dev pointer
125 *
126 * Gets the hw ready to enable irqs (all asics).
127 * This function disables all interrupt sources on the GPU.
128 */
129 void amdgpu_irq_preinstall(struct drm_device *dev)
130 {
131 struct amdgpu_device *adev = dev->dev_private;
132
133 /* Disable *all* interrupts */
134 amdgpu_irq_disable_all(adev);
135 /* Clear bits */
136 amdgpu_ih_process(adev);
137 }
138
139 /**
140 * amdgpu_irq_postinstall - drm irq preinstall callback
141 *
142 * @dev: drm dev pointer
143 *
144 * Handles stuff to be done after enabling irqs (all asics).
145 * Returns 0 on success.
146 */
147 int amdgpu_irq_postinstall(struct drm_device *dev)
148 {
149 dev->max_vblank_count = 0x00ffffff;
150 return 0;
151 }
152
153 /**
154 * amdgpu_irq_uninstall - drm irq uninstall callback
155 *
156 * @dev: drm dev pointer
157 *
158 * This function disables all interrupt sources on the GPU (all asics).
159 */
160 void amdgpu_irq_uninstall(struct drm_device *dev)
161 {
162 struct amdgpu_device *adev = dev->dev_private;
163
164 if (adev == NULL) {
165 return;
166 }
167 amdgpu_irq_disable_all(adev);
168 }
169
170 /**
171 * amdgpu_irq_handler - irq handler
172 *
173 * @int irq, void *arg: args
174 *
175 * This is the irq handler for the amdgpu driver (all asics).
176 */
177 irqreturn_t amdgpu_irq_handler(int irq, void *arg)
178 {
179 struct drm_device *dev = (struct drm_device *) arg;
180 struct amdgpu_device *adev = dev->dev_private;
181 irqreturn_t ret;
182
183 ret = amdgpu_ih_process(adev);
184 if (ret == IRQ_HANDLED)
185 pm_runtime_mark_last_busy(dev->dev);
186 return ret;
187 }
188
189 /**
190 * amdgpu_msi_ok - asic specific msi checks
191 *
192 * @adev: amdgpu device pointer
193 *
194 * Handles asic specific MSI checks to determine if
195 * MSIs should be enabled on a particular chip (all asics).
196 * Returns true if MSIs should be enabled, false if MSIs
197 * should not be enabled.
198 */
199 static bool amdgpu_msi_ok(struct amdgpu_device *adev)
200 {
201 /* force MSI on */
202 if (amdgpu_msi == 1)
203 return true;
204 else if (amdgpu_msi == 0)
205 return false;
206
207 return true;
208 }
209
210 /**
211 * amdgpu_irq_init - init driver interrupt info
212 *
213 * @adev: amdgpu device pointer
214 *
215 * Sets up the work irq handlers, vblank init, MSIs, etc. (all asics).
216 * Returns 0 for success, error for failure.
217 */
218 int amdgpu_irq_init(struct amdgpu_device *adev)
219 {
220 int r = 0;
221
222 spin_lock_init(&adev->irq.lock);
223 r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc);
224 if (r) {
225 return r;
226 }
227 /* enable msi */
228 adev->irq.msi_enabled = false;
229
230 if (amdgpu_msi_ok(adev)) {
231 int ret = pci_enable_msi(adev->pdev);
232 if (!ret) {
233 adev->irq.msi_enabled = true;
234 dev_info(adev->dev, "amdgpu: using MSI.\n");
235 }
236 }
237
238 INIT_WORK(&adev->hotplug_work, amdgpu_hotplug_work_func);
239 INIT_WORK(&adev->reset_work, amdgpu_irq_reset_work_func);
240
241 adev->irq.installed = true;
242 r = drm_irq_install(adev->ddev, adev->ddev->pdev->irq);
243 if (r) {
244 adev->irq.installed = false;
245 flush_work(&adev->hotplug_work);
246 return r;
247 }
248
249 DRM_INFO("amdgpu: irq initialized.\n");
250 return 0;
251 }
252
253 /**
254 * amdgpu_irq_fini - tear down driver interrupt info
255 *
256 * @adev: amdgpu device pointer
257 *
258 * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics).
259 */
260 void amdgpu_irq_fini(struct amdgpu_device *adev)
261 {
262 unsigned i;
263
264 drm_vblank_cleanup(adev->ddev);
265 if (adev->irq.installed) {
266 drm_irq_uninstall(adev->ddev);
267 adev->irq.installed = false;
268 if (adev->irq.msi_enabled)
269 pci_disable_msi(adev->pdev);
270 flush_work(&adev->hotplug_work);
271 }
272
273 for (i = 0; i < AMDGPU_MAX_IRQ_SRC_ID; ++i) {
274 struct amdgpu_irq_src *src = adev->irq.sources[i];
275
276 if (!src)
277 continue;
278
279 kfree(src->enabled_types);
280 src->enabled_types = NULL;
281 if (src->data) {
282 kfree(src->data);
283 kfree(src);
284 adev->irq.sources[i] = NULL;
285 }
286 }
287 }
288
289 /**
290 * amdgpu_irq_add_id - register irq source
291 *
292 * @adev: amdgpu device pointer
293 * @src_id: source id for this source
294 * @source: irq source
295 *
296 */
297 int amdgpu_irq_add_id(struct amdgpu_device *adev, unsigned src_id,
298 struct amdgpu_irq_src *source)
299 {
300 if (src_id >= AMDGPU_MAX_IRQ_SRC_ID)
301 return -EINVAL;
302
303 if (adev->irq.sources[src_id] != NULL)
304 return -EINVAL;
305
306 if (!source->funcs)
307 return -EINVAL;
308
309 if (source->num_types && !source->enabled_types) {
310 atomic_t *types;
311
312 types = kcalloc(source->num_types, sizeof(atomic_t),
313 GFP_KERNEL);
314 if (!types)
315 return -ENOMEM;
316
317 source->enabled_types = types;
318 }
319
320 adev->irq.sources[src_id] = source;
321 return 0;
322 }
323
324 /**
325 * amdgpu_irq_dispatch - dispatch irq to IP blocks
326 *
327 * @adev: amdgpu device pointer
328 * @entry: interrupt vector
329 *
330 * Dispatches the irq to the different IP blocks
331 */
332 void amdgpu_irq_dispatch(struct amdgpu_device *adev,
333 struct amdgpu_iv_entry *entry)
334 {
335 unsigned src_id = entry->src_id;
336 struct amdgpu_irq_src *src;
337 int r;
338
339 if (src_id >= AMDGPU_MAX_IRQ_SRC_ID) {
340 DRM_DEBUG("Invalid src_id in IV: %d\n", src_id);
341 return;
342 }
343
344 src = adev->irq.sources[src_id];
345 if (!src) {
346 DRM_DEBUG("Unhandled interrupt src_id: %d\n", src_id);
347 return;
348 }
349
350 r = src->funcs->process(adev, src, entry);
351 if (r)
352 DRM_ERROR("error processing interrupt (%d)\n", r);
353 }
354
355 /**
356 * amdgpu_irq_update - update hw interrupt state
357 *
358 * @adev: amdgpu device pointer
359 * @src: interrupt src you want to enable
360 * @type: type of interrupt you want to update
361 *
362 * Updates the interrupt state for a specific src (all asics).
363 */
364 int amdgpu_irq_update(struct amdgpu_device *adev,
365 struct amdgpu_irq_src *src, unsigned type)
366 {
367 unsigned long irqflags;
368 enum amdgpu_interrupt_state state;
369 int r;
370
371 spin_lock_irqsave(&adev->irq.lock, irqflags);
372
373 /* we need to determine after taking the lock, otherwise
374 we might disable just enabled interrupts again */
375 if (amdgpu_irq_enabled(adev, src, type))
376 state = AMDGPU_IRQ_STATE_ENABLE;
377 else
378 state = AMDGPU_IRQ_STATE_DISABLE;
379
380 r = src->funcs->set(adev, src, type, state);
381 spin_unlock_irqrestore(&adev->irq.lock, irqflags);
382 return r;
383 }
384
385 /**
386 * amdgpu_irq_get - enable interrupt
387 *
388 * @adev: amdgpu device pointer
389 * @src: interrupt src you want to enable
390 * @type: type of interrupt you want to enable
391 *
392 * Enables the interrupt type for a specific src (all asics).
393 */
394 int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
395 unsigned type)
396 {
397 if (!adev->ddev->irq_enabled)
398 return -ENOENT;
399
400 if (type >= src->num_types)
401 return -EINVAL;
402
403 if (!src->enabled_types || !src->funcs->set)
404 return -EINVAL;
405
406 if (atomic_inc_return(&src->enabled_types[type]) == 1)
407 return amdgpu_irq_update(adev, src, type);
408
409 return 0;
410 }
411
412 bool amdgpu_irq_get_delayed(struct amdgpu_device *adev,
413 struct amdgpu_irq_src *src,
414 unsigned type)
415 {
416 if ((type >= src->num_types) || !src->enabled_types)
417 return false;
418 return atomic_inc_return(&src->enabled_types[type]) == 1;
419 }
420
421 /**
422 * amdgpu_irq_put - disable interrupt
423 *
424 * @adev: amdgpu device pointer
425 * @src: interrupt src you want to disable
426 * @type: type of interrupt you want to disable
427 *
428 * Disables the interrupt type for a specific src (all asics).
429 */
430 int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
431 unsigned type)
432 {
433 if (!adev->ddev->irq_enabled)
434 return -ENOENT;
435
436 if (type >= src->num_types)
437 return -EINVAL;
438
439 if (!src->enabled_types || !src->funcs->set)
440 return -EINVAL;
441
442 if (atomic_dec_and_test(&src->enabled_types[type]))
443 return amdgpu_irq_update(adev, src, type);
444
445 return 0;
446 }
447
448 /**
449 * amdgpu_irq_enabled - test if irq is enabled or not
450 *
451 * @adev: amdgpu device pointer
452 * @idx: interrupt src you want to test
453 *
454 * Tests if the given interrupt source is enabled or not
455 */
456 bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
457 unsigned type)
458 {
459 if (!adev->ddev->irq_enabled)
460 return false;
461
462 if (type >= src->num_types)
463 return false;
464
465 if (!src->enabled_types || !src->funcs->set)
466 return false;
467
468 return !!atomic_read(&src->enabled_types[type]);
469 }
470