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