diff options
Diffstat (limited to 'drivers/gpu')
26 files changed, 253 insertions, 118 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 69af73f15310..596ee5cd3b84 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | |||
| @@ -430,9 +430,10 @@ static int unregister_process_nocpsch(struct device_queue_manager *dqm, | |||
| 430 | 430 | ||
| 431 | BUG_ON(!dqm || !qpd); | 431 | BUG_ON(!dqm || !qpd); |
| 432 | 432 | ||
| 433 | BUG_ON(!list_empty(&qpd->queues_list)); | 433 | pr_debug("In func %s\n", __func__); |
| 434 | 434 | ||
| 435 | pr_debug("kfd: In func %s\n", __func__); | 435 | pr_debug("qpd->queues_list is %s\n", |
| 436 | list_empty(&qpd->queues_list) ? "empty" : "not empty"); | ||
| 436 | 437 | ||
| 437 | retval = 0; | 438 | retval = 0; |
| 438 | mutex_lock(&dqm->lock); | 439 | mutex_lock(&dqm->lock); |
| @@ -882,6 +883,8 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q, | |||
| 882 | return -ENOMEM; | 883 | return -ENOMEM; |
| 883 | } | 884 | } |
| 884 | 885 | ||
| 886 | init_sdma_vm(dqm, q, qpd); | ||
| 887 | |||
| 885 | retval = mqd->init_mqd(mqd, &q->mqd, &q->mqd_mem_obj, | 888 | retval = mqd->init_mqd(mqd, &q->mqd, &q->mqd_mem_obj, |
| 886 | &q->gart_mqd_addr, &q->properties); | 889 | &q->gart_mqd_addr, &q->properties); |
| 887 | if (retval != 0) | 890 | if (retval != 0) |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index 661c6605d31b..e469c4b2e8cc 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c | |||
| @@ -728,9 +728,9 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr, | |||
| 728 | sysfs_show_32bit_prop(buffer, "max_engine_clk_fcompute", | 728 | sysfs_show_32bit_prop(buffer, "max_engine_clk_fcompute", |
| 729 | dev->gpu->kfd2kgd->get_max_engine_clock_in_mhz( | 729 | dev->gpu->kfd2kgd->get_max_engine_clock_in_mhz( |
| 730 | dev->gpu->kgd)); | 730 | dev->gpu->kgd)); |
| 731 | |||
| 731 | sysfs_show_64bit_prop(buffer, "local_mem_size", | 732 | sysfs_show_64bit_prop(buffer, "local_mem_size", |
| 732 | dev->gpu->kfd2kgd->get_vmem_size( | 733 | (unsigned long long int) 0); |
| 733 | dev->gpu->kgd)); | ||
| 734 | 734 | ||
| 735 | sysfs_show_32bit_prop(buffer, "fw_version", | 735 | sysfs_show_32bit_prop(buffer, "fw_version", |
| 736 | dev->gpu->kfd2kgd->get_fw_version( | 736 | dev->gpu->kfd2kgd->get_fw_version( |
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index c8a34476570a..af9662e58272 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
| @@ -131,12 +131,11 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc) | |||
| 131 | 131 | ||
| 132 | /* Reinitialize corresponding vblank timestamp if high-precision query | 132 | /* Reinitialize corresponding vblank timestamp if high-precision query |
| 133 | * available. Skip this step if query unsupported or failed. Will | 133 | * available. Skip this step if query unsupported or failed. Will |
| 134 | * reinitialize delayed at next vblank interrupt in that case. | 134 | * reinitialize delayed at next vblank interrupt in that case and |
| 135 | * assign 0 for now, to mark the vblanktimestamp as invalid. | ||
| 135 | */ | 136 | */ |
| 136 | if (rc) { | 137 | tslot = atomic_read(&vblank->count) + diff; |
| 137 | tslot = atomic_read(&vblank->count) + diff; | 138 | vblanktimestamp(dev, crtc, tslot) = rc ? t_vblank : (struct timeval) {0, 0}; |
| 138 | vblanktimestamp(dev, crtc, tslot) = t_vblank; | ||
| 139 | } | ||
| 140 | 139 | ||
| 141 | smp_mb__before_atomic(); | 140 | smp_mb__before_atomic(); |
| 142 | atomic_add(diff, &vblank->count); | 141 | atomic_add(diff, &vblank->count); |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index c302ffb5a168..a19d2c71e205 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -699,6 +699,16 @@ static int i915_drm_resume(struct drm_device *dev) | |||
| 699 | intel_init_pch_refclk(dev); | 699 | intel_init_pch_refclk(dev); |
| 700 | drm_mode_config_reset(dev); | 700 | drm_mode_config_reset(dev); |
| 701 | 701 | ||
| 702 | /* | ||
| 703 | * Interrupts have to be enabled before any batches are run. If not the | ||
| 704 | * GPU will hang. i915_gem_init_hw() will initiate batches to | ||
| 705 | * update/restore the context. | ||
| 706 | * | ||
| 707 | * Modeset enabling in intel_modeset_init_hw() also needs working | ||
| 708 | * interrupts. | ||
| 709 | */ | ||
| 710 | intel_runtime_pm_enable_interrupts(dev_priv); | ||
| 711 | |||
| 702 | mutex_lock(&dev->struct_mutex); | 712 | mutex_lock(&dev->struct_mutex); |
| 703 | if (i915_gem_init_hw(dev)) { | 713 | if (i915_gem_init_hw(dev)) { |
| 704 | DRM_ERROR("failed to re-initialize GPU, declaring wedged!\n"); | 714 | DRM_ERROR("failed to re-initialize GPU, declaring wedged!\n"); |
| @@ -706,9 +716,6 @@ static int i915_drm_resume(struct drm_device *dev) | |||
| 706 | } | 716 | } |
| 707 | mutex_unlock(&dev->struct_mutex); | 717 | mutex_unlock(&dev->struct_mutex); |
| 708 | 718 | ||
| 709 | /* We need working interrupts for modeset enabling ... */ | ||
| 710 | intel_runtime_pm_enable_interrupts(dev_priv); | ||
| 711 | |||
| 712 | intel_modeset_init_hw(dev); | 719 | intel_modeset_init_hw(dev); |
| 713 | 720 | ||
| 714 | spin_lock_irq(&dev_priv->irq_lock); | 721 | spin_lock_irq(&dev_priv->irq_lock); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d547d9c8dda2..d0f3cbc87474 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -13635,9 +13635,6 @@ static const struct intel_dmi_quirk intel_dmi_quirks[] = { | |||
| 13635 | }; | 13635 | }; |
| 13636 | 13636 | ||
| 13637 | static struct intel_quirk intel_quirks[] = { | 13637 | static struct intel_quirk intel_quirks[] = { |
| 13638 | /* HP Mini needs pipe A force quirk (LP: #322104) */ | ||
| 13639 | { 0x27ae, 0x103c, 0x361a, quirk_pipea_force }, | ||
| 13640 | |||
| 13641 | /* Toshiba Protege R-205, S-209 needs pipe A force quirk */ | 13638 | /* Toshiba Protege R-205, S-209 needs pipe A force quirk */ |
| 13642 | { 0x2592, 0x1179, 0x0001, quirk_pipea_force }, | 13639 | { 0x2592, 0x1179, 0x0001, quirk_pipea_force }, |
| 13643 | 13640 | ||
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d0237102c27e..f27346e907b1 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -1348,7 +1348,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, | |||
| 1348 | 1348 | ||
| 1349 | pipe_config->has_dp_encoder = true; | 1349 | pipe_config->has_dp_encoder = true; |
| 1350 | pipe_config->has_drrs = false; | 1350 | pipe_config->has_drrs = false; |
| 1351 | pipe_config->has_audio = intel_dp->has_audio; | 1351 | pipe_config->has_audio = intel_dp->has_audio && port != PORT_A; |
| 1352 | 1352 | ||
| 1353 | if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) { | 1353 | if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) { |
| 1354 | intel_fixed_panel_mode(intel_connector->panel.fixed_mode, | 1354 | intel_fixed_panel_mode(intel_connector->panel.fixed_mode, |
| @@ -2211,8 +2211,8 @@ static void intel_dp_get_config(struct intel_encoder *encoder, | |||
| 2211 | int dotclock; | 2211 | int dotclock; |
| 2212 | 2212 | ||
| 2213 | tmp = I915_READ(intel_dp->output_reg); | 2213 | tmp = I915_READ(intel_dp->output_reg); |
| 2214 | if (tmp & DP_AUDIO_OUTPUT_ENABLE) | 2214 | |
| 2215 | pipe_config->has_audio = true; | 2215 | pipe_config->has_audio = tmp & DP_AUDIO_OUTPUT_ENABLE && port != PORT_A; |
| 2216 | 2216 | ||
| 2217 | if ((port == PORT_A) || !HAS_PCH_CPT(dev)) { | 2217 | if ((port == PORT_A) || !HAS_PCH_CPT(dev)) { |
| 2218 | if (tmp & DP_SYNC_HS_HIGH) | 2218 | if (tmp & DP_SYNC_HS_HIGH) |
| @@ -3812,7 +3812,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) | |||
| 3812 | if (val == 0) | 3812 | if (val == 0) |
| 3813 | break; | 3813 | break; |
| 3814 | 3814 | ||
| 3815 | intel_dp->sink_rates[i] = val * 200; | 3815 | /* Value read is in kHz while drm clock is saved in deca-kHz */ |
| 3816 | intel_dp->sink_rates[i] = (val * 200) / 10; | ||
| 3816 | } | 3817 | } |
| 3817 | intel_dp->num_sink_rates = i; | 3818 | intel_dp->num_sink_rates = i; |
| 3818 | } | 3819 | } |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 5abda1d2c018..fbcc7dff0d63 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
| @@ -813,12 +813,28 @@ static int intel_dual_link_lvds_callback(const struct dmi_system_id *id) | |||
| 813 | static const struct dmi_system_id intel_dual_link_lvds[] = { | 813 | static const struct dmi_system_id intel_dual_link_lvds[] = { |
| 814 | { | 814 | { |
| 815 | .callback = intel_dual_link_lvds_callback, | 815 | .callback = intel_dual_link_lvds_callback, |
| 816 | .ident = "Apple MacBook Pro (Core i5/i7 Series)", | 816 | .ident = "Apple MacBook Pro 15\" (2010)", |
| 817 | .matches = { | ||
| 818 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | ||
| 819 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro6,2"), | ||
| 820 | }, | ||
| 821 | }, | ||
| 822 | { | ||
| 823 | .callback = intel_dual_link_lvds_callback, | ||
| 824 | .ident = "Apple MacBook Pro 15\" (2011)", | ||
| 817 | .matches = { | 825 | .matches = { |
| 818 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | 826 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), |
| 819 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"), | 827 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"), |
| 820 | }, | 828 | }, |
| 821 | }, | 829 | }, |
| 830 | { | ||
| 831 | .callback = intel_dual_link_lvds_callback, | ||
| 832 | .ident = "Apple MacBook Pro 15\" (2012)", | ||
| 833 | .matches = { | ||
| 834 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | ||
| 835 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro9,1"), | ||
| 836 | }, | ||
| 837 | }, | ||
| 822 | { } /* terminating entry */ | 838 | { } /* terminating entry */ |
| 823 | }; | 839 | }; |
| 824 | 840 | ||
| @@ -848,6 +864,11 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) | |||
| 848 | if (i915.lvds_channel_mode > 0) | 864 | if (i915.lvds_channel_mode > 0) |
| 849 | return i915.lvds_channel_mode == 2; | 865 | return i915.lvds_channel_mode == 2; |
| 850 | 866 | ||
| 867 | /* single channel LVDS is limited to 112 MHz */ | ||
| 868 | if (lvds_encoder->attached_connector->base.panel.fixed_mode->clock | ||
| 869 | > 112999) | ||
| 870 | return true; | ||
| 871 | |||
| 851 | if (dmi_check_system(intel_dual_link_lvds)) | 872 | if (dmi_check_system(intel_dual_link_lvds)) |
| 852 | return true; | 873 | return true; |
| 853 | 874 | ||
| @@ -1111,6 +1132,8 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 1111 | out: | 1132 | out: |
| 1112 | mutex_unlock(&dev->mode_config.mutex); | 1133 | mutex_unlock(&dev->mode_config.mutex); |
| 1113 | 1134 | ||
| 1135 | intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode); | ||
| 1136 | |||
| 1114 | lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder); | 1137 | lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder); |
| 1115 | DRM_DEBUG_KMS("detected %s-link lvds configuration\n", | 1138 | DRM_DEBUG_KMS("detected %s-link lvds configuration\n", |
| 1116 | lvds_encoder->is_dual_link ? "dual" : "single"); | 1139 | lvds_encoder->is_dual_link ? "dual" : "single"); |
| @@ -1125,7 +1148,6 @@ out: | |||
| 1125 | } | 1148 | } |
| 1126 | drm_connector_register(connector); | 1149 | drm_connector_register(connector); |
| 1127 | 1150 | ||
| 1128 | intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode); | ||
| 1129 | intel_panel_setup_backlight(connector, INVALID_PIPE); | 1151 | intel_panel_setup_backlight(connector, INVALID_PIPE); |
| 1130 | 1152 | ||
| 1131 | return; | 1153 | return; |
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 28faea9996f9..a0c35bbc8546 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c | |||
| @@ -5822,7 +5822,7 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev) | |||
| 5822 | L2_CACHE_BIGK_FRAGMENT_SIZE(4)); | 5822 | L2_CACHE_BIGK_FRAGMENT_SIZE(4)); |
| 5823 | /* setup context0 */ | 5823 | /* setup context0 */ |
| 5824 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); | 5824 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); |
| 5825 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); | 5825 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, (rdev->mc.gtt_end >> 12) - 1); |
| 5826 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); | 5826 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); |
| 5827 | WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, | 5827 | WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, |
| 5828 | (u32)(rdev->dummy_page.addr >> 12)); | 5828 | (u32)(rdev->dummy_page.addr >> 12)); |
| @@ -5837,7 +5837,7 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev) | |||
| 5837 | /* restore context1-15 */ | 5837 | /* restore context1-15 */ |
| 5838 | /* set vm size, must be a multiple of 4 */ | 5838 | /* set vm size, must be a multiple of 4 */ |
| 5839 | WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0); | 5839 | WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0); |
| 5840 | WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn); | 5840 | WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn - 1); |
| 5841 | for (i = 1; i < 16; i++) { | 5841 | for (i = 1; i < 16; i++) { |
| 5842 | if (i < 8) | 5842 | if (i < 8) |
| 5843 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), | 5843 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index f848acfd3fc8..05e6d6ef5963 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
| @@ -2485,7 +2485,7 @@ static int evergreen_pcie_gart_enable(struct radeon_device *rdev) | |||
| 2485 | WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); | 2485 | WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); |
| 2486 | WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); | 2486 | WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); |
| 2487 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); | 2487 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); |
| 2488 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); | 2488 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, (rdev->mc.gtt_end >> 12) - 1); |
| 2489 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); | 2489 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); |
| 2490 | WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | | 2490 | WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | |
| 2491 | RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); | 2491 | RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); |
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index e8a496ff007e..aba2f428c0a8 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
| @@ -1282,7 +1282,7 @@ static int cayman_pcie_gart_enable(struct radeon_device *rdev) | |||
| 1282 | L2_CACHE_BIGK_FRAGMENT_SIZE(6)); | 1282 | L2_CACHE_BIGK_FRAGMENT_SIZE(6)); |
| 1283 | /* setup context0 */ | 1283 | /* setup context0 */ |
| 1284 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); | 1284 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); |
| 1285 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); | 1285 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, (rdev->mc.gtt_end >> 12) - 1); |
| 1286 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); | 1286 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); |
| 1287 | WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, | 1287 | WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, |
| 1288 | (u32)(rdev->dummy_page.addr >> 12)); | 1288 | (u32)(rdev->dummy_page.addr >> 12)); |
| @@ -1301,7 +1301,8 @@ static int cayman_pcie_gart_enable(struct radeon_device *rdev) | |||
| 1301 | */ | 1301 | */ |
| 1302 | for (i = 1; i < 8; i++) { | 1302 | for (i = 1; i < 8; i++) { |
| 1303 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0); | 1303 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0); |
| 1304 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), rdev->vm_manager.max_pfn); | 1304 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), |
| 1305 | rdev->vm_manager.max_pfn - 1); | ||
| 1305 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), | 1306 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), |
| 1306 | rdev->vm_manager.saved_table_addr[i]); | 1307 | rdev->vm_manager.saved_table_addr[i]); |
| 1307 | } | 1308 | } |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 8f6d862a1882..25b4ac967742 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
| @@ -1112,7 +1112,7 @@ static int r600_pcie_gart_enable(struct radeon_device *rdev) | |||
| 1112 | WREG32(MC_VM_L1_TLB_MCB_RD_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE); | 1112 | WREG32(MC_VM_L1_TLB_MCB_RD_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE); |
| 1113 | WREG32(MC_VM_L1_TLB_MCB_WR_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE); | 1113 | WREG32(MC_VM_L1_TLB_MCB_WR_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE); |
| 1114 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); | 1114 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); |
| 1115 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); | 1115 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, (rdev->mc.gtt_end >> 12) - 1); |
| 1116 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); | 1116 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); |
| 1117 | WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | | 1117 | WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | |
| 1118 | RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); | 1118 | RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index d2abe481954f..46eb0fa75a61 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -1673,7 +1673,6 @@ struct radeon_uvd { | |||
| 1673 | struct radeon_bo *vcpu_bo; | 1673 | struct radeon_bo *vcpu_bo; |
| 1674 | void *cpu_addr; | 1674 | void *cpu_addr; |
| 1675 | uint64_t gpu_addr; | 1675 | uint64_t gpu_addr; |
| 1676 | void *saved_bo; | ||
| 1677 | atomic_t handles[RADEON_MAX_UVD_HANDLES]; | 1676 | atomic_t handles[RADEON_MAX_UVD_HANDLES]; |
| 1678 | struct drm_file *filp[RADEON_MAX_UVD_HANDLES]; | 1677 | struct drm_file *filp[RADEON_MAX_UVD_HANDLES]; |
| 1679 | unsigned img_size[RADEON_MAX_UVD_HANDLES]; | 1678 | unsigned img_size[RADEON_MAX_UVD_HANDLES]; |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index fafd8ce4d58f..8dbf5083c4ff 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c | |||
| @@ -1202,7 +1202,7 @@ static struct radeon_asic rs780_asic = { | |||
| 1202 | static struct radeon_asic_ring rv770_uvd_ring = { | 1202 | static struct radeon_asic_ring rv770_uvd_ring = { |
| 1203 | .ib_execute = &uvd_v1_0_ib_execute, | 1203 | .ib_execute = &uvd_v1_0_ib_execute, |
| 1204 | .emit_fence = &uvd_v2_2_fence_emit, | 1204 | .emit_fence = &uvd_v2_2_fence_emit, |
| 1205 | .emit_semaphore = &uvd_v1_0_semaphore_emit, | 1205 | .emit_semaphore = &uvd_v2_2_semaphore_emit, |
| 1206 | .cs_parse = &radeon_uvd_cs_parse, | 1206 | .cs_parse = &radeon_uvd_cs_parse, |
| 1207 | .ring_test = &uvd_v1_0_ring_test, | 1207 | .ring_test = &uvd_v1_0_ring_test, |
| 1208 | .ib_test = &uvd_v1_0_ib_test, | 1208 | .ib_test = &uvd_v1_0_ib_test, |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index cf0a90bb61ca..a3ca8cd305c5 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
| @@ -949,6 +949,10 @@ void uvd_v1_0_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); | |||
| 949 | int uvd_v2_2_resume(struct radeon_device *rdev); | 949 | int uvd_v2_2_resume(struct radeon_device *rdev); |
| 950 | void uvd_v2_2_fence_emit(struct radeon_device *rdev, | 950 | void uvd_v2_2_fence_emit(struct radeon_device *rdev, |
| 951 | struct radeon_fence *fence); | 951 | struct radeon_fence *fence); |
| 952 | bool uvd_v2_2_semaphore_emit(struct radeon_device *rdev, | ||
| 953 | struct radeon_ring *ring, | ||
| 954 | struct radeon_semaphore *semaphore, | ||
| 955 | bool emit_wait); | ||
| 952 | 956 | ||
| 953 | /* uvd v3.1 */ | 957 | /* uvd v3.1 */ |
| 954 | bool uvd_v3_1_semaphore_emit(struct radeon_device *rdev, | 958 | bool uvd_v3_1_semaphore_emit(struct radeon_device *rdev, |
diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index 8b82abb78df1..dcb779647c57 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c | |||
| @@ -464,6 +464,10 @@ void radeon_audio_detect(struct drm_connector *connector, | |||
| 464 | return; | 464 | return; |
| 465 | 465 | ||
| 466 | rdev = connector->encoder->dev->dev_private; | 466 | rdev = connector->encoder->dev->dev_private; |
| 467 | |||
| 468 | if (!radeon_audio_chipset_supported(rdev)) | ||
| 469 | return; | ||
| 470 | |||
| 467 | radeon_encoder = to_radeon_encoder(connector->encoder); | 471 | radeon_encoder = to_radeon_encoder(connector->encoder); |
| 468 | dig = radeon_encoder->enc_priv; | 472 | dig = radeon_encoder->enc_priv; |
| 469 | 473 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c index 1017338a49d9..2b98ed3e684d 100644 --- a/drivers/gpu/drm/radeon/radeon_dp_mst.c +++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c | |||
| @@ -666,6 +666,9 @@ radeon_dp_mst_probe(struct radeon_connector *radeon_connector) | |||
| 666 | int ret; | 666 | int ret; |
| 667 | u8 msg[1]; | 667 | u8 msg[1]; |
| 668 | 668 | ||
| 669 | if (!radeon_mst) | ||
| 670 | return 0; | ||
| 671 | |||
| 669 | if (dig_connector->dpcd[DP_DPCD_REV] < 0x12) | 672 | if (dig_connector->dpcd[DP_DPCD_REV] < 0x12) |
| 670 | return 0; | 673 | return 0; |
| 671 | 674 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_mn.c b/drivers/gpu/drm/radeon/radeon_mn.c index 535bf404b725..eef006c48584 100644 --- a/drivers/gpu/drm/radeon/radeon_mn.c +++ b/drivers/gpu/drm/radeon/radeon_mn.c | |||
| @@ -142,6 +142,9 @@ static void radeon_mn_invalidate_range_start(struct mmu_notifier *mn, | |||
| 142 | 142 | ||
| 143 | list_for_each_entry(bo, &node->bos, mn_list) { | 143 | list_for_each_entry(bo, &node->bos, mn_list) { |
| 144 | 144 | ||
| 145 | if (!bo->tbo.ttm || bo->tbo.ttm->state != tt_bound) | ||
| 146 | continue; | ||
| 147 | |||
| 145 | r = radeon_bo_reserve(bo, true); | 148 | r = radeon_bo_reserve(bo, true); |
| 146 | if (r) { | 149 | if (r) { |
| 147 | DRM_ERROR("(%ld) failed to reserve user bo\n", r); | 150 | DRM_ERROR("(%ld) failed to reserve user bo\n", r); |
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index b292aca0f342..edafd3c2b170 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c | |||
| @@ -591,8 +591,7 @@ static void radeon_ttm_tt_unpin_userptr(struct ttm_tt *ttm) | |||
| 591 | { | 591 | { |
| 592 | struct radeon_device *rdev = radeon_get_rdev(ttm->bdev); | 592 | struct radeon_device *rdev = radeon_get_rdev(ttm->bdev); |
| 593 | struct radeon_ttm_tt *gtt = (void *)ttm; | 593 | struct radeon_ttm_tt *gtt = (void *)ttm; |
| 594 | struct scatterlist *sg; | 594 | struct sg_page_iter sg_iter; |
| 595 | int i; | ||
| 596 | 595 | ||
| 597 | int write = !(gtt->userflags & RADEON_GEM_USERPTR_READONLY); | 596 | int write = !(gtt->userflags & RADEON_GEM_USERPTR_READONLY); |
| 598 | enum dma_data_direction direction = write ? | 597 | enum dma_data_direction direction = write ? |
| @@ -605,9 +604,8 @@ static void radeon_ttm_tt_unpin_userptr(struct ttm_tt *ttm) | |||
| 605 | /* free the sg table and pages again */ | 604 | /* free the sg table and pages again */ |
| 606 | dma_unmap_sg(rdev->dev, ttm->sg->sgl, ttm->sg->nents, direction); | 605 | dma_unmap_sg(rdev->dev, ttm->sg->sgl, ttm->sg->nents, direction); |
| 607 | 606 | ||
| 608 | for_each_sg(ttm->sg->sgl, sg, ttm->sg->nents, i) { | 607 | for_each_sg_page(ttm->sg->sgl, &sg_iter, ttm->sg->nents, 0) { |
| 609 | struct page *page = sg_page(sg); | 608 | struct page *page = sg_page_iter_page(&sg_iter); |
| 610 | |||
| 611 | if (!(gtt->userflags & RADEON_GEM_USERPTR_READONLY)) | 609 | if (!(gtt->userflags & RADEON_GEM_USERPTR_READONLY)) |
| 612 | set_page_dirty(page); | 610 | set_page_dirty(page); |
| 613 | 611 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index c10b2aec6450..6edcb5485092 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c | |||
| @@ -204,28 +204,32 @@ void radeon_uvd_fini(struct radeon_device *rdev) | |||
| 204 | 204 | ||
| 205 | int radeon_uvd_suspend(struct radeon_device *rdev) | 205 | int radeon_uvd_suspend(struct radeon_device *rdev) |
| 206 | { | 206 | { |
| 207 | unsigned size; | 207 | int i, r; |
| 208 | void *ptr; | ||
| 209 | int i; | ||
| 210 | 208 | ||
| 211 | if (rdev->uvd.vcpu_bo == NULL) | 209 | if (rdev->uvd.vcpu_bo == NULL) |
| 212 | return 0; | 210 | return 0; |
| 213 | 211 | ||
| 214 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) | 212 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { |
| 215 | if (atomic_read(&rdev->uvd.handles[i])) | 213 | uint32_t handle = atomic_read(&rdev->uvd.handles[i]); |
| 216 | break; | 214 | if (handle != 0) { |
| 215 | struct radeon_fence *fence; | ||
| 217 | 216 | ||
| 218 | if (i == RADEON_MAX_UVD_HANDLES) | 217 | radeon_uvd_note_usage(rdev); |
| 219 | return 0; | ||
| 220 | 218 | ||
| 221 | size = radeon_bo_size(rdev->uvd.vcpu_bo); | 219 | r = radeon_uvd_get_destroy_msg(rdev, |
| 222 | size -= rdev->uvd_fw->size; | 220 | R600_RING_TYPE_UVD_INDEX, handle, &fence); |
| 221 | if (r) { | ||
| 222 | DRM_ERROR("Error destroying UVD (%d)!\n", r); | ||
| 223 | continue; | ||
| 224 | } | ||
| 223 | 225 | ||
| 224 | ptr = rdev->uvd.cpu_addr; | 226 | radeon_fence_wait(fence, false); |
| 225 | ptr += rdev->uvd_fw->size; | 227 | radeon_fence_unref(&fence); |
| 226 | 228 | ||
| 227 | rdev->uvd.saved_bo = kmalloc(size, GFP_KERNEL); | 229 | rdev->uvd.filp[i] = NULL; |
| 228 | memcpy(rdev->uvd.saved_bo, ptr, size); | 230 | atomic_set(&rdev->uvd.handles[i], 0); |
| 231 | } | ||
| 232 | } | ||
| 229 | 233 | ||
| 230 | return 0; | 234 | return 0; |
| 231 | } | 235 | } |
| @@ -246,12 +250,7 @@ int radeon_uvd_resume(struct radeon_device *rdev) | |||
| 246 | ptr = rdev->uvd.cpu_addr; | 250 | ptr = rdev->uvd.cpu_addr; |
| 247 | ptr += rdev->uvd_fw->size; | 251 | ptr += rdev->uvd_fw->size; |
| 248 | 252 | ||
| 249 | if (rdev->uvd.saved_bo != NULL) { | 253 | memset(ptr, 0, size); |
| 250 | memcpy(ptr, rdev->uvd.saved_bo, size); | ||
| 251 | kfree(rdev->uvd.saved_bo); | ||
| 252 | rdev->uvd.saved_bo = NULL; | ||
| 253 | } else | ||
| 254 | memset(ptr, 0, size); | ||
| 255 | 254 | ||
| 256 | return 0; | 255 | return 0; |
| 257 | } | 256 | } |
| @@ -396,6 +395,29 @@ static int radeon_uvd_cs_msg_decode(uint32_t *msg, unsigned buf_sizes[]) | |||
| 396 | return 0; | 395 | return 0; |
| 397 | } | 396 | } |
| 398 | 397 | ||
| 398 | static int radeon_uvd_validate_codec(struct radeon_cs_parser *p, | ||
| 399 | unsigned stream_type) | ||
| 400 | { | ||
| 401 | switch (stream_type) { | ||
| 402 | case 0: /* H264 */ | ||
| 403 | case 1: /* VC1 */ | ||
| 404 | /* always supported */ | ||
| 405 | return 0; | ||
| 406 | |||
| 407 | case 3: /* MPEG2 */ | ||
| 408 | case 4: /* MPEG4 */ | ||
| 409 | /* only since UVD 3 */ | ||
| 410 | if (p->rdev->family >= CHIP_PALM) | ||
| 411 | return 0; | ||
| 412 | |||
| 413 | /* fall through */ | ||
| 414 | default: | ||
| 415 | DRM_ERROR("UVD codec not supported by hardware %d!\n", | ||
| 416 | stream_type); | ||
| 417 | return -EINVAL; | ||
| 418 | } | ||
| 419 | } | ||
| 420 | |||
| 399 | static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, | 421 | static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, |
| 400 | unsigned offset, unsigned buf_sizes[]) | 422 | unsigned offset, unsigned buf_sizes[]) |
| 401 | { | 423 | { |
| @@ -436,50 +458,70 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, | |||
| 436 | return -EINVAL; | 458 | return -EINVAL; |
| 437 | } | 459 | } |
| 438 | 460 | ||
| 439 | if (msg_type == 1) { | 461 | switch (msg_type) { |
| 440 | /* it's a decode msg, calc buffer sizes */ | 462 | case 0: |
| 441 | r = radeon_uvd_cs_msg_decode(msg, buf_sizes); | 463 | /* it's a create msg, calc image size (width * height) */ |
| 442 | /* calc image size (width * height) */ | 464 | img_size = msg[7] * msg[8]; |
| 443 | img_size = msg[6] * msg[7]; | 465 | |
| 466 | r = radeon_uvd_validate_codec(p, msg[4]); | ||
| 444 | radeon_bo_kunmap(bo); | 467 | radeon_bo_kunmap(bo); |
| 445 | if (r) | 468 | if (r) |
| 446 | return r; | 469 | return r; |
| 447 | 470 | ||
| 448 | } else if (msg_type == 2) { | 471 | /* try to alloc a new handle */ |
| 472 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { | ||
| 473 | if (atomic_read(&p->rdev->uvd.handles[i]) == handle) { | ||
| 474 | DRM_ERROR("Handle 0x%x already in use!\n", handle); | ||
| 475 | return -EINVAL; | ||
| 476 | } | ||
| 477 | |||
| 478 | if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) { | ||
| 479 | p->rdev->uvd.filp[i] = p->filp; | ||
| 480 | p->rdev->uvd.img_size[i] = img_size; | ||
| 481 | return 0; | ||
| 482 | } | ||
| 483 | } | ||
| 484 | |||
| 485 | DRM_ERROR("No more free UVD handles!\n"); | ||
| 486 | return -EINVAL; | ||
| 487 | |||
| 488 | case 1: | ||
| 489 | /* it's a decode msg, validate codec and calc buffer sizes */ | ||
| 490 | r = radeon_uvd_validate_codec(p, msg[4]); | ||
| 491 | if (!r) | ||
| 492 | r = radeon_uvd_cs_msg_decode(msg, buf_sizes); | ||
| 493 | radeon_bo_kunmap(bo); | ||
| 494 | if (r) | ||
| 495 | return r; | ||
| 496 | |||
| 497 | /* validate the handle */ | ||
| 498 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { | ||
| 499 | if (atomic_read(&p->rdev->uvd.handles[i]) == handle) { | ||
| 500 | if (p->rdev->uvd.filp[i] != p->filp) { | ||
| 501 | DRM_ERROR("UVD handle collision detected!\n"); | ||
| 502 | return -EINVAL; | ||
| 503 | } | ||
| 504 | return 0; | ||
| 505 | } | ||
| 506 | } | ||
| 507 | |||
| 508 | DRM_ERROR("Invalid UVD handle 0x%x!\n", handle); | ||
| 509 | return -ENOENT; | ||
| 510 | |||
| 511 | case 2: | ||
| 449 | /* it's a destroy msg, free the handle */ | 512 | /* it's a destroy msg, free the handle */ |
| 450 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) | 513 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) |
| 451 | atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0); | 514 | atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0); |
| 452 | radeon_bo_kunmap(bo); | 515 | radeon_bo_kunmap(bo); |
| 453 | return 0; | 516 | return 0; |
| 454 | } else { | ||
| 455 | /* it's a create msg, calc image size (width * height) */ | ||
| 456 | img_size = msg[7] * msg[8]; | ||
| 457 | radeon_bo_kunmap(bo); | ||
| 458 | 517 | ||
| 459 | if (msg_type != 0) { | 518 | default: |
| 460 | DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type); | ||
| 461 | return -EINVAL; | ||
| 462 | } | ||
| 463 | |||
| 464 | /* it's a create msg, no special handling needed */ | ||
| 465 | } | ||
| 466 | |||
| 467 | /* create or decode, validate the handle */ | ||
| 468 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { | ||
| 469 | if (atomic_read(&p->rdev->uvd.handles[i]) == handle) | ||
| 470 | return 0; | ||
| 471 | } | ||
| 472 | 519 | ||
| 473 | /* handle not found try to alloc a new one */ | 520 | DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type); |
| 474 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { | 521 | return -EINVAL; |
| 475 | if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) { | ||
| 476 | p->rdev->uvd.filp[i] = p->filp; | ||
| 477 | p->rdev->uvd.img_size[i] = img_size; | ||
| 478 | return 0; | ||
| 479 | } | ||
| 480 | } | 522 | } |
| 481 | 523 | ||
| 482 | DRM_ERROR("No more free UVD handles!\n"); | 524 | BUG(); |
| 483 | return -EINVAL; | 525 | return -EINVAL; |
| 484 | } | 526 | } |
| 485 | 527 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c index 24f849f888bb..0de5711ac508 100644 --- a/drivers/gpu/drm/radeon/radeon_vce.c +++ b/drivers/gpu/drm/radeon/radeon_vce.c | |||
| @@ -493,18 +493,27 @@ int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi, | |||
| 493 | * | 493 | * |
| 494 | * @p: parser context | 494 | * @p: parser context |
| 495 | * @handle: handle to validate | 495 | * @handle: handle to validate |
| 496 | * @allocated: allocated a new handle? | ||
| 496 | * | 497 | * |
| 497 | * Validates the handle and return the found session index or -EINVAL | 498 | * Validates the handle and return the found session index or -EINVAL |
| 498 | * we we don't have another free session index. | 499 | * we we don't have another free session index. |
| 499 | */ | 500 | */ |
| 500 | int radeon_vce_validate_handle(struct radeon_cs_parser *p, uint32_t handle) | 501 | static int radeon_vce_validate_handle(struct radeon_cs_parser *p, |
| 502 | uint32_t handle, bool *allocated) | ||
| 501 | { | 503 | { |
| 502 | unsigned i; | 504 | unsigned i; |
| 503 | 505 | ||
| 506 | *allocated = false; | ||
| 507 | |||
| 504 | /* validate the handle */ | 508 | /* validate the handle */ |
| 505 | for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { | 509 | for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { |
| 506 | if (atomic_read(&p->rdev->vce.handles[i]) == handle) | 510 | if (atomic_read(&p->rdev->vce.handles[i]) == handle) { |
| 511 | if (p->rdev->vce.filp[i] != p->filp) { | ||
| 512 | DRM_ERROR("VCE handle collision detected!\n"); | ||
| 513 | return -EINVAL; | ||
| 514 | } | ||
| 507 | return i; | 515 | return i; |
| 516 | } | ||
| 508 | } | 517 | } |
| 509 | 518 | ||
| 510 | /* handle not found try to alloc a new one */ | 519 | /* handle not found try to alloc a new one */ |
| @@ -512,6 +521,7 @@ int radeon_vce_validate_handle(struct radeon_cs_parser *p, uint32_t handle) | |||
| 512 | if (!atomic_cmpxchg(&p->rdev->vce.handles[i], 0, handle)) { | 521 | if (!atomic_cmpxchg(&p->rdev->vce.handles[i], 0, handle)) { |
| 513 | p->rdev->vce.filp[i] = p->filp; | 522 | p->rdev->vce.filp[i] = p->filp; |
| 514 | p->rdev->vce.img_size[i] = 0; | 523 | p->rdev->vce.img_size[i] = 0; |
| 524 | *allocated = true; | ||
| 515 | return i; | 525 | return i; |
| 516 | } | 526 | } |
| 517 | } | 527 | } |
| @@ -529,10 +539,10 @@ int radeon_vce_validate_handle(struct radeon_cs_parser *p, uint32_t handle) | |||
| 529 | int radeon_vce_cs_parse(struct radeon_cs_parser *p) | 539 | int radeon_vce_cs_parse(struct radeon_cs_parser *p) |
| 530 | { | 540 | { |
| 531 | int session_idx = -1; | 541 | int session_idx = -1; |
| 532 | bool destroyed = false; | 542 | bool destroyed = false, created = false, allocated = false; |
| 533 | uint32_t tmp, handle = 0; | 543 | uint32_t tmp, handle = 0; |
| 534 | uint32_t *size = &tmp; | 544 | uint32_t *size = &tmp; |
| 535 | int i, r; | 545 | int i, r = 0; |
| 536 | 546 | ||
| 537 | while (p->idx < p->chunk_ib->length_dw) { | 547 | while (p->idx < p->chunk_ib->length_dw) { |
| 538 | uint32_t len = radeon_get_ib_value(p, p->idx); | 548 | uint32_t len = radeon_get_ib_value(p, p->idx); |
| @@ -540,18 +550,21 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p) | |||
| 540 | 550 | ||
| 541 | if ((len < 8) || (len & 3)) { | 551 | if ((len < 8) || (len & 3)) { |
| 542 | DRM_ERROR("invalid VCE command length (%d)!\n", len); | 552 | DRM_ERROR("invalid VCE command length (%d)!\n", len); |
| 543 | return -EINVAL; | 553 | r = -EINVAL; |
| 554 | goto out; | ||
| 544 | } | 555 | } |
| 545 | 556 | ||
| 546 | if (destroyed) { | 557 | if (destroyed) { |
| 547 | DRM_ERROR("No other command allowed after destroy!\n"); | 558 | DRM_ERROR("No other command allowed after destroy!\n"); |
| 548 | return -EINVAL; | 559 | r = -EINVAL; |
| 560 | goto out; | ||
| 549 | } | 561 | } |
| 550 | 562 | ||
| 551 | switch (cmd) { | 563 | switch (cmd) { |
| 552 | case 0x00000001: // session | 564 | case 0x00000001: // session |
| 553 | handle = radeon_get_ib_value(p, p->idx + 2); | 565 | handle = radeon_get_ib_value(p, p->idx + 2); |
| 554 | session_idx = radeon_vce_validate_handle(p, handle); | 566 | session_idx = radeon_vce_validate_handle(p, handle, |
| 567 | &allocated); | ||
| 555 | if (session_idx < 0) | 568 | if (session_idx < 0) |
| 556 | return session_idx; | 569 | return session_idx; |
| 557 | size = &p->rdev->vce.img_size[session_idx]; | 570 | size = &p->rdev->vce.img_size[session_idx]; |
| @@ -561,6 +574,13 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p) | |||
| 561 | break; | 574 | break; |
| 562 | 575 | ||
| 563 | case 0x01000001: // create | 576 | case 0x01000001: // create |
| 577 | created = true; | ||
| 578 | if (!allocated) { | ||
| 579 | DRM_ERROR("Handle already in use!\n"); | ||
| 580 | r = -EINVAL; | ||
| 581 | goto out; | ||
| 582 | } | ||
| 583 | |||
| 564 | *size = radeon_get_ib_value(p, p->idx + 8) * | 584 | *size = radeon_get_ib_value(p, p->idx + 8) * |
| 565 | radeon_get_ib_value(p, p->idx + 10) * | 585 | radeon_get_ib_value(p, p->idx + 10) * |
| 566 | 8 * 3 / 2; | 586 | 8 * 3 / 2; |
| @@ -578,12 +598,12 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p) | |||
| 578 | r = radeon_vce_cs_reloc(p, p->idx + 10, p->idx + 9, | 598 | r = radeon_vce_cs_reloc(p, p->idx + 10, p->idx + 9, |
| 579 | *size); | 599 | *size); |
| 580 | if (r) | 600 | if (r) |
| 581 | return r; | 601 | goto out; |
| 582 | 602 | ||
| 583 | r = radeon_vce_cs_reloc(p, p->idx + 12, p->idx + 11, | 603 | r = radeon_vce_cs_reloc(p, p->idx + 12, p->idx + 11, |
| 584 | *size / 3); | 604 | *size / 3); |
| 585 | if (r) | 605 | if (r) |
| 586 | return r; | 606 | goto out; |
| 587 | break; | 607 | break; |
| 588 | 608 | ||
| 589 | case 0x02000001: // destroy | 609 | case 0x02000001: // destroy |
| @@ -594,7 +614,7 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p) | |||
| 594 | r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2, | 614 | r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2, |
| 595 | *size * 2); | 615 | *size * 2); |
| 596 | if (r) | 616 | if (r) |
| 597 | return r; | 617 | goto out; |
| 598 | break; | 618 | break; |
| 599 | 619 | ||
| 600 | case 0x05000004: // video bitstream buffer | 620 | case 0x05000004: // video bitstream buffer |
| @@ -602,36 +622,47 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p) | |||
| 602 | r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2, | 622 | r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2, |
| 603 | tmp); | 623 | tmp); |
| 604 | if (r) | 624 | if (r) |
| 605 | return r; | 625 | goto out; |
| 606 | break; | 626 | break; |
| 607 | 627 | ||
| 608 | case 0x05000005: // feedback buffer | 628 | case 0x05000005: // feedback buffer |
| 609 | r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2, | 629 | r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2, |
| 610 | 4096); | 630 | 4096); |
| 611 | if (r) | 631 | if (r) |
| 612 | return r; | 632 | goto out; |
| 613 | break; | 633 | break; |
| 614 | 634 | ||
| 615 | default: | 635 | default: |
| 616 | DRM_ERROR("invalid VCE command (0x%x)!\n", cmd); | 636 | DRM_ERROR("invalid VCE command (0x%x)!\n", cmd); |
| 617 | return -EINVAL; | 637 | r = -EINVAL; |
| 638 | goto out; | ||
| 618 | } | 639 | } |
| 619 | 640 | ||
| 620 | if (session_idx == -1) { | 641 | if (session_idx == -1) { |
| 621 | DRM_ERROR("no session command at start of IB\n"); | 642 | DRM_ERROR("no session command at start of IB\n"); |
| 622 | return -EINVAL; | 643 | r = -EINVAL; |
| 644 | goto out; | ||
| 623 | } | 645 | } |
| 624 | 646 | ||
| 625 | p->idx += len / 4; | 647 | p->idx += len / 4; |
| 626 | } | 648 | } |
| 627 | 649 | ||
| 628 | if (destroyed) { | 650 | if (allocated && !created) { |
| 629 | /* IB contains a destroy msg, free the handle */ | 651 | DRM_ERROR("New session without create command!\n"); |
| 652 | r = -ENOENT; | ||
| 653 | } | ||
| 654 | |||
| 655 | out: | ||
| 656 | if ((!r && destroyed) || (r && allocated)) { | ||
| 657 | /* | ||
| 658 | * IB contains a destroy msg or we have allocated an | ||
| 659 | * handle and got an error, anyway free the handle | ||
| 660 | */ | ||
| 630 | for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) | 661 | for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) |
| 631 | atomic_cmpxchg(&p->rdev->vce.handles[i], handle, 0); | 662 | atomic_cmpxchg(&p->rdev->vce.handles[i], handle, 0); |
| 632 | } | 663 | } |
| 633 | 664 | ||
| 634 | return 0; | 665 | return r; |
| 635 | } | 666 | } |
| 636 | 667 | ||
| 637 | /** | 668 | /** |
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 01ee96acb398..c54d6313a46d 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
| @@ -921,7 +921,7 @@ static int rv770_pcie_gart_enable(struct radeon_device *rdev) | |||
| 921 | WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); | 921 | WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); |
| 922 | WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); | 922 | WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); |
| 923 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); | 923 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); |
| 924 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); | 924 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, (rdev->mc.gtt_end >> 12) - 1); |
| 925 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); | 925 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); |
| 926 | WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | | 926 | WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | |
| 927 | RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); | 927 | RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); |
diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h index 3cf1e2921545..9ef2064b1c9c 100644 --- a/drivers/gpu/drm/radeon/rv770d.h +++ b/drivers/gpu/drm/radeon/rv770d.h | |||
| @@ -989,6 +989,9 @@ | |||
| 989 | ((n) & 0x3FFF) << 16) | 989 | ((n) & 0x3FFF) << 16) |
| 990 | 990 | ||
| 991 | /* UVD */ | 991 | /* UVD */ |
| 992 | #define UVD_SEMA_ADDR_LOW 0xef00 | ||
| 993 | #define UVD_SEMA_ADDR_HIGH 0xef04 | ||
| 994 | #define UVD_SEMA_CMD 0xef08 | ||
| 992 | #define UVD_GPCOM_VCPU_CMD 0xef0c | 995 | #define UVD_GPCOM_VCPU_CMD 0xef0c |
| 993 | #define UVD_GPCOM_VCPU_DATA0 0xef10 | 996 | #define UVD_GPCOM_VCPU_DATA0 0xef10 |
| 994 | #define UVD_GPCOM_VCPU_DATA1 0xef14 | 997 | #define UVD_GPCOM_VCPU_DATA1 0xef14 |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index b1d74bc375d8..5326f753e107 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
| @@ -4303,7 +4303,7 @@ static int si_pcie_gart_enable(struct radeon_device *rdev) | |||
| 4303 | L2_CACHE_BIGK_FRAGMENT_SIZE(4)); | 4303 | L2_CACHE_BIGK_FRAGMENT_SIZE(4)); |
| 4304 | /* setup context0 */ | 4304 | /* setup context0 */ |
| 4305 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); | 4305 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); |
| 4306 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); | 4306 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, (rdev->mc.gtt_end >> 12) - 1); |
| 4307 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); | 4307 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); |
| 4308 | WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, | 4308 | WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, |
| 4309 | (u32)(rdev->dummy_page.addr >> 12)); | 4309 | (u32)(rdev->dummy_page.addr >> 12)); |
| @@ -4318,7 +4318,7 @@ static int si_pcie_gart_enable(struct radeon_device *rdev) | |||
| 4318 | /* empty context1-15 */ | 4318 | /* empty context1-15 */ |
| 4319 | /* set vm size, must be a multiple of 4 */ | 4319 | /* set vm size, must be a multiple of 4 */ |
| 4320 | WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0); | 4320 | WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0); |
| 4321 | WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn); | 4321 | WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn - 1); |
| 4322 | /* Assign the pt base to something valid for now; the pts used for | 4322 | /* Assign the pt base to something valid for now; the pts used for |
| 4323 | * the VMs are determined by the application and setup and assigned | 4323 | * the VMs are determined by the application and setup and assigned |
| 4324 | * on the fly in the vm part of radeon_gart.c | 4324 | * on the fly in the vm part of radeon_gart.c |
diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c index e72b3cb59358..c6b1cbca47fc 100644 --- a/drivers/gpu/drm/radeon/uvd_v1_0.c +++ b/drivers/gpu/drm/radeon/uvd_v1_0.c | |||
| @@ -466,18 +466,8 @@ bool uvd_v1_0_semaphore_emit(struct radeon_device *rdev, | |||
| 466 | struct radeon_semaphore *semaphore, | 466 | struct radeon_semaphore *semaphore, |
| 467 | bool emit_wait) | 467 | bool emit_wait) |
| 468 | { | 468 | { |
| 469 | uint64_t addr = semaphore->gpu_addr; | 469 | /* disable semaphores for UVD V1 hardware */ |
| 470 | 470 | return false; | |
| 471 | radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0)); | ||
| 472 | radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF); | ||
| 473 | |||
| 474 | radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0)); | ||
| 475 | radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF); | ||
| 476 | |||
| 477 | radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0)); | ||
| 478 | radeon_ring_write(ring, emit_wait ? 1 : 0); | ||
| 479 | |||
| 480 | return true; | ||
| 481 | } | 471 | } |
| 482 | 472 | ||
| 483 | /** | 473 | /** |
diff --git a/drivers/gpu/drm/radeon/uvd_v2_2.c b/drivers/gpu/drm/radeon/uvd_v2_2.c index 89193519f8a1..7ed778cec7c6 100644 --- a/drivers/gpu/drm/radeon/uvd_v2_2.c +++ b/drivers/gpu/drm/radeon/uvd_v2_2.c | |||
| @@ -60,6 +60,35 @@ void uvd_v2_2_fence_emit(struct radeon_device *rdev, | |||
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | /** | 62 | /** |
| 63 | * uvd_v2_2_semaphore_emit - emit semaphore command | ||
| 64 | * | ||
| 65 | * @rdev: radeon_device pointer | ||
| 66 | * @ring: radeon_ring pointer | ||
| 67 | * @semaphore: semaphore to emit commands for | ||
| 68 | * @emit_wait: true if we should emit a wait command | ||
| 69 | * | ||
| 70 | * Emit a semaphore command (either wait or signal) to the UVD ring. | ||
| 71 | */ | ||
| 72 | bool uvd_v2_2_semaphore_emit(struct radeon_device *rdev, | ||
| 73 | struct radeon_ring *ring, | ||
| 74 | struct radeon_semaphore *semaphore, | ||
| 75 | bool emit_wait) | ||
| 76 | { | ||
| 77 | uint64_t addr = semaphore->gpu_addr; | ||
| 78 | |||
| 79 | radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0)); | ||
| 80 | radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF); | ||
| 81 | |||
| 82 | radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0)); | ||
| 83 | radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF); | ||
| 84 | |||
| 85 | radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0)); | ||
| 86 | radeon_ring_write(ring, emit_wait ? 1 : 0); | ||
| 87 | |||
| 88 | return true; | ||
| 89 | } | ||
| 90 | |||
| 91 | /** | ||
| 63 | * uvd_v2_2_resume - memory controller programming | 92 | * uvd_v2_2_resume - memory controller programming |
| 64 | * | 93 | * |
| 65 | * @rdev: radeon_device pointer | 94 | * @rdev: radeon_device pointer |
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 1833abd7d3aa..bfad15a913a0 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c | |||
| @@ -173,7 +173,6 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) | |||
| 173 | drm->irq_enabled = true; | 173 | drm->irq_enabled = true; |
| 174 | 174 | ||
| 175 | /* syncpoints are used for full 32-bit hardware VBLANK counters */ | 175 | /* syncpoints are used for full 32-bit hardware VBLANK counters */ |
| 176 | drm->vblank_disable_immediate = true; | ||
| 177 | drm->max_vblank_count = 0xffffffff; | 176 | drm->max_vblank_count = 0xffffffff; |
| 178 | 177 | ||
| 179 | err = drm_vblank_init(drm, drm->mode_config.num_crtc); | 178 | err = drm_vblank_init(drm, drm->mode_config.num_crtc); |
