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 <linux/irq.h> 29 #include <drm/drmP.h> 30 #include <drm/drm_crtc_helper.h> 31 #include <drm/amdgpu_drm.h> 32 #include "amdgpu.h" 33 #include "amdgpu_ih.h" 34 #include "atom.h" 35 #include "amdgpu_connectors.h" 36 37 #include <linux/pm_runtime.h> 38 39 #define AMDGPU_WAIT_IDLE_TIMEOUT 200 40 41 /* 42 * Handle hotplug events outside the interrupt handler proper. 43 */ 44 /** 45 * amdgpu_hotplug_work_func - display hotplug work handler 46 * 47 * @work: work struct 48 * 49 * This is the hot plug event work handler (all asics). 50 * The work gets scheduled from the irq handler if there 51 * was a hot plug interrupt. It walks the connector table 52 * and calls the hotplug handler for each one, then sends 53 * a drm hotplug event to alert userspace. 54 */ 55 static void amdgpu_hotplug_work_func(struct work_struct *work) 56 { 57 struct amdgpu_device *adev = container_of(work, struct amdgpu_device, 58 hotplug_work); 59 struct drm_device *dev = adev->ddev; 60 struct drm_mode_config *mode_config = &dev->mode_config; 61 struct drm_connector *connector; 62 63 mutex_lock(&mode_config->mutex); 64 list_for_each_entry(connector, &mode_config->connector_list, head) 65 amdgpu_connector_hotplug(connector); 66 mutex_unlock(&mode_config->mutex); 67 /* Just fire off a uevent and let userspace tell us what to do */ 68 drm_helper_hpd_irq_event(dev); 69 } 70 71 /** 72 * amdgpu_irq_reset_work_func - execute gpu reset 73 * 74 * @work: work struct 75 * 76 * Execute scheduled gpu reset (cayman+). 77 * This function is called when the irq handler 78 * thinks we need a gpu reset. 79 */ 80 static void amdgpu_irq_reset_work_func(struct work_struct *work) 81 { 82 struct amdgpu_device *adev = container_of(work, struct amdgpu_device, 83 reset_work); 84 85 amdgpu_gpu_reset(adev); 86 } 87 88 /* Disable *all* interrupts */ 89 static void amdgpu_irq_disable_all(struct amdgpu_device *adev) 90 { 91 unsigned long irqflags; 92 unsigned i, j; 93 int r; 94 95 spin_lock_irqsave(&adev->irq.lock, irqflags); 96 for (i = 0; i < AMDGPU_MAX_IRQ_SRC_ID; ++i) { 97 struct amdgpu_irq_src *src = adev->irq.sources[i]; 98 99 if (!src || !src->funcs->set || !src->num_types) 100 continue; 101 102 for (j = 0; j < src->num_types; ++j) { 103 atomic_set(&src->enabled_types[j], 0); 104 r = src->funcs->set(adev, src, j, 105 AMDGPU_IRQ_STATE_DISABLE); 106 if (r) 107 DRM_ERROR("error disabling interrupt (%d)\n", 108 r); 109 } 110 } 111 spin_unlock_irqrestore(&adev->irq.lock, irqflags); 112 } 113 114 /** 115 * amdgpu_irq_preinstall - drm irq preinstall callback 116 * 117 * @dev: drm dev pointer 118 * 119 * Gets the hw ready to enable irqs (all asics). 120 * This function disables all interrupt sources on the GPU. 121 */ 122 void amdgpu_irq_preinstall(struct drm_device *dev) 123 { 124 struct amdgpu_device *adev = dev->dev_private; 125 126 /* Disable *all* interrupts */ 127 amdgpu_irq_disable_all(adev); 128 /* Clear bits */ 129 amdgpu_ih_process(adev); 130 } 131 132 /** 133 * amdgpu_irq_postinstall - drm irq preinstall callback 134 * 135 * @dev: drm dev pointer 136 * 137 * Handles stuff to be done after enabling irqs (all asics). 138 * Returns 0 on success. 139 */ 140 int amdgpu_irq_postinstall(struct drm_device *dev) 141 { 142 dev->max_vblank_count = 0x00ffffff; 143 return 0; 144 } 145 146 /** 147 * amdgpu_irq_uninstall - drm irq uninstall callback 148 * 149 * @dev: drm dev pointer 150 * 151 * This function disables all interrupt sources on the GPU (all asics). 152 */ 153 void amdgpu_irq_uninstall(struct drm_device *dev) 154 { 155 struct amdgpu_device *adev = dev->dev_private; 156 157 if (adev == NULL) { 158 return; 159 } 160 amdgpu_irq_disable_all(adev); 161 } 162 163 /** 164 * amdgpu_irq_handler - irq handler 165 * 166 * @int irq, void *arg: args 167 * 168 * This is the irq handler for the amdgpu driver (all asics). 169 */ 170 irqreturn_t amdgpu_irq_handler(int irq, void *arg) 171 { 172 struct drm_device *dev = (struct drm_device *) arg; 173 struct amdgpu_device *adev = dev->dev_private; 174 irqreturn_t ret; 175 176 ret = amdgpu_ih_process(adev); 177 if (ret == IRQ_HANDLED) 178 pm_runtime_mark_last_busy(dev->dev); 179 return ret; 180 } 181 182 /** 183 * amdgpu_msi_ok - asic specific msi checks 184 * 185 * @adev: amdgpu device pointer 186 * 187 * Handles asic specific MSI checks to determine if 188 * MSIs should be enabled on a particular chip (all asics). 189 * Returns true if MSIs should be enabled, false if MSIs 190 * should not be enabled. 191 */ 192 static bool amdgpu_msi_ok(struct amdgpu_device *adev) 193 { 194 /* force MSI on */ 195 if (amdgpu_msi == 1) 196 return true; 197 else if (amdgpu_msi == 0) 198 return false; 199 200 return true; 201 } 202 203 /** 204 * amdgpu_irq_init - init driver interrupt info 205 * 206 * @adev: amdgpu device pointer 207 * 208 * Sets up the work irq handlers, vblank init, MSIs, etc. (all asics). 209 * Returns 0 for success, error for failure. 210 */ 211 int amdgpu_irq_init(struct amdgpu_device *adev) 212 { 213 int r = 0; 214 215 spin_lock_init(&adev->irq.lock); 216 r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc); 217 if (r) { 218 return r; 219 } 220 221 /* enable msi */ 222 adev->irq.msi_enabled = false; 223 224 if (amdgpu_msi_ok(adev)) { 225 int ret = pci_enable_msi(adev->pdev); 226 if (!ret) { 227 adev->irq.msi_enabled = true; 228 dev_info(adev->dev, "amdgpu: using MSI.\n"); 229 } 230 } 231 232 INIT_WORK(&adev->hotplug_work, amdgpu_hotplug_work_func); 233 INIT_WORK(&adev->reset_work, amdgpu_irq_reset_work_func); 234 235 adev->irq.installed = true; 236 r = drm_irq_install(adev->ddev, adev->ddev->pdev->irq); 237 if (r) { 238 adev->irq.installed = false; 239 flush_work(&adev->hotplug_work); 240 cancel_work_sync(&adev->reset_work); 241 return r; 242 } 243 244 DRM_INFO("amdgpu: irq initialized.\n"); 245 return 0; 246 } 247 248 /** 249 * amdgpu_irq_fini - tear down driver interrupt info 250 * 251 * @adev: amdgpu device pointer 252 * 253 * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics). 254 */ 255 void amdgpu_irq_fini(struct amdgpu_device *adev) 256 { 257 unsigned i; 258 259 drm_vblank_cleanup(adev->ddev); 260 if (adev->irq.installed) { 261 drm_irq_uninstall(adev->ddev); 262 adev->irq.installed = false; 263 if (adev->irq.msi_enabled) 264 pci_disable_msi(adev->pdev); 265 flush_work(&adev->hotplug_work); 266 cancel_work_sync(&adev->reset_work); 267 } 268 269 for (i = 0; i < AMDGPU_MAX_IRQ_SRC_ID; ++i) { 270 struct amdgpu_irq_src *src = adev->irq.sources[i]; 271 272 if (!src) 273 continue; 274 275 kfree(src->enabled_types); 276 src->enabled_types = NULL; 277 if (src->data) { 278 kfree(src->data); 279 kfree(src); 280 adev->irq.sources[i] = NULL; 281 } 282 } 283 } 284 285 /** 286 * amdgpu_irq_add_id - register irq source 287 * 288 * @adev: amdgpu device pointer 289 * @src_id: source id for this source 290 * @source: irq source 291 * 292 */ 293 int amdgpu_irq_add_id(struct amdgpu_device *adev, unsigned src_id, 294 struct amdgpu_irq_src *source) 295 { 296 if (src_id >= AMDGPU_MAX_IRQ_SRC_ID) 297 return -EINVAL; 298 299 if (adev->irq.sources[src_id] != NULL) 300 return -EINVAL; 301 302 if (!source->funcs) 303 return -EINVAL; 304 305 if (source->num_types && !source->enabled_types) { 306 atomic_t *types; 307 308 types = kcalloc(source->num_types, sizeof(atomic_t), 309 GFP_KERNEL); 310 if (!types) 311 return -ENOMEM; 312 313 source->enabled_types = types; 314 } 315 316 adev->irq.sources[src_id] = source; 317 318 return 0; 319 } 320 321 /** 322 * amdgpu_irq_dispatch - dispatch irq to IP blocks 323 * 324 * @adev: amdgpu device pointer 325 * @entry: interrupt vector 326 * 327 * Dispatches the irq to the different IP blocks 328 */ 329 void amdgpu_irq_dispatch(struct amdgpu_device *adev, 330 struct amdgpu_iv_entry *entry) 331 { 332 unsigned src_id = entry->src_id; 333 struct amdgpu_irq_src *src; 334 int r; 335 336 if (src_id >= AMDGPU_MAX_IRQ_SRC_ID) { 337 DRM_DEBUG("Invalid src_id in IV: %d\n", src_id); 338 return; 339 } 340 341 if (adev->irq.virq[src_id]) { 342 generic_handle_irq(irq_find_mapping(adev->irq.domain, src_id)); 343 } else { 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 /** 357 * amdgpu_irq_update - update hw interrupt state 358 * 359 * @adev: amdgpu device pointer 360 * @src: interrupt src you want to enable 361 * @type: type of interrupt you want to update 362 * 363 * Updates the interrupt state for a specific src (all asics). 364 */ 365 int amdgpu_irq_update(struct amdgpu_device *adev, 366 struct amdgpu_irq_src *src, unsigned type) 367 { 368 unsigned long irqflags; 369 enum amdgpu_interrupt_state state; 370 int r; 371 372 spin_lock_irqsave(&adev->irq.lock, irqflags); 373 374 /* we need to determine after taking the lock, otherwise 375 we might disable just enabled interrupts again */ 376 if (amdgpu_irq_enabled(adev, src, type)) 377 state = AMDGPU_IRQ_STATE_ENABLE; 378 else 379 state = AMDGPU_IRQ_STATE_DISABLE; 380 381 r = src->funcs->set(adev, src, type, state); 382 spin_unlock_irqrestore(&adev->irq.lock, irqflags); 383 return r; 384 } 385 386 void amdgpu_irq_gpu_reset_resume_helper(struct amdgpu_device *adev) 387 { 388 int i, j; 389 for (i = 0; i < AMDGPU_MAX_IRQ_SRC_ID; i++) { 390 struct amdgpu_irq_src *src = adev->irq.sources[i]; 391 if (!src) 392 continue; 393 for (j = 0; j < src->num_types; j++) 394 amdgpu_irq_update(adev, src, j); 395 } 396 } 397 398 /** 399 * amdgpu_irq_get - enable interrupt 400 * 401 * @adev: amdgpu device pointer 402 * @src: interrupt src you want to enable 403 * @type: type of interrupt you want to enable 404 * 405 * Enables the interrupt type for a specific src (all asics). 406 */ 407 int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src, 408 unsigned type) 409 { 410 if (!adev->ddev->irq_enabled) 411 return -ENOENT; 412 413 if (type >= src->num_types) 414 return -EINVAL; 415 416 if (!src->enabled_types || !src->funcs->set) 417 return -EINVAL; 418 419 if (atomic_inc_return(&src->enabled_types[type]) == 1) 420 return amdgpu_irq_update(adev, src, type); 421 422 return 0; 423 } 424 425 /** 426 * amdgpu_irq_put - disable interrupt 427 * 428 * @adev: amdgpu device pointer 429 * @src: interrupt src you want to disable 430 * @type: type of interrupt you want to disable 431 * 432 * Disables the interrupt type for a specific src (all asics). 433 */ 434 int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src, 435 unsigned type) 436 { 437 if (!adev->ddev->irq_enabled) 438 return -ENOENT; 439 440 if (type >= src->num_types) 441 return -EINVAL; 442 443 if (!src->enabled_types || !src->funcs->set) 444 return -EINVAL; 445 446 if (atomic_dec_and_test(&src->enabled_types[type])) 447 return amdgpu_irq_update(adev, src, type); 448 449 return 0; 450 } 451 452 /** 453 * amdgpu_irq_enabled - test if irq is enabled or not 454 * 455 * @adev: amdgpu device pointer 456 * @idx: interrupt src you want to test 457 * 458 * Tests if the given interrupt source is enabled or not 459 */ 460 bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src, 461 unsigned type) 462 { 463 if (!adev->ddev->irq_enabled) 464 return false; 465 466 if (type >= src->num_types) 467 return false; 468 469 if (!src->enabled_types || !src->funcs->set) 470 return false; 471 472 return !!atomic_read(&src->enabled_types[type]); 473 } 474 475 /* gen irq */ 476 static void amdgpu_irq_mask(struct irq_data *irqd) 477 { 478 /* XXX */ 479 } 480 481 static void amdgpu_irq_unmask(struct irq_data *irqd) 482 { 483 /* XXX */ 484 } 485 486 static struct irq_chip amdgpu_irq_chip = { 487 .name = "amdgpu-ih", 488 .irq_mask = amdgpu_irq_mask, 489 .irq_unmask = amdgpu_irq_unmask, 490 }; 491 492 static int amdgpu_irqdomain_map(struct irq_domain *d, 493 unsigned int irq, irq_hw_number_t hwirq) 494 { 495 if (hwirq >= AMDGPU_MAX_IRQ_SRC_ID) 496 return -EPERM; 497 498 irq_set_chip_and_handler(irq, 499 &amdgpu_irq_chip, handle_simple_irq); 500 return 0; 501 } 502 503 static const struct irq_domain_ops amdgpu_hw_irqdomain_ops = { 504 .map = amdgpu_irqdomain_map, 505 }; 506 507 /** 508 * amdgpu_irq_add_domain - create a linear irq domain 509 * 510 * @adev: amdgpu device pointer 511 * 512 * Create an irq domain for GPU interrupt sources 513 * that may be driven by another driver (e.g., ACP). 514 */ 515 int amdgpu_irq_add_domain(struct amdgpu_device *adev) 516 { 517 adev->irq.domain = irq_domain_add_linear(NULL, AMDGPU_MAX_IRQ_SRC_ID, 518 &amdgpu_hw_irqdomain_ops, adev); 519 if (!adev->irq.domain) { 520 DRM_ERROR("GPU irq add domain failed\n"); 521 return -ENODEV; 522 } 523 524 return 0; 525 } 526 527 /** 528 * amdgpu_irq_remove_domain - remove the irq domain 529 * 530 * @adev: amdgpu device pointer 531 * 532 * Remove the irq domain for GPU interrupt sources 533 * that may be driven by another driver (e.g., ACP). 534 */ 535 void amdgpu_irq_remove_domain(struct amdgpu_device *adev) 536 { 537 if (adev->irq.domain) { 538 irq_domain_remove(adev->irq.domain); 539 adev->irq.domain = NULL; 540 } 541 } 542 543 /** 544 * amdgpu_irq_create_mapping - create a mapping between a domain irq and a 545 * Linux irq 546 * 547 * @adev: amdgpu device pointer 548 * @src_id: IH source id 549 * 550 * Create a mapping between a domain irq (GPU IH src id) and a Linux irq 551 * Use this for components that generate a GPU interrupt, but are driven 552 * by a different driver (e.g., ACP). 553 * Returns the Linux irq. 554 */ 555 unsigned amdgpu_irq_create_mapping(struct amdgpu_device *adev, unsigned src_id) 556 { 557 adev->irq.virq[src_id] = irq_create_mapping(adev->irq.domain, src_id); 558 559 return adev->irq.virq[src_id]; 560 } 561