diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-05-23 12:41:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-05-23 12:41:33 -0400 |
commit | 2b2d323a31dc8b369a4c0e33705339399021fa83 (patch) | |
tree | c74f0b1fadf8d56672d5090489d5fa69e226b12a | |
parent | fc3ac5c75bae55ca6a070eb72038a94d4f130d8d (diff) | |
parent | 77c01bef72a5ce5cb24adae6066ed81a52004d30 (diff) |
Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Pull drm radeon and nouveau fixes from Dave Airlie:
"Fixes for the other big two.
The radeon VCE one is large but it fixes some userspace triggerable
issues, otherwise its blackscreens and oopses.
Nouveau fixes a bleeding laptop panel issue when displayport is used
sometimes"
* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
drm/radeon/pm: don't allow debugfs/sysfs access when PX card is off (v2)
drm/radeon: avoid segfault on device open when accel is not working.
drm/radeon: fix typo in finding PLL params
drm/radeon: fix register typo on si
drm/radeon: fix buffer placement under memory pressure v2
drm/radeon: fix page directory update size estimation
drm/radeon: handle non-VGA class pci devices with ATRM
drm/radeon: fix DCE83 check for mullins
drm/radeon: check VCE relocation buffer range v3
drm/radeon: also try GART for CPU accessed buffers
drm/gf119-/disp: fix nasty bug which can clobber SOR0's clock setup
drm/nvd9/therm: handle another kind of PWM fan
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c | 1 | ||||
-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 |
11 files changed, 218 insertions, 80 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c index 7762665ad8fd..876de9ac3793 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | |||
@@ -1009,7 +1009,7 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, | |||
1009 | } | 1009 | } |
1010 | 1010 | ||
1011 | if (outp == 8) | 1011 | if (outp == 8) |
1012 | return false; | 1012 | return conf; |
1013 | 1013 | ||
1014 | data = exec_lookup(priv, head, outp, ctrl, dcb, &ver, &hdr, &cnt, &len, &info1); | 1014 | data = exec_lookup(priv, head, outp, ctrl, dcb, &ver, &hdr, &cnt, &len, &info1); |
1015 | if (data == 0x0000) | 1015 | if (data == 0x0000) |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c index 43fec17ea540..bbf117be572f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c | |||
@@ -40,6 +40,7 @@ pwm_info(struct nouveau_therm *therm, int line) | |||
40 | case 0x00: return 2; | 40 | case 0x00: return 2; |
41 | case 0x19: return 1; | 41 | case 0x19: return 1; |
42 | case 0x1c: return 0; | 42 | case 0x1c: return 0; |
43 | case 0x1e: return 2; | ||
43 | default: | 44 | default: |
44 | break; | 45 | break; |
45 | } | 46 | } |
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) |