diff options
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_bios.c | 14 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_kms.c | 55 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_object.c | 40 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_pm.c | 42 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_vce.c | 130 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_vm.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/sid.h | 4 |
9 files changed, 216 insertions, 79 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 68528619834a..8149e7cf4303 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -1642,6 +1642,7 @@ struct radeon_vce { | |||
| 1642 | unsigned fb_version; | 1642 | unsigned fb_version; |
| 1643 | atomic_t handles[RADEON_MAX_VCE_HANDLES]; | 1643 | atomic_t handles[RADEON_MAX_VCE_HANDLES]; |
| 1644 | struct drm_file *filp[RADEON_MAX_VCE_HANDLES]; | 1644 | struct drm_file *filp[RADEON_MAX_VCE_HANDLES]; |
| 1645 | unsigned img_size[RADEON_MAX_VCE_HANDLES]; | ||
| 1645 | struct delayed_work idle_work; | 1646 | struct delayed_work idle_work; |
| 1646 | }; | 1647 | }; |
| 1647 | 1648 | ||
| @@ -1655,7 +1656,7 @@ int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring, | |||
| 1655 | uint32_t handle, struct radeon_fence **fence); | 1656 | uint32_t handle, struct radeon_fence **fence); |
| 1656 | void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp); | 1657 | void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp); |
| 1657 | void radeon_vce_note_usage(struct radeon_device *rdev); | 1658 | void radeon_vce_note_usage(struct radeon_device *rdev); |
| 1658 | int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi); | 1659 | int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi, unsigned size); |
| 1659 | int radeon_vce_cs_parse(struct radeon_cs_parser *p); | 1660 | int radeon_vce_cs_parse(struct radeon_cs_parser *p); |
| 1660 | bool radeon_vce_semaphore_emit(struct radeon_device *rdev, | 1661 | bool radeon_vce_semaphore_emit(struct radeon_device *rdev, |
| 1661 | struct radeon_ring *ring, | 1662 | struct radeon_ring *ring, |
| @@ -2640,7 +2641,8 @@ void r100_pll_errata_after_index(struct radeon_device *rdev); | |||
| 2640 | #define ASIC_IS_DCE8(rdev) ((rdev->family >= CHIP_BONAIRE)) | 2641 | #define ASIC_IS_DCE8(rdev) ((rdev->family >= CHIP_BONAIRE)) |
| 2641 | #define ASIC_IS_DCE81(rdev) ((rdev->family == CHIP_KAVERI)) | 2642 | #define ASIC_IS_DCE81(rdev) ((rdev->family == CHIP_KAVERI)) |
| 2642 | #define ASIC_IS_DCE82(rdev) ((rdev->family == CHIP_BONAIRE)) | 2643 | #define ASIC_IS_DCE82(rdev) ((rdev->family == CHIP_BONAIRE)) |
| 2643 | #define ASIC_IS_DCE83(rdev) ((rdev->family == CHIP_KABINI)) | 2644 | #define ASIC_IS_DCE83(rdev) ((rdev->family == CHIP_KABINI) || \ |
| 2645 | (rdev->family == CHIP_MULLINS)) | ||
| 2644 | 2646 | ||
| 2645 | #define ASIC_IS_LOMBOK(rdev) ((rdev->ddev->pdev->device == 0x6849) || \ | 2647 | #define ASIC_IS_LOMBOK(rdev) ((rdev->ddev->pdev->device == 0x6849) || \ |
| 2646 | (rdev->ddev->pdev->device == 0x6850) || \ | 2648 | (rdev->ddev->pdev->device == 0x6850) || \ |
diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index b3633d9a5317..9ab30976287d 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c | |||
| @@ -196,6 +196,20 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) | |||
| 196 | } | 196 | } |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | if (!found) { | ||
| 200 | while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { | ||
| 201 | dhandle = ACPI_HANDLE(&pdev->dev); | ||
| 202 | if (!dhandle) | ||
| 203 | continue; | ||
| 204 | |||
| 205 | status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); | ||
| 206 | if (!ACPI_FAILURE(status)) { | ||
| 207 | found = true; | ||
| 208 | break; | ||
| 209 | } | ||
| 210 | } | ||
| 211 | } | ||
| 212 | |||
| 199 | if (!found) | 213 | if (!found) |
| 200 | return false; | 214 | return false; |
| 201 | 215 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 408b6ac53f0b..f00dbbf4d806 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
| @@ -999,7 +999,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, | |||
| 999 | 999 | ||
| 1000 | /* avoid high jitter with small fractional dividers */ | 1000 | /* avoid high jitter with small fractional dividers */ |
| 1001 | if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV && (fb_div % 10)) { | 1001 | if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV && (fb_div % 10)) { |
| 1002 | fb_div_min = max(fb_div_min, (9 - (fb_div % 10)) * 20 + 60); | 1002 | fb_div_min = max(fb_div_min, (9 - (fb_div % 10)) * 20 + 50); |
| 1003 | if (fb_div < fb_div_min) { | 1003 | if (fb_div < fb_div_min) { |
| 1004 | unsigned tmp = DIV_ROUND_UP(fb_div_min, fb_div); | 1004 | unsigned tmp = DIV_ROUND_UP(fb_div_min, fb_div); |
| 1005 | fb_div *= tmp; | 1005 | fb_div *= tmp; |
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 0cc47f12d995..eaaedba04675 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c | |||
| @@ -577,28 +577,29 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) | |||
| 577 | return r; | 577 | return r; |
| 578 | } | 578 | } |
| 579 | 579 | ||
| 580 | r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); | 580 | if (rdev->accel_working) { |
| 581 | if (r) { | 581 | r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); |
| 582 | radeon_vm_fini(rdev, &fpriv->vm); | 582 | if (r) { |
| 583 | kfree(fpriv); | 583 | radeon_vm_fini(rdev, &fpriv->vm); |
| 584 | return r; | 584 | kfree(fpriv); |
| 585 | } | 585 | return r; |
| 586 | } | ||
| 586 | 587 | ||
| 587 | /* map the ib pool buffer read only into | 588 | /* map the ib pool buffer read only into |
| 588 | * virtual address space */ | 589 | * virtual address space */ |
| 589 | bo_va = radeon_vm_bo_add(rdev, &fpriv->vm, | 590 | bo_va = radeon_vm_bo_add(rdev, &fpriv->vm, |
| 590 | rdev->ring_tmp_bo.bo); | 591 | rdev->ring_tmp_bo.bo); |
| 591 | r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET, | 592 | r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET, |
| 592 | RADEON_VM_PAGE_READABLE | | 593 | RADEON_VM_PAGE_READABLE | |
| 593 | RADEON_VM_PAGE_SNOOPED); | 594 | RADEON_VM_PAGE_SNOOPED); |
| 594 | 595 | ||
| 595 | radeon_bo_unreserve(rdev->ring_tmp_bo.bo); | 596 | radeon_bo_unreserve(rdev->ring_tmp_bo.bo); |
| 596 | if (r) { | 597 | if (r) { |
| 597 | radeon_vm_fini(rdev, &fpriv->vm); | 598 | radeon_vm_fini(rdev, &fpriv->vm); |
| 598 | kfree(fpriv); | 599 | kfree(fpriv); |
| 599 | return r; | 600 | return r; |
| 601 | } | ||
| 600 | } | 602 | } |
| 601 | |||
| 602 | file_priv->driver_priv = fpriv; | 603 | file_priv->driver_priv = fpriv; |
| 603 | } | 604 | } |
| 604 | 605 | ||
| @@ -626,13 +627,15 @@ void radeon_driver_postclose_kms(struct drm_device *dev, | |||
| 626 | struct radeon_bo_va *bo_va; | 627 | struct radeon_bo_va *bo_va; |
| 627 | int r; | 628 | int r; |
| 628 | 629 | ||
| 629 | r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); | 630 | if (rdev->accel_working) { |
| 630 | if (!r) { | 631 | r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); |
| 631 | bo_va = radeon_vm_bo_find(&fpriv->vm, | 632 | if (!r) { |
| 632 | rdev->ring_tmp_bo.bo); | 633 | bo_va = radeon_vm_bo_find(&fpriv->vm, |
| 633 | if (bo_va) | 634 | rdev->ring_tmp_bo.bo); |
| 634 | radeon_vm_bo_rmv(rdev, bo_va); | 635 | if (bo_va) |
| 635 | radeon_bo_unreserve(rdev->ring_tmp_bo.bo); | 636 | radeon_vm_bo_rmv(rdev, bo_va); |
| 637 | radeon_bo_unreserve(rdev->ring_tmp_bo.bo); | ||
| 638 | } | ||
| 636 | } | 639 | } |
| 637 | 640 | ||
| 638 | radeon_vm_fini(rdev, &fpriv->vm); | 641 | radeon_vm_fini(rdev, &fpriv->vm); |
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 19bec0dbfa38..4faa4d6f9bb4 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
| @@ -458,7 +458,7 @@ int radeon_bo_list_validate(struct radeon_device *rdev, | |||
| 458 | * into account. We don't want to disallow buffer moves | 458 | * into account. We don't want to disallow buffer moves |
| 459 | * completely. | 459 | * completely. |
| 460 | */ | 460 | */ |
| 461 | if (current_domain != RADEON_GEM_DOMAIN_CPU && | 461 | if ((lobj->alt_domain & current_domain) != 0 && |
| 462 | (domain & current_domain) == 0 && /* will be moved */ | 462 | (domain & current_domain) == 0 && /* will be moved */ |
| 463 | bytes_moved > bytes_moved_threshold) { | 463 | bytes_moved > bytes_moved_threshold) { |
| 464 | /* don't move it */ | 464 | /* don't move it */ |
| @@ -699,22 +699,30 @@ int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) | |||
| 699 | rbo = container_of(bo, struct radeon_bo, tbo); | 699 | rbo = container_of(bo, struct radeon_bo, tbo); |
| 700 | radeon_bo_check_tiling(rbo, 0, 0); | 700 | radeon_bo_check_tiling(rbo, 0, 0); |
| 701 | rdev = rbo->rdev; | 701 | rdev = rbo->rdev; |
| 702 | if (bo->mem.mem_type == TTM_PL_VRAM) { | 702 | if (bo->mem.mem_type != TTM_PL_VRAM) |
| 703 | size = bo->mem.num_pages << PAGE_SHIFT; | 703 | return 0; |
| 704 | offset = bo->mem.start << PAGE_SHIFT; | 704 | |
| 705 | if ((offset + size) > rdev->mc.visible_vram_size) { | 705 | size = bo->mem.num_pages << PAGE_SHIFT; |
| 706 | /* hurrah the memory is not visible ! */ | 706 | offset = bo->mem.start << PAGE_SHIFT; |
| 707 | radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM); | 707 | if ((offset + size) <= rdev->mc.visible_vram_size) |
| 708 | rbo->placement.lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT; | 708 | return 0; |
| 709 | r = ttm_bo_validate(bo, &rbo->placement, false, false); | 709 | |
| 710 | if (unlikely(r != 0)) | 710 | /* hurrah the memory is not visible ! */ |
| 711 | return r; | 711 | radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM); |
| 712 | offset = bo->mem.start << PAGE_SHIFT; | 712 | rbo->placement.lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT; |
| 713 | /* this should not happen */ | 713 | r = ttm_bo_validate(bo, &rbo->placement, false, false); |
| 714 | if ((offset + size) > rdev->mc.visible_vram_size) | 714 | if (unlikely(r == -ENOMEM)) { |
| 715 | return -EINVAL; | 715 | radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); |
| 716 | } | 716 | return ttm_bo_validate(bo, &rbo->placement, false, false); |
| 717 | } else if (unlikely(r != 0)) { | ||
| 718 | return r; | ||
| 717 | } | 719 | } |
| 720 | |||
| 721 | offset = bo->mem.start << PAGE_SHIFT; | ||
| 722 | /* this should never happen */ | ||
| 723 | if ((offset + size) > rdev->mc.visible_vram_size) | ||
| 724 | return -EINVAL; | ||
| 725 | |||
| 718 | return 0; | 726 | return 0; |
| 719 | } | 727 | } |
| 720 | 728 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index f30b8426eee2..53d6e1bb48dc 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
| @@ -361,6 +361,11 @@ static ssize_t radeon_set_pm_profile(struct device *dev, | |||
| 361 | struct drm_device *ddev = dev_get_drvdata(dev); | 361 | struct drm_device *ddev = dev_get_drvdata(dev); |
| 362 | struct radeon_device *rdev = ddev->dev_private; | 362 | struct radeon_device *rdev = ddev->dev_private; |
| 363 | 363 | ||
| 364 | /* Can't set profile when the card is off */ | ||
| 365 | if ((rdev->flags & RADEON_IS_PX) && | ||
| 366 | (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) | ||
| 367 | return -EINVAL; | ||
| 368 | |||
| 364 | mutex_lock(&rdev->pm.mutex); | 369 | mutex_lock(&rdev->pm.mutex); |
| 365 | if (rdev->pm.pm_method == PM_METHOD_PROFILE) { | 370 | if (rdev->pm.pm_method == PM_METHOD_PROFILE) { |
| 366 | if (strncmp("default", buf, strlen("default")) == 0) | 371 | if (strncmp("default", buf, strlen("default")) == 0) |
| @@ -409,6 +414,13 @@ static ssize_t radeon_set_pm_method(struct device *dev, | |||
| 409 | struct drm_device *ddev = dev_get_drvdata(dev); | 414 | struct drm_device *ddev = dev_get_drvdata(dev); |
| 410 | struct radeon_device *rdev = ddev->dev_private; | 415 | struct radeon_device *rdev = ddev->dev_private; |
| 411 | 416 | ||
| 417 | /* Can't set method when the card is off */ | ||
| 418 | if ((rdev->flags & RADEON_IS_PX) && | ||
| 419 | (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) { | ||
| 420 | count = -EINVAL; | ||
| 421 | goto fail; | ||
| 422 | } | ||
| 423 | |||
| 412 | /* we don't support the legacy modes with dpm */ | 424 | /* we don't support the legacy modes with dpm */ |
| 413 | if (rdev->pm.pm_method == PM_METHOD_DPM) { | 425 | if (rdev->pm.pm_method == PM_METHOD_DPM) { |
| 414 | count = -EINVAL; | 426 | count = -EINVAL; |
| @@ -446,6 +458,10 @@ static ssize_t radeon_get_dpm_state(struct device *dev, | |||
| 446 | struct radeon_device *rdev = ddev->dev_private; | 458 | struct radeon_device *rdev = ddev->dev_private; |
| 447 | enum radeon_pm_state_type pm = rdev->pm.dpm.user_state; | 459 | enum radeon_pm_state_type pm = rdev->pm.dpm.user_state; |
| 448 | 460 | ||
| 461 | if ((rdev->flags & RADEON_IS_PX) && | ||
| 462 | (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) | ||
| 463 | return snprintf(buf, PAGE_SIZE, "off\n"); | ||
| 464 | |||
| 449 | return snprintf(buf, PAGE_SIZE, "%s\n", | 465 | return snprintf(buf, PAGE_SIZE, "%s\n", |
| 450 | (pm == POWER_STATE_TYPE_BATTERY) ? "battery" : | 466 | (pm == POWER_STATE_TYPE_BATTERY) ? "battery" : |
| 451 | (pm == POWER_STATE_TYPE_BALANCED) ? "balanced" : "performance"); | 467 | (pm == POWER_STATE_TYPE_BALANCED) ? "balanced" : "performance"); |
| @@ -459,6 +475,11 @@ static ssize_t radeon_set_dpm_state(struct device *dev, | |||
| 459 | struct drm_device *ddev = dev_get_drvdata(dev); | 475 | struct drm_device *ddev = dev_get_drvdata(dev); |
| 460 | struct radeon_device *rdev = ddev->dev_private; | 476 | struct radeon_device *rdev = ddev->dev_private; |
| 461 | 477 | ||
| 478 | /* Can't set dpm state when the card is off */ | ||
| 479 | if ((rdev->flags & RADEON_IS_PX) && | ||
| 480 | (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) | ||
| 481 | return -EINVAL; | ||
| 482 | |||
| 462 | mutex_lock(&rdev->pm.mutex); | 483 | mutex_lock(&rdev->pm.mutex); |
| 463 | if (strncmp("battery", buf, strlen("battery")) == 0) | 484 | if (strncmp("battery", buf, strlen("battery")) == 0) |
| 464 | rdev->pm.dpm.user_state = POWER_STATE_TYPE_BATTERY; | 485 | rdev->pm.dpm.user_state = POWER_STATE_TYPE_BATTERY; |
| @@ -485,6 +506,10 @@ static ssize_t radeon_get_dpm_forced_performance_level(struct device *dev, | |||
| 485 | struct radeon_device *rdev = ddev->dev_private; | 506 | struct radeon_device *rdev = ddev->dev_private; |
| 486 | enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level; | 507 | enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level; |
| 487 | 508 | ||
| 509 | if ((rdev->flags & RADEON_IS_PX) && | ||
| 510 | (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) | ||
| 511 | return snprintf(buf, PAGE_SIZE, "off\n"); | ||
| 512 | |||
| 488 | return snprintf(buf, PAGE_SIZE, "%s\n", | 513 | return snprintf(buf, PAGE_SIZE, "%s\n", |
| 489 | (level == RADEON_DPM_FORCED_LEVEL_AUTO) ? "auto" : | 514 | (level == RADEON_DPM_FORCED_LEVEL_AUTO) ? "auto" : |
| 490 | (level == RADEON_DPM_FORCED_LEVEL_LOW) ? "low" : "high"); | 515 | (level == RADEON_DPM_FORCED_LEVEL_LOW) ? "low" : "high"); |
| @@ -500,6 +525,11 @@ static ssize_t radeon_set_dpm_forced_performance_level(struct device *dev, | |||
| 500 | enum radeon_dpm_forced_level level; | 525 | enum radeon_dpm_forced_level level; |
| 501 | int ret = 0; | 526 | int ret = 0; |
| 502 | 527 | ||
| 528 | /* Can't force performance level when the card is off */ | ||
| 529 | if ((rdev->flags & RADEON_IS_PX) && | ||
| 530 | (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) | ||
| 531 | return -EINVAL; | ||
| 532 | |||
| 503 | mutex_lock(&rdev->pm.mutex); | 533 | mutex_lock(&rdev->pm.mutex); |
| 504 | if (strncmp("low", buf, strlen("low")) == 0) { | 534 | if (strncmp("low", buf, strlen("low")) == 0) { |
| 505 | level = RADEON_DPM_FORCED_LEVEL_LOW; | 535 | level = RADEON_DPM_FORCED_LEVEL_LOW; |
| @@ -538,8 +568,14 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev, | |||
| 538 | char *buf) | 568 | char *buf) |
| 539 | { | 569 | { |
| 540 | struct radeon_device *rdev = dev_get_drvdata(dev); | 570 | struct radeon_device *rdev = dev_get_drvdata(dev); |
| 571 | struct drm_device *ddev = rdev->ddev; | ||
| 541 | int temp; | 572 | int temp; |
| 542 | 573 | ||
| 574 | /* Can't get temperature when the card is off */ | ||
| 575 | if ((rdev->flags & RADEON_IS_PX) && | ||
| 576 | (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) | ||
| 577 | return -EINVAL; | ||
| 578 | |||
| 543 | if (rdev->asic->pm.get_temperature) | 579 | if (rdev->asic->pm.get_temperature) |
| 544 | temp = radeon_get_temperature(rdev); | 580 | temp = radeon_get_temperature(rdev); |
| 545 | else | 581 | else |
| @@ -1614,8 +1650,12 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data) | |||
| 1614 | struct drm_info_node *node = (struct drm_info_node *) m->private; | 1650 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
| 1615 | struct drm_device *dev = node->minor->dev; | 1651 | struct drm_device *dev = node->minor->dev; |
| 1616 | struct radeon_device *rdev = dev->dev_private; | 1652 | struct radeon_device *rdev = dev->dev_private; |
| 1653 | struct drm_device *ddev = rdev->ddev; | ||
| 1617 | 1654 | ||
| 1618 | if (rdev->pm.dpm_enabled) { | 1655 | if ((rdev->flags & RADEON_IS_PX) && |
| 1656 | (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) { | ||
| 1657 | seq_printf(m, "PX asic powered off\n"); | ||
| 1658 | } else if (rdev->pm.dpm_enabled) { | ||
| 1619 | mutex_lock(&rdev->pm.mutex); | 1659 | mutex_lock(&rdev->pm.mutex); |
| 1620 | if (rdev->asic->dpm.debugfs_print_current_performance_level) | 1660 | if (rdev->asic->dpm.debugfs_print_current_performance_level) |
| 1621 | radeon_dpm_debugfs_print_current_performance_level(rdev, m); | 1661 | radeon_dpm_debugfs_print_current_performance_level(rdev, m); |
diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c index f73324c81491..3971d968af6c 100644 --- a/drivers/gpu/drm/radeon/radeon_vce.c +++ b/drivers/gpu/drm/radeon/radeon_vce.c | |||
| @@ -443,13 +443,16 @@ int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring, | |||
| 443 | * @p: parser context | 443 | * @p: parser context |
| 444 | * @lo: address of lower dword | 444 | * @lo: address of lower dword |
| 445 | * @hi: address of higher dword | 445 | * @hi: address of higher dword |
| 446 | * @size: size of checker for relocation buffer | ||
| 446 | * | 447 | * |
| 447 | * Patch relocation inside command stream with real buffer address | 448 | * Patch relocation inside command stream with real buffer address |
| 448 | */ | 449 | */ |
| 449 | int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi) | 450 | int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi, |
| 451 | unsigned size) | ||
| 450 | { | 452 | { |
| 451 | struct radeon_cs_chunk *relocs_chunk; | 453 | struct radeon_cs_chunk *relocs_chunk; |
| 452 | uint64_t offset; | 454 | struct radeon_cs_reloc *reloc; |
| 455 | uint64_t start, end, offset; | ||
| 453 | unsigned idx; | 456 | unsigned idx; |
| 454 | 457 | ||
| 455 | relocs_chunk = &p->chunks[p->chunk_relocs_idx]; | 458 | relocs_chunk = &p->chunks[p->chunk_relocs_idx]; |
| @@ -462,15 +465,60 @@ int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi) | |||
| 462 | return -EINVAL; | 465 | return -EINVAL; |
| 463 | } | 466 | } |
| 464 | 467 | ||
| 465 | offset += p->relocs_ptr[(idx / 4)]->gpu_offset; | 468 | reloc = p->relocs_ptr[(idx / 4)]; |
| 469 | start = reloc->gpu_offset; | ||
| 470 | end = start + radeon_bo_size(reloc->robj); | ||
| 471 | start += offset; | ||
| 466 | 472 | ||
| 467 | p->ib.ptr[lo] = offset & 0xFFFFFFFF; | 473 | p->ib.ptr[lo] = start & 0xFFFFFFFF; |
| 468 | p->ib.ptr[hi] = offset >> 32; | 474 | p->ib.ptr[hi] = start >> 32; |
| 475 | |||
| 476 | if (end <= start) { | ||
| 477 | DRM_ERROR("invalid reloc offset %llX!\n", offset); | ||
| 478 | return -EINVAL; | ||
| 479 | } | ||
| 480 | if ((end - start) < size) { | ||
| 481 | DRM_ERROR("buffer to small (%d / %d)!\n", | ||
| 482 | (unsigned)(end - start), size); | ||
| 483 | return -EINVAL; | ||
| 484 | } | ||
| 469 | 485 | ||
| 470 | return 0; | 486 | return 0; |
| 471 | } | 487 | } |
| 472 | 488 | ||
| 473 | /** | 489 | /** |
| 490 | * radeon_vce_validate_handle - validate stream handle | ||
| 491 | * | ||
| 492 | * @p: parser context | ||
| 493 | * @handle: handle to validate | ||
| 494 | * | ||
| 495 | * Validates the handle and return the found session index or -EINVAL | ||
| 496 | * we we don't have another free session index. | ||
| 497 | */ | ||
| 498 | int radeon_vce_validate_handle(struct radeon_cs_parser *p, uint32_t handle) | ||
| 499 | { | ||
| 500 | unsigned i; | ||
| 501 | |||
| 502 | /* validate the handle */ | ||
| 503 | for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { | ||
| 504 | if (atomic_read(&p->rdev->vce.handles[i]) == handle) | ||
| 505 | return i; | ||
| 506 | } | ||
| 507 | |||
| 508 | /* handle not found try to alloc a new one */ | ||
| 509 | for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { | ||
| 510 | if (!atomic_cmpxchg(&p->rdev->vce.handles[i], 0, handle)) { | ||
| 511 | p->rdev->vce.filp[i] = p->filp; | ||
| 512 | p->rdev->vce.img_size[i] = 0; | ||
| 513 | return i; | ||
| 514 | } | ||
| 515 | } | ||
| 516 | |||
| 517 | DRM_ERROR("No more free VCE handles!\n"); | ||
| 518 | return -EINVAL; | ||
| 519 | } | ||
| 520 | |||
| 521 | /** | ||
| 474 | * radeon_vce_cs_parse - parse and validate the command stream | 522 | * radeon_vce_cs_parse - parse and validate the command stream |
| 475 | * | 523 | * |
| 476 | * @p: parser context | 524 | * @p: parser context |
| @@ -478,8 +526,10 @@ int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi) | |||
| 478 | */ | 526 | */ |
| 479 | int radeon_vce_cs_parse(struct radeon_cs_parser *p) | 527 | int radeon_vce_cs_parse(struct radeon_cs_parser *p) |
| 480 | { | 528 | { |
| 481 | uint32_t handle = 0; | 529 | int session_idx = -1; |
| 482 | bool destroy = false; | 530 | bool destroyed = false; |
| 531 | uint32_t tmp, handle = 0; | ||
| 532 | uint32_t *size = &tmp; | ||
| 483 | int i, r; | 533 | int i, r; |
| 484 | 534 | ||
| 485 | while (p->idx < p->chunks[p->chunk_ib_idx].length_dw) { | 535 | while (p->idx < p->chunks[p->chunk_ib_idx].length_dw) { |
| @@ -491,13 +541,29 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p) | |||
| 491 | return -EINVAL; | 541 | return -EINVAL; |
| 492 | } | 542 | } |
| 493 | 543 | ||
| 544 | if (destroyed) { | ||
| 545 | DRM_ERROR("No other command allowed after destroy!\n"); | ||
| 546 | return -EINVAL; | ||
| 547 | } | ||
| 548 | |||
| 494 | switch (cmd) { | 549 | switch (cmd) { |
| 495 | case 0x00000001: // session | 550 | case 0x00000001: // session |
| 496 | handle = radeon_get_ib_value(p, p->idx + 2); | 551 | handle = radeon_get_ib_value(p, p->idx + 2); |
| 552 | session_idx = radeon_vce_validate_handle(p, handle); | ||
| 553 | if (session_idx < 0) | ||
| 554 | return session_idx; | ||
| 555 | size = &p->rdev->vce.img_size[session_idx]; | ||
| 497 | break; | 556 | break; |
| 498 | 557 | ||
| 499 | case 0x00000002: // task info | 558 | case 0x00000002: // task info |
| 559 | break; | ||
| 560 | |||
| 500 | case 0x01000001: // create | 561 | case 0x01000001: // create |
| 562 | *size = radeon_get_ib_value(p, p->idx + 8) * | ||
| 563 | radeon_get_ib_value(p, p->idx + 10) * | ||
| 564 | 8 * 3 / 2; | ||
| 565 | break; | ||
| 566 | |||
| 501 | case 0x04000001: // config extension | 567 | case 0x04000001: // config extension |
| 502 | case 0x04000002: // pic control | 568 | case 0x04000002: // pic control |
| 503 | case 0x04000005: // rate control | 569 | case 0x04000005: // rate control |
| @@ -506,23 +572,39 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p) | |||
| 506 | break; | 572 | break; |
| 507 | 573 | ||
| 508 | case 0x03000001: // encode | 574 | case 0x03000001: // encode |
| 509 | r = radeon_vce_cs_reloc(p, p->idx + 10, p->idx + 9); | 575 | r = radeon_vce_cs_reloc(p, p->idx + 10, p->idx + 9, |
| 576 | *size); | ||
| 510 | if (r) | 577 | if (r) |
| 511 | return r; | 578 | return r; |
| 512 | 579 | ||
| 513 | r = radeon_vce_cs_reloc(p, p->idx + 12, p->idx + 11); | 580 | r = radeon_vce_cs_reloc(p, p->idx + 12, p->idx + 11, |
| 581 | *size / 3); | ||
| 514 | if (r) | 582 | if (r) |
| 515 | return r; | 583 | return r; |
| 516 | break; | 584 | break; |
| 517 | 585 | ||
| 518 | case 0x02000001: // destroy | 586 | case 0x02000001: // destroy |
| 519 | destroy = true; | 587 | destroyed = true; |
| 520 | break; | 588 | break; |
| 521 | 589 | ||
| 522 | case 0x05000001: // context buffer | 590 | case 0x05000001: // context buffer |
| 591 | r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2, | ||
| 592 | *size * 2); | ||
| 593 | if (r) | ||
| 594 | return r; | ||
| 595 | break; | ||
| 596 | |||
| 523 | case 0x05000004: // video bitstream buffer | 597 | case 0x05000004: // video bitstream buffer |
| 598 | tmp = radeon_get_ib_value(p, p->idx + 4); | ||
| 599 | r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2, | ||
| 600 | tmp); | ||
| 601 | if (r) | ||
| 602 | return r; | ||
| 603 | break; | ||
| 604 | |||
| 524 | case 0x05000005: // feedback buffer | 605 | case 0x05000005: // feedback buffer |
| 525 | r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2); | 606 | r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2, |
| 607 | 4096); | ||
| 526 | if (r) | 608 | if (r) |
| 527 | return r; | 609 | return r; |
| 528 | break; | 610 | break; |
| @@ -532,33 +614,21 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p) | |||
| 532 | return -EINVAL; | 614 | return -EINVAL; |
| 533 | } | 615 | } |
| 534 | 616 | ||
| 617 | if (session_idx == -1) { | ||
| 618 | DRM_ERROR("no session command at start of IB\n"); | ||
| 619 | return -EINVAL; | ||
| 620 | } | ||
| 621 | |||
| 535 | p->idx += len / 4; | 622 | p->idx += len / 4; |
| 536 | } | 623 | } |
| 537 | 624 | ||
| 538 | if (destroy) { | 625 | if (destroyed) { |
| 539 | /* IB contains a destroy msg, free the handle */ | 626 | /* IB contains a destroy msg, free the handle */ |
| 540 | for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) | 627 | for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) |
| 541 | atomic_cmpxchg(&p->rdev->vce.handles[i], handle, 0); | 628 | atomic_cmpxchg(&p->rdev->vce.handles[i], handle, 0); |
| 542 | |||
| 543 | return 0; | ||
| 544 | } | ||
| 545 | |||
| 546 | /* create or encode, validate the handle */ | ||
| 547 | for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { | ||
| 548 | if (atomic_read(&p->rdev->vce.handles[i]) == handle) | ||
| 549 | return 0; | ||
| 550 | } | 629 | } |
| 551 | 630 | ||
| 552 | /* handle not found try to alloc a new one */ | 631 | return 0; |
| 553 | for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { | ||
| 554 | if (!atomic_cmpxchg(&p->rdev->vce.handles[i], 0, handle)) { | ||
| 555 | p->rdev->vce.filp[i] = p->filp; | ||
| 556 | return 0; | ||
| 557 | } | ||
| 558 | } | ||
| 559 | |||
| 560 | DRM_ERROR("No more free VCE handles!\n"); | ||
| 561 | return -EINVAL; | ||
| 562 | } | 632 | } |
| 563 | 633 | ||
| 564 | /** | 634 | /** |
diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index 2aae6ce49d32..d9ab99f47612 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c | |||
| @@ -595,7 +595,7 @@ int radeon_vm_update_page_directory(struct radeon_device *rdev, | |||
| 595 | ndw = 64; | 595 | ndw = 64; |
| 596 | 596 | ||
| 597 | /* assume the worst case */ | 597 | /* assume the worst case */ |
| 598 | ndw += vm->max_pde_used * 12; | 598 | ndw += vm->max_pde_used * 16; |
| 599 | 599 | ||
| 600 | /* update too big for an IB */ | 600 | /* update too big for an IB */ |
| 601 | if (ndw > 0xfffff) | 601 | if (ndw > 0xfffff) |
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 683532f84931..7321283602ce 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h | |||
| @@ -107,8 +107,8 @@ | |||
| 107 | #define SPLL_CHG_STATUS (1 << 1) | 107 | #define SPLL_CHG_STATUS (1 << 1) |
| 108 | #define SPLL_CNTL_MODE 0x618 | 108 | #define SPLL_CNTL_MODE 0x618 |
| 109 | #define SPLL_SW_DIR_CONTROL (1 << 0) | 109 | #define SPLL_SW_DIR_CONTROL (1 << 0) |
| 110 | # define SPLL_REFCLK_SEL(x) ((x) << 8) | 110 | # define SPLL_REFCLK_SEL(x) ((x) << 26) |
| 111 | # define SPLL_REFCLK_SEL_MASK 0xFF00 | 111 | # define SPLL_REFCLK_SEL_MASK (3 << 26) |
| 112 | 112 | ||
| 113 | #define CG_SPLL_SPREAD_SPECTRUM 0x620 | 113 | #define CG_SPLL_SPREAD_SPECTRUM 0x620 |
| 114 | #define SSEN (1 << 0) | 114 | #define SSEN (1 << 0) |
