diff options
26 files changed, 227 insertions, 256 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/Makefile b/drivers/gpu/drm/amd/amdkfd/Makefile index be6246de5091..307a309110e6 100644 --- a/drivers/gpu/drm/amd/amdkfd/Makefile +++ b/drivers/gpu/drm/amd/amdkfd/Makefile | |||
| @@ -8,7 +8,6 @@ amdkfd-y := kfd_module.o kfd_device.o kfd_chardev.o kfd_topology.o \ | |||
| 8 | kfd_pasid.o kfd_doorbell.o kfd_flat_memory.o \ | 8 | kfd_pasid.o kfd_doorbell.o kfd_flat_memory.o \ |
| 9 | kfd_process.o kfd_queue.o kfd_mqd_manager.o \ | 9 | kfd_process.o kfd_queue.o kfd_mqd_manager.o \ |
| 10 | kfd_kernel_queue.o kfd_packet_manager.o \ | 10 | kfd_kernel_queue.o kfd_packet_manager.o \ |
| 11 | kfd_process_queue_manager.o kfd_device_queue_manager.o \ | 11 | kfd_process_queue_manager.o kfd_device_queue_manager.o |
| 12 | kfd_interrupt.o | ||
| 13 | 12 | ||
| 14 | obj-$(CONFIG_HSA_AMD) += amdkfd.o | 13 | obj-$(CONFIG_HSA_AMD) += amdkfd.o |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 43884ebd4303..633532a2e7ec 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c | |||
| @@ -192,13 +192,6 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, | |||
| 192 | goto kfd_topology_add_device_error; | 192 | goto kfd_topology_add_device_error; |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | if (kfd_interrupt_init(kfd)) { | ||
| 196 | dev_err(kfd_device, | ||
| 197 | "Error initializing interrupts for device (%x:%x)\n", | ||
| 198 | kfd->pdev->vendor, kfd->pdev->device); | ||
| 199 | goto kfd_interrupt_error; | ||
| 200 | } | ||
| 201 | |||
| 202 | if (!device_iommu_pasid_init(kfd)) { | 195 | if (!device_iommu_pasid_init(kfd)) { |
| 203 | dev_err(kfd_device, | 196 | dev_err(kfd_device, |
| 204 | "Error initializing iommuv2 for device (%x:%x)\n", | 197 | "Error initializing iommuv2 for device (%x:%x)\n", |
| @@ -237,8 +230,6 @@ dqm_start_error: | |||
| 237 | device_queue_manager_error: | 230 | device_queue_manager_error: |
| 238 | amd_iommu_free_device(kfd->pdev); | 231 | amd_iommu_free_device(kfd->pdev); |
| 239 | device_iommu_pasid_error: | 232 | device_iommu_pasid_error: |
| 240 | kfd_interrupt_exit(kfd); | ||
| 241 | kfd_interrupt_error: | ||
| 242 | kfd_topology_remove_device(kfd); | 233 | kfd_topology_remove_device(kfd); |
| 243 | kfd_topology_add_device_error: | 234 | kfd_topology_add_device_error: |
| 244 | kfd2kgd->fini_sa_manager(kfd->kgd); | 235 | kfd2kgd->fini_sa_manager(kfd->kgd); |
| @@ -254,7 +245,6 @@ void kgd2kfd_device_exit(struct kfd_dev *kfd) | |||
| 254 | if (kfd->init_complete) { | 245 | if (kfd->init_complete) { |
| 255 | device_queue_manager_uninit(kfd->dqm); | 246 | device_queue_manager_uninit(kfd->dqm); |
| 256 | amd_iommu_free_device(kfd->pdev); | 247 | amd_iommu_free_device(kfd->pdev); |
| 257 | kfd_interrupt_exit(kfd); | ||
| 258 | kfd_topology_remove_device(kfd); | 248 | kfd_topology_remove_device(kfd); |
| 259 | } | 249 | } |
| 260 | 250 | ||
| @@ -296,13 +286,5 @@ int kgd2kfd_resume(struct kfd_dev *kfd) | |||
| 296 | /* This is called directly from KGD at ISR. */ | 286 | /* This is called directly from KGD at ISR. */ |
| 297 | void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) | 287 | void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) |
| 298 | { | 288 | { |
| 299 | if (kfd->init_complete) { | 289 | /* Process interrupts / schedule work as necessary */ |
| 300 | spin_lock(&kfd->interrupt_lock); | ||
| 301 | |||
| 302 | if (kfd->interrupts_active | ||
| 303 | && enqueue_ih_ring_entry(kfd, ih_ring_entry)) | ||
| 304 | schedule_work(&kfd->interrupt_work); | ||
| 305 | |||
| 306 | spin_unlock(&kfd->interrupt_lock); | ||
| 307 | } | ||
| 308 | } | 290 | } |
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 9c8961d22360..30c8fda9622e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | |||
| @@ -280,7 +280,7 @@ static int create_compute_queue_nocpsch(struct device_queue_manager *dqm, | |||
| 280 | q->queue); | 280 | q->queue); |
| 281 | 281 | ||
| 282 | retval = mqd->load_mqd(mqd, q->mqd, q->pipe, | 282 | retval = mqd->load_mqd(mqd, q->mqd, q->pipe, |
| 283 | q->queue, q->properties.write_ptr); | 283 | q->queue, (uint32_t __user *) q->properties.write_ptr); |
| 284 | if (retval != 0) { | 284 | if (retval != 0) { |
| 285 | deallocate_hqd(dqm, q); | 285 | deallocate_hqd(dqm, q); |
| 286 | mqd->uninit_mqd(mqd, q->mqd, q->mqd_mem_obj); | 286 | mqd->uninit_mqd(mqd, q->mqd, q->mqd_mem_obj); |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c deleted file mode 100644 index 5b999095a1f7..000000000000 --- a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c +++ /dev/null | |||
| @@ -1,176 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2014 Advanced Micro Devices, Inc. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice shall be included in | ||
| 12 | * all copies or substantial portions of the Software. | ||
| 13 | * | ||
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 21 | */ | ||
| 22 | |||
| 23 | /* | ||
| 24 | * KFD Interrupts. | ||
| 25 | * | ||
| 26 | * AMD GPUs deliver interrupts by pushing an interrupt description onto the | ||
| 27 | * interrupt ring and then sending an interrupt. KGD receives the interrupt | ||
| 28 | * in ISR and sends us a pointer to each new entry on the interrupt ring. | ||
| 29 | * | ||
| 30 | * We generally can't process interrupt-signaled events from ISR, so we call | ||
| 31 | * out to each interrupt client module (currently only the scheduler) to ask if | ||
| 32 | * each interrupt is interesting. If they return true, then it requires further | ||
| 33 | * processing so we copy it to an internal interrupt ring and call each | ||
| 34 | * interrupt client again from a work-queue. | ||
| 35 | * | ||
| 36 | * There's no acknowledgment for the interrupts we use. The hardware simply | ||
| 37 | * queues a new interrupt each time without waiting. | ||
| 38 | * | ||
| 39 | * The fixed-size internal queue means that it's possible for us to lose | ||
| 40 | * interrupts because we have no back-pressure to the hardware. | ||
| 41 | */ | ||
| 42 | |||
| 43 | #include <linux/slab.h> | ||
| 44 | #include <linux/device.h> | ||
| 45 | #include "kfd_priv.h" | ||
| 46 | |||
| 47 | #define KFD_INTERRUPT_RING_SIZE 256 | ||
| 48 | |||
| 49 | static void interrupt_wq(struct work_struct *); | ||
| 50 | |||
| 51 | int kfd_interrupt_init(struct kfd_dev *kfd) | ||
| 52 | { | ||
| 53 | void *interrupt_ring = kmalloc_array(KFD_INTERRUPT_RING_SIZE, | ||
| 54 | kfd->device_info->ih_ring_entry_size, | ||
| 55 | GFP_KERNEL); | ||
| 56 | if (!interrupt_ring) | ||
| 57 | return -ENOMEM; | ||
| 58 | |||
| 59 | kfd->interrupt_ring = interrupt_ring; | ||
| 60 | kfd->interrupt_ring_size = | ||
| 61 | KFD_INTERRUPT_RING_SIZE * kfd->device_info->ih_ring_entry_size; | ||
| 62 | atomic_set(&kfd->interrupt_ring_wptr, 0); | ||
| 63 | atomic_set(&kfd->interrupt_ring_rptr, 0); | ||
| 64 | |||
| 65 | spin_lock_init(&kfd->interrupt_lock); | ||
| 66 | |||
| 67 | INIT_WORK(&kfd->interrupt_work, interrupt_wq); | ||
| 68 | |||
| 69 | kfd->interrupts_active = true; | ||
| 70 | |||
| 71 | /* | ||
| 72 | * After this function returns, the interrupt will be enabled. This | ||
| 73 | * barrier ensures that the interrupt running on a different processor | ||
| 74 | * sees all the above writes. | ||
| 75 | */ | ||
| 76 | smp_wmb(); | ||
| 77 | |||
| 78 | return 0; | ||
| 79 | } | ||
| 80 | |||
| 81 | void kfd_interrupt_exit(struct kfd_dev *kfd) | ||
| 82 | { | ||
| 83 | /* | ||
| 84 | * Stop the interrupt handler from writing to the ring and scheduling | ||
| 85 | * workqueue items. The spinlock ensures that any interrupt running | ||
| 86 | * after we have unlocked sees interrupts_active = false. | ||
| 87 | */ | ||
| 88 | unsigned long flags; | ||
| 89 | |||
| 90 | spin_lock_irqsave(&kfd->interrupt_lock, flags); | ||
| 91 | kfd->interrupts_active = false; | ||
| 92 | spin_unlock_irqrestore(&kfd->interrupt_lock, flags); | ||
| 93 | |||
| 94 | /* | ||
| 95 | * Flush_scheduled_work ensures that there are no outstanding | ||
| 96 | * work-queue items that will access interrupt_ring. New work items | ||
| 97 | * can't be created because we stopped interrupt handling above. | ||
| 98 | */ | ||
| 99 | flush_scheduled_work(); | ||
| 100 | |||
| 101 | kfree(kfd->interrupt_ring); | ||
| 102 | } | ||
| 103 | |||
| 104 | /* | ||
| 105 | * This assumes that it can't be called concurrently with itself | ||
| 106 | * but only with dequeue_ih_ring_entry. | ||
| 107 | */ | ||
| 108 | bool enqueue_ih_ring_entry(struct kfd_dev *kfd, const void *ih_ring_entry) | ||
| 109 | { | ||
| 110 | unsigned int rptr = atomic_read(&kfd->interrupt_ring_rptr); | ||
| 111 | unsigned int wptr = atomic_read(&kfd->interrupt_ring_wptr); | ||
| 112 | |||
| 113 | if ((rptr - wptr) % kfd->interrupt_ring_size == | ||
| 114 | kfd->device_info->ih_ring_entry_size) { | ||
| 115 | /* This is very bad, the system is likely to hang. */ | ||
| 116 | dev_err_ratelimited(kfd_chardev(), | ||
| 117 | "Interrupt ring overflow, dropping interrupt.\n"); | ||
| 118 | return false; | ||
| 119 | } | ||
| 120 | |||
| 121 | memcpy(kfd->interrupt_ring + wptr, ih_ring_entry, | ||
| 122 | kfd->device_info->ih_ring_entry_size); | ||
| 123 | |||
| 124 | wptr = (wptr + kfd->device_info->ih_ring_entry_size) % | ||
| 125 | kfd->interrupt_ring_size; | ||
| 126 | smp_wmb(); /* Ensure memcpy'd data is visible before wptr update. */ | ||
| 127 | atomic_set(&kfd->interrupt_ring_wptr, wptr); | ||
| 128 | |||
| 129 | return true; | ||
| 130 | } | ||
| 131 | |||
| 132 | /* | ||
| 133 | * This assumes that it can't be called concurrently with itself | ||
| 134 | * but only with enqueue_ih_ring_entry. | ||
| 135 | */ | ||
| 136 | static bool dequeue_ih_ring_entry(struct kfd_dev *kfd, void *ih_ring_entry) | ||
| 137 | { | ||
| 138 | /* | ||
| 139 | * Assume that wait queues have an implicit barrier, i.e. anything that | ||
| 140 | * happened in the ISR before it queued work is visible. | ||
| 141 | */ | ||
| 142 | |||
| 143 | unsigned int wptr = atomic_read(&kfd->interrupt_ring_wptr); | ||
| 144 | unsigned int rptr = atomic_read(&kfd->interrupt_ring_rptr); | ||
| 145 | |||
| 146 | if (rptr == wptr) | ||
| 147 | return false; | ||
| 148 | |||
| 149 | memcpy(ih_ring_entry, kfd->interrupt_ring + rptr, | ||
| 150 | kfd->device_info->ih_ring_entry_size); | ||
| 151 | |||
| 152 | rptr = (rptr + kfd->device_info->ih_ring_entry_size) % | ||
| 153 | kfd->interrupt_ring_size; | ||
| 154 | |||
| 155 | /* | ||
| 156 | * Ensure the rptr write update is not visible until | ||
| 157 | * memcpy has finished reading. | ||
| 158 | */ | ||
| 159 | smp_mb(); | ||
| 160 | atomic_set(&kfd->interrupt_ring_rptr, rptr); | ||
| 161 | |||
| 162 | return true; | ||
| 163 | } | ||
| 164 | |||
| 165 | static void interrupt_wq(struct work_struct *work) | ||
| 166 | { | ||
| 167 | struct kfd_dev *dev = container_of(work, struct kfd_dev, | ||
| 168 | interrupt_work); | ||
| 169 | |||
| 170 | uint32_t ih_ring_entry[DIV_ROUND_UP( | ||
| 171 | dev->device_info->ih_ring_entry_size, | ||
| 172 | sizeof(uint32_t))]; | ||
| 173 | |||
| 174 | while (dequeue_ih_ring_entry(dev, ih_ring_entry)) | ||
| 175 | ; | ||
| 176 | } | ||
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index a5edb29507e3..b3dc13c83169 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h | |||
| @@ -135,22 +135,10 @@ struct kfd_dev { | |||
| 135 | 135 | ||
| 136 | struct kgd2kfd_shared_resources shared_resources; | 136 | struct kgd2kfd_shared_resources shared_resources; |
| 137 | 137 | ||
| 138 | void *interrupt_ring; | ||
| 139 | size_t interrupt_ring_size; | ||
| 140 | atomic_t interrupt_ring_rptr; | ||
| 141 | atomic_t interrupt_ring_wptr; | ||
| 142 | struct work_struct interrupt_work; | ||
| 143 | spinlock_t interrupt_lock; | ||
| 144 | |||
| 145 | /* QCM Device instance */ | 138 | /* QCM Device instance */ |
| 146 | struct device_queue_manager *dqm; | 139 | struct device_queue_manager *dqm; |
| 147 | 140 | ||
| 148 | bool init_complete; | 141 | bool init_complete; |
| 149 | /* | ||
| 150 | * Interrupts of interest to KFD are copied | ||
| 151 | * from the HW ring into a SW ring. | ||
| 152 | */ | ||
| 153 | bool interrupts_active; | ||
| 154 | }; | 142 | }; |
| 155 | 143 | ||
| 156 | /* KGD2KFD callbacks */ | 144 | /* KGD2KFD callbacks */ |
| @@ -531,10 +519,7 @@ struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev); | |||
| 531 | struct kfd_dev *kfd_topology_enum_kfd_devices(uint8_t idx); | 519 | struct kfd_dev *kfd_topology_enum_kfd_devices(uint8_t idx); |
| 532 | 520 | ||
| 533 | /* Interrupts */ | 521 | /* Interrupts */ |
| 534 | int kfd_interrupt_init(struct kfd_dev *dev); | ||
| 535 | void kfd_interrupt_exit(struct kfd_dev *dev); | ||
| 536 | void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry); | 522 | void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry); |
| 537 | bool enqueue_ih_ring_entry(struct kfd_dev *kfd, const void *ih_ring_entry); | ||
| 538 | 523 | ||
| 539 | /* Power Management */ | 524 | /* Power Management */ |
| 540 | void kgd2kfd_suspend(struct kfd_dev *kfd); | 525 | void kgd2kfd_suspend(struct kfd_dev *kfd); |
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 52ce26d6b4fb..cf775a4449c1 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
| @@ -741,7 +741,9 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) | |||
| 741 | int i, j, rc = 0; | 741 | int i, j, rc = 0; |
| 742 | int start; | 742 | int start; |
| 743 | 743 | ||
| 744 | drm_modeset_lock_all(dev); | 744 | if (__drm_modeset_lock_all(dev, !!oops_in_progress)) { |
| 745 | return -EBUSY; | ||
| 746 | } | ||
| 745 | if (!drm_fb_helper_is_bound(fb_helper)) { | 747 | if (!drm_fb_helper_is_bound(fb_helper)) { |
| 746 | drm_modeset_unlock_all(dev); | 748 | drm_modeset_unlock_all(dev); |
| 747 | return -EBUSY; | 749 | return -EBUSY; |
| @@ -915,7 +917,9 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, | |||
| 915 | int ret = 0; | 917 | int ret = 0; |
| 916 | int i; | 918 | int i; |
| 917 | 919 | ||
| 918 | drm_modeset_lock_all(dev); | 920 | if (__drm_modeset_lock_all(dev, !!oops_in_progress)) { |
| 921 | return -EBUSY; | ||
| 922 | } | ||
| 919 | if (!drm_fb_helper_is_bound(fb_helper)) { | 923 | if (!drm_fb_helper_is_bound(fb_helper)) { |
| 920 | drm_modeset_unlock_all(dev); | 924 | drm_modeset_unlock_all(dev); |
| 921 | return -EBUSY; | 925 | return -EBUSY; |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 121470a83d1a..1bcbe07cecfc 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c | |||
| @@ -645,18 +645,6 @@ static int exynos_drm_init(void) | |||
| 645 | if (!is_exynos) | 645 | if (!is_exynos) |
| 646 | return -ENODEV; | 646 | return -ENODEV; |
| 647 | 647 | ||
| 648 | /* | ||
| 649 | * Register device object only in case of Exynos SoC. | ||
| 650 | * | ||
| 651 | * Below codes resolves temporarily infinite loop issue incurred | ||
| 652 | * by Exynos drm driver when using multi-platform kernel. | ||
| 653 | * So these codes will be replaced with more generic way later. | ||
| 654 | */ | ||
| 655 | if (!of_machine_is_compatible("samsung,exynos3") && | ||
| 656 | !of_machine_is_compatible("samsung,exynos4") && | ||
| 657 | !of_machine_is_compatible("samsung,exynos5")) | ||
| 658 | return -ENODEV; | ||
| 659 | |||
| 660 | exynos_drm_pdev = platform_device_register_simple("exynos-drm", -1, | 648 | exynos_drm_pdev = platform_device_register_simple("exynos-drm", -1, |
| 661 | NULL, 0); | 649 | NULL, 0); |
| 662 | if (IS_ERR(exynos_drm_pdev)) | 650 | if (IS_ERR(exynos_drm_pdev)) |
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 5765a161abdd..98051e8e855a 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c | |||
| @@ -1669,7 +1669,6 @@ static void hdmi_mode_apply(struct hdmi_context *hdata) | |||
| 1669 | 1669 | ||
| 1670 | static void hdmiphy_conf_reset(struct hdmi_context *hdata) | 1670 | static void hdmiphy_conf_reset(struct hdmi_context *hdata) |
| 1671 | { | 1671 | { |
| 1672 | u8 buffer[2]; | ||
| 1673 | u32 reg; | 1672 | u32 reg; |
| 1674 | 1673 | ||
| 1675 | clk_disable_unprepare(hdata->res.sclk_hdmi); | 1674 | clk_disable_unprepare(hdata->res.sclk_hdmi); |
| @@ -1677,11 +1676,8 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata) | |||
| 1677 | clk_prepare_enable(hdata->res.sclk_hdmi); | 1676 | clk_prepare_enable(hdata->res.sclk_hdmi); |
| 1678 | 1677 | ||
| 1679 | /* operation mode */ | 1678 | /* operation mode */ |
| 1680 | buffer[0] = 0x1f; | 1679 | hdmiphy_reg_writeb(hdata, HDMIPHY_MODE_SET_DONE, |
| 1681 | buffer[1] = 0x00; | 1680 | HDMI_PHY_ENABLE_MODE_SET); |
| 1682 | |||
| 1683 | if (hdata->hdmiphy_port) | ||
| 1684 | i2c_master_send(hdata->hdmiphy_port, buffer, 2); | ||
| 1685 | 1681 | ||
| 1686 | if (hdata->type == HDMI_TYPE13) | 1682 | if (hdata->type == HDMI_TYPE13) |
| 1687 | reg = HDMI_V13_PHY_RSTOUT; | 1683 | reg = HDMI_V13_PHY_RSTOUT; |
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 820b76234ef4..064ed6597def 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c | |||
| @@ -1026,6 +1026,7 @@ static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos) | |||
| 1026 | static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) | 1026 | static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) |
| 1027 | { | 1027 | { |
| 1028 | struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); | 1028 | struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); |
| 1029 | int err; | ||
| 1029 | 1030 | ||
| 1030 | mutex_lock(&mixer_ctx->mixer_mutex); | 1031 | mutex_lock(&mixer_ctx->mixer_mutex); |
| 1031 | if (!mixer_ctx->powered) { | 1032 | if (!mixer_ctx->powered) { |
| @@ -1034,7 +1035,11 @@ static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) | |||
| 1034 | } | 1035 | } |
| 1035 | mutex_unlock(&mixer_ctx->mixer_mutex); | 1036 | mutex_unlock(&mixer_ctx->mixer_mutex); |
| 1036 | 1037 | ||
| 1037 | drm_vblank_get(mgr->crtc->dev, mixer_ctx->pipe); | 1038 | err = drm_vblank_get(mgr->crtc->dev, mixer_ctx->pipe); |
| 1039 | if (err < 0) { | ||
| 1040 | DRM_DEBUG_KMS("failed to acquire vblank counter\n"); | ||
| 1041 | return; | ||
| 1042 | } | ||
| 1038 | 1043 | ||
| 1039 | atomic_set(&mixer_ctx->wait_vsync_event, 1); | 1044 | atomic_set(&mixer_ctx->wait_vsync_event, 1); |
| 1040 | 1045 | ||
| @@ -1262,8 +1267,6 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data) | |||
| 1262 | return ret; | 1267 | return ret; |
| 1263 | } | 1268 | } |
| 1264 | 1269 | ||
| 1265 | pm_runtime_enable(dev); | ||
| 1266 | |||
| 1267 | return 0; | 1270 | return 0; |
| 1268 | } | 1271 | } |
| 1269 | 1272 | ||
| @@ -1272,8 +1275,6 @@ static void mixer_unbind(struct device *dev, struct device *master, void *data) | |||
| 1272 | struct mixer_context *ctx = dev_get_drvdata(dev); | 1275 | struct mixer_context *ctx = dev_get_drvdata(dev); |
| 1273 | 1276 | ||
| 1274 | mixer_mgr_remove(&ctx->manager); | 1277 | mixer_mgr_remove(&ctx->manager); |
| 1275 | |||
| 1276 | pm_runtime_disable(dev); | ||
| 1277 | } | 1278 | } |
| 1278 | 1279 | ||
| 1279 | static const struct component_ops mixer_component_ops = { | 1280 | static const struct component_ops mixer_component_ops = { |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c11603b4cf1d..76354d3ba925 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -5155,7 +5155,7 @@ static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task) | |||
| 5155 | if (!mutex_is_locked(mutex)) | 5155 | if (!mutex_is_locked(mutex)) |
| 5156 | return false; | 5156 | return false; |
| 5157 | 5157 | ||
| 5158 | #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_MUTEXES) | 5158 | #if defined(CONFIG_SMP) && !defined(CONFIG_DEBUG_MUTEXES) |
| 5159 | return mutex->owner == task; | 5159 | return mutex->owner == task; |
| 5160 | #else | 5160 | #else |
| 5161 | /* Since UP may be pre-empted, we cannot assume that we own the lock */ | 5161 | /* Since UP may be pre-empted, we cannot assume that we own the lock */ |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index d0d3dfbe6d2a..b051a238baf9 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -292,6 +292,23 @@ void gen6_enable_rps_interrupts(struct drm_device *dev) | |||
| 292 | spin_unlock_irq(&dev_priv->irq_lock); | 292 | spin_unlock_irq(&dev_priv->irq_lock); |
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | u32 gen6_sanitize_rps_pm_mask(struct drm_i915_private *dev_priv, u32 mask) | ||
| 296 | { | ||
| 297 | /* | ||
| 298 | * SNB,IVB can while VLV,CHV may hard hang on looping batchbuffer | ||
| 299 | * if GEN6_PM_UP_EI_EXPIRED is masked. | ||
| 300 | * | ||
| 301 | * TODO: verify if this can be reproduced on VLV,CHV. | ||
| 302 | */ | ||
| 303 | if (INTEL_INFO(dev_priv)->gen <= 7 && !IS_HASWELL(dev_priv)) | ||
| 304 | mask &= ~GEN6_PM_RP_UP_EI_EXPIRED; | ||
| 305 | |||
| 306 | if (INTEL_INFO(dev_priv)->gen >= 8) | ||
| 307 | mask &= ~GEN8_PMINTR_REDIRECT_TO_NON_DISP; | ||
| 308 | |||
| 309 | return mask; | ||
| 310 | } | ||
| 311 | |||
| 295 | void gen6_disable_rps_interrupts(struct drm_device *dev) | 312 | void gen6_disable_rps_interrupts(struct drm_device *dev) |
| 296 | { | 313 | { |
| 297 | struct drm_i915_private *dev_priv = dev->dev_private; | 314 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -304,8 +321,7 @@ void gen6_disable_rps_interrupts(struct drm_device *dev) | |||
| 304 | 321 | ||
| 305 | spin_lock_irq(&dev_priv->irq_lock); | 322 | spin_lock_irq(&dev_priv->irq_lock); |
| 306 | 323 | ||
| 307 | I915_WRITE(GEN6_PMINTRMSK, INTEL_INFO(dev_priv)->gen >= 8 ? | 324 | I915_WRITE(GEN6_PMINTRMSK, gen6_sanitize_rps_pm_mask(dev_priv, ~0)); |
| 308 | ~GEN8_PMINTR_REDIRECT_TO_NON_DISP : ~0); | ||
| 309 | 325 | ||
| 310 | __gen6_disable_pm_irq(dev_priv, dev_priv->pm_rps_events); | 326 | __gen6_disable_pm_irq(dev_priv, dev_priv->pm_rps_events); |
| 311 | I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) & | 327 | I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) & |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e2af1383b179..e7a16f119a29 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -9815,7 +9815,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
| 9815 | if (obj->tiling_mode != work->old_fb_obj->tiling_mode) | 9815 | if (obj->tiling_mode != work->old_fb_obj->tiling_mode) |
| 9816 | /* vlv: DISPLAY_FLIP fails to change tiling */ | 9816 | /* vlv: DISPLAY_FLIP fails to change tiling */ |
| 9817 | ring = NULL; | 9817 | ring = NULL; |
| 9818 | } else if (IS_IVYBRIDGE(dev)) { | 9818 | } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { |
| 9819 | ring = &dev_priv->ring[BCS]; | 9819 | ring = &dev_priv->ring[BCS]; |
| 9820 | } else if (INTEL_INFO(dev)->gen >= 7) { | 9820 | } else if (INTEL_INFO(dev)->gen >= 7) { |
| 9821 | ring = obj->ring; | 9821 | ring = obj->ring; |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 25fdbb16d4e0..3b40a17b8852 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
| @@ -794,6 +794,7 @@ void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); | |||
| 794 | void gen6_reset_rps_interrupts(struct drm_device *dev); | 794 | void gen6_reset_rps_interrupts(struct drm_device *dev); |
| 795 | void gen6_enable_rps_interrupts(struct drm_device *dev); | 795 | void gen6_enable_rps_interrupts(struct drm_device *dev); |
| 796 | void gen6_disable_rps_interrupts(struct drm_device *dev); | 796 | void gen6_disable_rps_interrupts(struct drm_device *dev); |
| 797 | u32 gen6_sanitize_rps_pm_mask(struct drm_i915_private *dev_priv, u32 mask); | ||
| 797 | void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv); | 798 | void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv); |
| 798 | void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv); | 799 | void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv); |
| 799 | static inline bool intel_irqs_enabled(struct drm_i915_private *dev_priv) | 800 | static inline bool intel_irqs_enabled(struct drm_i915_private *dev_priv) |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 964b28e3c630..bf814a64582a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
| @@ -4363,16 +4363,7 @@ static u32 gen6_rps_pm_mask(struct drm_i915_private *dev_priv, u8 val) | |||
| 4363 | mask |= dev_priv->pm_rps_events & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED); | 4363 | mask |= dev_priv->pm_rps_events & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED); |
| 4364 | mask &= dev_priv->pm_rps_events; | 4364 | mask &= dev_priv->pm_rps_events; |
| 4365 | 4365 | ||
| 4366 | /* IVB and SNB hard hangs on looping batchbuffer | 4366 | return gen6_sanitize_rps_pm_mask(dev_priv, ~mask); |
| 4367 | * if GEN6_PM_UP_EI_EXPIRED is masked. | ||
| 4368 | */ | ||
| 4369 | if (INTEL_INFO(dev_priv->dev)->gen <= 7 && !IS_HASWELL(dev_priv->dev)) | ||
| 4370 | mask |= GEN6_PM_RP_UP_EI_EXPIRED; | ||
| 4371 | |||
| 4372 | if (IS_GEN8(dev_priv->dev)) | ||
| 4373 | mask |= GEN8_PMINTR_REDIRECT_TO_NON_DISP; | ||
| 4374 | |||
| 4375 | return ~mask; | ||
| 4376 | } | 4367 | } |
| 4377 | 4368 | ||
| 4378 | /* gen6_set_rps is called to update the frequency request, but should also be | 4369 | /* gen6_set_rps is called to update the frequency request, but should also be |
| @@ -4441,7 +4432,8 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv) | |||
| 4441 | return; | 4432 | return; |
| 4442 | 4433 | ||
| 4443 | /* Mask turbo interrupt so that they will not come in between */ | 4434 | /* Mask turbo interrupt so that they will not come in between */ |
| 4444 | I915_WRITE(GEN6_PMINTRMSK, 0xffffffff); | 4435 | I915_WRITE(GEN6_PMINTRMSK, |
| 4436 | gen6_sanitize_rps_pm_mask(dev_priv, ~0)); | ||
| 4445 | 4437 | ||
| 4446 | vlv_force_gfx_clock(dev_priv, true); | 4438 | vlv_force_gfx_clock(dev_priv, true); |
| 4447 | 4439 | ||
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 6dcde3798b45..64fdae558d36 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c | |||
| @@ -6033,6 +6033,17 @@ void cik_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, | |||
| 6033 | radeon_ring_write(ring, 0); | 6033 | radeon_ring_write(ring, 0); |
| 6034 | radeon_ring_write(ring, 1 << vm_id); | 6034 | radeon_ring_write(ring, 1 << vm_id); |
| 6035 | 6035 | ||
| 6036 | /* wait for the invalidate to complete */ | ||
| 6037 | radeon_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5)); | ||
| 6038 | radeon_ring_write(ring, (WAIT_REG_MEM_OPERATION(0) | /* wait */ | ||
| 6039 | WAIT_REG_MEM_FUNCTION(0) | /* always */ | ||
| 6040 | WAIT_REG_MEM_ENGINE(0))); /* me */ | ||
| 6041 | radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2); | ||
| 6042 | radeon_ring_write(ring, 0); | ||
| 6043 | radeon_ring_write(ring, 0); /* ref */ | ||
| 6044 | radeon_ring_write(ring, 0); /* mask */ | ||
| 6045 | radeon_ring_write(ring, 0x20); /* poll interval */ | ||
| 6046 | |||
| 6036 | /* compute doesn't have PFP */ | 6047 | /* compute doesn't have PFP */ |
| 6037 | if (usepfp) { | 6048 | if (usepfp) { |
| 6038 | /* sync PFP to ME, otherwise we might get invalid PFP reads */ | 6049 | /* sync PFP to ME, otherwise we might get invalid PFP reads */ |
diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index dde5c7e29eb2..a0133c74f4cf 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c | |||
| @@ -903,6 +903,9 @@ void cik_sdma_vm_pad_ib(struct radeon_ib *ib) | |||
| 903 | void cik_dma_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, | 903 | void cik_dma_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, |
| 904 | unsigned vm_id, uint64_t pd_addr) | 904 | unsigned vm_id, uint64_t pd_addr) |
| 905 | { | 905 | { |
| 906 | u32 extra_bits = (SDMA_POLL_REG_MEM_EXTRA_OP(0) | | ||
| 907 | SDMA_POLL_REG_MEM_EXTRA_FUNC(0)); /* always */ | ||
| 908 | |||
| 906 | radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000)); | 909 | radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000)); |
| 907 | if (vm_id < 8) { | 910 | if (vm_id < 8) { |
| 908 | radeon_ring_write(ring, (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm_id << 2)) >> 2); | 911 | radeon_ring_write(ring, (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm_id << 2)) >> 2); |
| @@ -943,5 +946,12 @@ void cik_dma_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, | |||
| 943 | radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000)); | 946 | radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000)); |
| 944 | radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2); | 947 | radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2); |
| 945 | radeon_ring_write(ring, 1 << vm_id); | 948 | radeon_ring_write(ring, 1 << vm_id); |
| 949 | |||
| 950 | radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_POLL_REG_MEM, 0, extra_bits)); | ||
| 951 | radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2); | ||
| 952 | radeon_ring_write(ring, 0); | ||
| 953 | radeon_ring_write(ring, 0); /* reference */ | ||
| 954 | radeon_ring_write(ring, 0); /* mask */ | ||
| 955 | radeon_ring_write(ring, (0xfff << 16) | 10); /* retry count, poll interval */ | ||
| 946 | } | 956 | } |
| 947 | 957 | ||
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 360de9f1f491..aea48c89b241 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
| @@ -2516,6 +2516,16 @@ void cayman_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, | |||
| 2516 | radeon_ring_write(ring, PACKET0(VM_INVALIDATE_REQUEST, 0)); | 2516 | radeon_ring_write(ring, PACKET0(VM_INVALIDATE_REQUEST, 0)); |
| 2517 | radeon_ring_write(ring, 1 << vm_id); | 2517 | radeon_ring_write(ring, 1 << vm_id); |
| 2518 | 2518 | ||
| 2519 | /* wait for the invalidate to complete */ | ||
| 2520 | radeon_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5)); | ||
| 2521 | radeon_ring_write(ring, (WAIT_REG_MEM_FUNCTION(0) | /* always */ | ||
| 2522 | WAIT_REG_MEM_ENGINE(0))); /* me */ | ||
| 2523 | radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2); | ||
| 2524 | radeon_ring_write(ring, 0); | ||
| 2525 | radeon_ring_write(ring, 0); /* ref */ | ||
| 2526 | radeon_ring_write(ring, 0); /* mask */ | ||
| 2527 | radeon_ring_write(ring, 0x20); /* poll interval */ | ||
| 2528 | |||
| 2519 | /* sync PFP to ME, otherwise we might get invalid PFP reads */ | 2529 | /* sync PFP to ME, otherwise we might get invalid PFP reads */ |
| 2520 | radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); | 2530 | radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); |
| 2521 | radeon_ring_write(ring, 0x0); | 2531 | radeon_ring_write(ring, 0x0); |
diff --git a/drivers/gpu/drm/radeon/ni_dma.c b/drivers/gpu/drm/radeon/ni_dma.c index 50f88611ff60..4be2bb7cbef3 100644 --- a/drivers/gpu/drm/radeon/ni_dma.c +++ b/drivers/gpu/drm/radeon/ni_dma.c | |||
| @@ -463,5 +463,11 @@ void cayman_dma_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, | |||
| 463 | radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0)); | 463 | radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0)); |
| 464 | radeon_ring_write(ring, (0xf << 16) | (VM_INVALIDATE_REQUEST >> 2)); | 464 | radeon_ring_write(ring, (0xf << 16) | (VM_INVALIDATE_REQUEST >> 2)); |
| 465 | radeon_ring_write(ring, 1 << vm_id); | 465 | radeon_ring_write(ring, 1 << vm_id); |
| 466 | |||
| 467 | /* wait for invalidate to complete */ | ||
| 468 | radeon_ring_write(ring, DMA_SRBM_READ_PACKET); | ||
| 469 | radeon_ring_write(ring, (0xff << 20) | (VM_INVALIDATE_REQUEST >> 2)); | ||
| 470 | radeon_ring_write(ring, 0); /* mask */ | ||
| 471 | radeon_ring_write(ring, 0); /* value */ | ||
| 466 | } | 472 | } |
| 467 | 473 | ||
diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index 2e12e4d69253..ad7125486894 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h | |||
| @@ -1133,6 +1133,23 @@ | |||
| 1133 | #define PACKET3_MEM_SEMAPHORE 0x39 | 1133 | #define PACKET3_MEM_SEMAPHORE 0x39 |
| 1134 | #define PACKET3_MPEG_INDEX 0x3A | 1134 | #define PACKET3_MPEG_INDEX 0x3A |
| 1135 | #define PACKET3_WAIT_REG_MEM 0x3C | 1135 | #define PACKET3_WAIT_REG_MEM 0x3C |
| 1136 | #define WAIT_REG_MEM_FUNCTION(x) ((x) << 0) | ||
| 1137 | /* 0 - always | ||
| 1138 | * 1 - < | ||
| 1139 | * 2 - <= | ||
| 1140 | * 3 - == | ||
| 1141 | * 4 - != | ||
| 1142 | * 5 - >= | ||
| 1143 | * 6 - > | ||
| 1144 | */ | ||
| 1145 | #define WAIT_REG_MEM_MEM_SPACE(x) ((x) << 4) | ||
| 1146 | /* 0 - reg | ||
| 1147 | * 1 - mem | ||
| 1148 | */ | ||
| 1149 | #define WAIT_REG_MEM_ENGINE(x) ((x) << 8) | ||
| 1150 | /* 0 - me | ||
| 1151 | * 1 - pfp | ||
| 1152 | */ | ||
| 1136 | #define PACKET3_MEM_WRITE 0x3D | 1153 | #define PACKET3_MEM_WRITE 0x3D |
| 1137 | #define PACKET3_PFP_SYNC_ME 0x42 | 1154 | #define PACKET3_PFP_SYNC_ME 0x42 |
| 1138 | #define PACKET3_SURFACE_SYNC 0x43 | 1155 | #define PACKET3_SURFACE_SYNC 0x43 |
| @@ -1272,6 +1289,13 @@ | |||
| 1272 | (1 << 21) | \ | 1289 | (1 << 21) | \ |
| 1273 | (((n) & 0xFFFFF) << 0)) | 1290 | (((n) & 0xFFFFF) << 0)) |
| 1274 | 1291 | ||
| 1292 | #define DMA_SRBM_POLL_PACKET ((9 << 28) | \ | ||
| 1293 | (1 << 27) | \ | ||
| 1294 | (1 << 26)) | ||
| 1295 | |||
| 1296 | #define DMA_SRBM_READ_PACKET ((9 << 28) | \ | ||
| 1297 | (1 << 27)) | ||
| 1298 | |||
| 1275 | /* async DMA Packet types */ | 1299 | /* async DMA Packet types */ |
| 1276 | #define DMA_PACKET_WRITE 0x2 | 1300 | #define DMA_PACKET_WRITE 0x2 |
| 1277 | #define DMA_PACKET_COPY 0x3 | 1301 | #define DMA_PACKET_COPY 0x3 |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 850de57069be..121aff6a3b41 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c | |||
| @@ -333,6 +333,20 @@ static struct radeon_asic_ring r300_gfx_ring = { | |||
| 333 | .set_wptr = &r100_gfx_set_wptr, | 333 | .set_wptr = &r100_gfx_set_wptr, |
| 334 | }; | 334 | }; |
| 335 | 335 | ||
| 336 | static struct radeon_asic_ring rv515_gfx_ring = { | ||
| 337 | .ib_execute = &r100_ring_ib_execute, | ||
| 338 | .emit_fence = &r300_fence_ring_emit, | ||
| 339 | .emit_semaphore = &r100_semaphore_ring_emit, | ||
| 340 | .cs_parse = &r300_cs_parse, | ||
| 341 | .ring_start = &rv515_ring_start, | ||
| 342 | .ring_test = &r100_ring_test, | ||
| 343 | .ib_test = &r100_ib_test, | ||
| 344 | .is_lockup = &r100_gpu_is_lockup, | ||
| 345 | .get_rptr = &r100_gfx_get_rptr, | ||
| 346 | .get_wptr = &r100_gfx_get_wptr, | ||
| 347 | .set_wptr = &r100_gfx_set_wptr, | ||
| 348 | }; | ||
| 349 | |||
| 336 | static struct radeon_asic r300_asic = { | 350 | static struct radeon_asic r300_asic = { |
| 337 | .init = &r300_init, | 351 | .init = &r300_init, |
| 338 | .fini = &r300_fini, | 352 | .fini = &r300_fini, |
| @@ -748,7 +762,7 @@ static struct radeon_asic rv515_asic = { | |||
| 748 | .set_page = &rv370_pcie_gart_set_page, | 762 | .set_page = &rv370_pcie_gart_set_page, |
| 749 | }, | 763 | }, |
| 750 | .ring = { | 764 | .ring = { |
| 751 | [RADEON_RING_TYPE_GFX_INDEX] = &r300_gfx_ring | 765 | [RADEON_RING_TYPE_GFX_INDEX] = &rv515_gfx_ring |
| 752 | }, | 766 | }, |
| 753 | .irq = { | 767 | .irq = { |
| 754 | .set = &rs600_irq_set, | 768 | .set = &rs600_irq_set, |
| @@ -814,7 +828,7 @@ static struct radeon_asic r520_asic = { | |||
| 814 | .set_page = &rv370_pcie_gart_set_page, | 828 | .set_page = &rv370_pcie_gart_set_page, |
| 815 | }, | 829 | }, |
| 816 | .ring = { | 830 | .ring = { |
| 817 | [RADEON_RING_TYPE_GFX_INDEX] = &r300_gfx_ring | 831 | [RADEON_RING_TYPE_GFX_INDEX] = &rv515_gfx_ring |
| 818 | }, | 832 | }, |
| 819 | .irq = { | 833 | .irq = { |
| 820 | .set = &rs600_irq_set, | 834 | .set = &rs600_irq_set, |
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index a46f73737994..d0b4f7d1140d 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c | |||
| @@ -576,7 +576,7 @@ error_unreserve: | |||
| 576 | error_free: | 576 | error_free: |
| 577 | drm_free_large(vm_bos); | 577 | drm_free_large(vm_bos); |
| 578 | 578 | ||
| 579 | if (r) | 579 | if (r && r != -ERESTARTSYS) |
| 580 | DRM_ERROR("Couldn't update BO_VA (%d)\n", r); | 580 | DRM_ERROR("Couldn't update BO_VA (%d)\n", r); |
| 581 | } | 581 | } |
| 582 | 582 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 32522cc940a1..f7da8fe96a66 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
| @@ -1287,8 +1287,39 @@ dpm_failed: | |||
| 1287 | return ret; | 1287 | return ret; |
| 1288 | } | 1288 | } |
| 1289 | 1289 | ||
| 1290 | struct radeon_dpm_quirk { | ||
| 1291 | u32 chip_vendor; | ||
| 1292 | u32 chip_device; | ||
| 1293 | u32 subsys_vendor; | ||
| 1294 | u32 subsys_device; | ||
| 1295 | }; | ||
| 1296 | |||
| 1297 | /* cards with dpm stability problems */ | ||
| 1298 | static struct radeon_dpm_quirk radeon_dpm_quirk_list[] = { | ||
| 1299 | /* TURKS - https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1386534 */ | ||
| 1300 | { PCI_VENDOR_ID_ATI, 0x6759, 0x1682, 0x3195 }, | ||
| 1301 | /* TURKS - https://bugzilla.kernel.org/show_bug.cgi?id=83731 */ | ||
| 1302 | { PCI_VENDOR_ID_ATI, 0x6840, 0x1179, 0xfb81 }, | ||
| 1303 | { 0, 0, 0, 0 }, | ||
| 1304 | }; | ||
| 1305 | |||
| 1290 | int radeon_pm_init(struct radeon_device *rdev) | 1306 | int radeon_pm_init(struct radeon_device *rdev) |
| 1291 | { | 1307 | { |
| 1308 | struct radeon_dpm_quirk *p = radeon_dpm_quirk_list; | ||
| 1309 | bool disable_dpm = false; | ||
| 1310 | |||
| 1311 | /* Apply dpm quirks */ | ||
| 1312 | while (p && p->chip_device != 0) { | ||
| 1313 | if (rdev->pdev->vendor == p->chip_vendor && | ||
| 1314 | rdev->pdev->device == p->chip_device && | ||
| 1315 | rdev->pdev->subsystem_vendor == p->subsys_vendor && | ||
| 1316 | rdev->pdev->subsystem_device == p->subsys_device) { | ||
| 1317 | disable_dpm = true; | ||
| 1318 | break; | ||
| 1319 | } | ||
| 1320 | ++p; | ||
| 1321 | } | ||
| 1322 | |||
| 1292 | /* enable dpm on rv6xx+ */ | 1323 | /* enable dpm on rv6xx+ */ |
| 1293 | switch (rdev->family) { | 1324 | switch (rdev->family) { |
| 1294 | case CHIP_RV610: | 1325 | case CHIP_RV610: |
| @@ -1344,6 +1375,8 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
| 1344 | (!(rdev->flags & RADEON_IS_IGP)) && | 1375 | (!(rdev->flags & RADEON_IS_IGP)) && |
| 1345 | (!rdev->smc_fw)) | 1376 | (!rdev->smc_fw)) |
| 1346 | rdev->pm.pm_method = PM_METHOD_PROFILE; | 1377 | rdev->pm.pm_method = PM_METHOD_PROFILE; |
| 1378 | else if (disable_dpm && (radeon_dpm == -1)) | ||
| 1379 | rdev->pm.pm_method = PM_METHOD_PROFILE; | ||
| 1347 | else if (radeon_dpm == 0) | 1380 | else if (radeon_dpm == 0) |
| 1348 | rdev->pm.pm_method = PM_METHOD_PROFILE; | 1381 | rdev->pm.pm_method = PM_METHOD_PROFILE; |
| 1349 | else | 1382 | else |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 60df444bd075..5d89b874a1a2 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
| @@ -5057,6 +5057,16 @@ void si_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, | |||
| 5057 | radeon_ring_write(ring, 0); | 5057 | radeon_ring_write(ring, 0); |
| 5058 | radeon_ring_write(ring, 1 << vm_id); | 5058 | radeon_ring_write(ring, 1 << vm_id); |
| 5059 | 5059 | ||
| 5060 | /* wait for the invalidate to complete */ | ||
| 5061 | radeon_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5)); | ||
| 5062 | radeon_ring_write(ring, (WAIT_REG_MEM_FUNCTION(0) | /* always */ | ||
| 5063 | WAIT_REG_MEM_ENGINE(0))); /* me */ | ||
| 5064 | radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2); | ||
| 5065 | radeon_ring_write(ring, 0); | ||
| 5066 | radeon_ring_write(ring, 0); /* ref */ | ||
| 5067 | radeon_ring_write(ring, 0); /* mask */ | ||
| 5068 | radeon_ring_write(ring, 0x20); /* poll interval */ | ||
| 5069 | |||
| 5060 | /* sync PFP to ME, otherwise we might get invalid PFP reads */ | 5070 | /* sync PFP to ME, otherwise we might get invalid PFP reads */ |
| 5061 | radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); | 5071 | radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); |
| 5062 | radeon_ring_write(ring, 0x0); | 5072 | radeon_ring_write(ring, 0x0); |
diff --git a/drivers/gpu/drm/radeon/si_dma.c b/drivers/gpu/drm/radeon/si_dma.c index f5cc777e1c5f..aa7b872b2c43 100644 --- a/drivers/gpu/drm/radeon/si_dma.c +++ b/drivers/gpu/drm/radeon/si_dma.c | |||
| @@ -206,6 +206,14 @@ void si_dma_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, | |||
| 206 | radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0, 0)); | 206 | radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0, 0)); |
| 207 | radeon_ring_write(ring, (0xf << 16) | (VM_INVALIDATE_REQUEST >> 2)); | 207 | radeon_ring_write(ring, (0xf << 16) | (VM_INVALIDATE_REQUEST >> 2)); |
| 208 | radeon_ring_write(ring, 1 << vm_id); | 208 | radeon_ring_write(ring, 1 << vm_id); |
| 209 | |||
| 210 | /* wait for invalidate to complete */ | ||
| 211 | radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_POLL_REG_MEM, 0, 0, 0, 0)); | ||
| 212 | radeon_ring_write(ring, VM_INVALIDATE_REQUEST); | ||
| 213 | radeon_ring_write(ring, 0xff << 16); /* retry */ | ||
| 214 | radeon_ring_write(ring, 1 << vm_id); /* mask */ | ||
| 215 | radeon_ring_write(ring, 0); /* value */ | ||
| 216 | radeon_ring_write(ring, (0 << 28) | 0x20); /* func(always) | poll interval */ | ||
| 209 | } | 217 | } |
| 210 | 218 | ||
| 211 | /** | 219 | /** |
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 32e354b8b0ab..eff8a6444956 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c | |||
| @@ -2908,6 +2908,22 @@ static int si_init_smc_spll_table(struct radeon_device *rdev) | |||
| 2908 | return ret; | 2908 | return ret; |
| 2909 | } | 2909 | } |
| 2910 | 2910 | ||
| 2911 | struct si_dpm_quirk { | ||
| 2912 | u32 chip_vendor; | ||
| 2913 | u32 chip_device; | ||
| 2914 | u32 subsys_vendor; | ||
| 2915 | u32 subsys_device; | ||
| 2916 | u32 max_sclk; | ||
| 2917 | u32 max_mclk; | ||
| 2918 | }; | ||
| 2919 | |||
| 2920 | /* cards with dpm stability problems */ | ||
| 2921 | static struct si_dpm_quirk si_dpm_quirk_list[] = { | ||
| 2922 | /* PITCAIRN - https://bugs.freedesktop.org/show_bug.cgi?id=76490 */ | ||
| 2923 | { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 }, | ||
| 2924 | { 0, 0, 0, 0 }, | ||
| 2925 | }; | ||
| 2926 | |||
| 2911 | static void si_apply_state_adjust_rules(struct radeon_device *rdev, | 2927 | static void si_apply_state_adjust_rules(struct radeon_device *rdev, |
| 2912 | struct radeon_ps *rps) | 2928 | struct radeon_ps *rps) |
| 2913 | { | 2929 | { |
| @@ -2918,7 +2934,22 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, | |||
| 2918 | u32 mclk, sclk; | 2934 | u32 mclk, sclk; |
| 2919 | u16 vddc, vddci; | 2935 | u16 vddc, vddci; |
| 2920 | u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc; | 2936 | u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc; |
| 2937 | u32 max_sclk = 0, max_mclk = 0; | ||
| 2921 | int i; | 2938 | int i; |
| 2939 | struct si_dpm_quirk *p = si_dpm_quirk_list; | ||
| 2940 | |||
| 2941 | /* Apply dpm quirks */ | ||
| 2942 | while (p && p->chip_device != 0) { | ||
| 2943 | if (rdev->pdev->vendor == p->chip_vendor && | ||
| 2944 | rdev->pdev->device == p->chip_device && | ||
| 2945 | rdev->pdev->subsystem_vendor == p->subsys_vendor && | ||
| 2946 | rdev->pdev->subsystem_device == p->subsys_device) { | ||
| 2947 | max_sclk = p->max_sclk; | ||
| 2948 | max_mclk = p->max_mclk; | ||
| 2949 | break; | ||
| 2950 | } | ||
| 2951 | ++p; | ||
| 2952 | } | ||
| 2922 | 2953 | ||
| 2923 | if ((rdev->pm.dpm.new_active_crtc_count > 1) || | 2954 | if ((rdev->pm.dpm.new_active_crtc_count > 1) || |
| 2924 | ni_dpm_vblank_too_short(rdev)) | 2955 | ni_dpm_vblank_too_short(rdev)) |
| @@ -2972,6 +3003,14 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, | |||
| 2972 | if (ps->performance_levels[i].mclk > max_mclk_vddc) | 3003 | if (ps->performance_levels[i].mclk > max_mclk_vddc) |
| 2973 | ps->performance_levels[i].mclk = max_mclk_vddc; | 3004 | ps->performance_levels[i].mclk = max_mclk_vddc; |
| 2974 | } | 3005 | } |
| 3006 | if (max_mclk) { | ||
| 3007 | if (ps->performance_levels[i].mclk > max_mclk) | ||
| 3008 | ps->performance_levels[i].mclk = max_mclk; | ||
| 3009 | } | ||
| 3010 | if (max_sclk) { | ||
| 3011 | if (ps->performance_levels[i].sclk > max_sclk) | ||
| 3012 | ps->performance_levels[i].sclk = max_sclk; | ||
| 3013 | } | ||
| 2975 | } | 3014 | } |
| 2976 | 3015 | ||
| 2977 | /* XXX validate the min clocks required for display */ | 3016 | /* XXX validate the min clocks required for display */ |
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 4069be89e585..84999242c747 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h | |||
| @@ -1632,6 +1632,23 @@ | |||
| 1632 | #define PACKET3_MPEG_INDEX 0x3A | 1632 | #define PACKET3_MPEG_INDEX 0x3A |
| 1633 | #define PACKET3_COPY_DW 0x3B | 1633 | #define PACKET3_COPY_DW 0x3B |
| 1634 | #define PACKET3_WAIT_REG_MEM 0x3C | 1634 | #define PACKET3_WAIT_REG_MEM 0x3C |
| 1635 | #define WAIT_REG_MEM_FUNCTION(x) ((x) << 0) | ||
| 1636 | /* 0 - always | ||
| 1637 | * 1 - < | ||
| 1638 | * 2 - <= | ||
| 1639 | * 3 - == | ||
| 1640 | * 4 - != | ||
| 1641 | * 5 - >= | ||
| 1642 | * 6 - > | ||
| 1643 | */ | ||
| 1644 | #define WAIT_REG_MEM_MEM_SPACE(x) ((x) << 4) | ||
| 1645 | /* 0 - reg | ||
| 1646 | * 1 - mem | ||
| 1647 | */ | ||
| 1648 | #define WAIT_REG_MEM_ENGINE(x) ((x) << 8) | ||
| 1649 | /* 0 - me | ||
| 1650 | * 1 - pfp | ||
| 1651 | */ | ||
| 1635 | #define PACKET3_MEM_WRITE 0x3D | 1652 | #define PACKET3_MEM_WRITE 0x3D |
| 1636 | #define PACKET3_COPY_DATA 0x40 | 1653 | #define PACKET3_COPY_DATA 0x40 |
| 1637 | #define PACKET3_CP_DMA 0x41 | 1654 | #define PACKET3_CP_DMA 0x41 |
| @@ -1835,6 +1852,7 @@ | |||
| 1835 | #define DMA_PACKET_TRAP 0x7 | 1852 | #define DMA_PACKET_TRAP 0x7 |
| 1836 | #define DMA_PACKET_SRBM_WRITE 0x9 | 1853 | #define DMA_PACKET_SRBM_WRITE 0x9 |
| 1837 | #define DMA_PACKET_CONSTANT_FILL 0xd | 1854 | #define DMA_PACKET_CONSTANT_FILL 0xd |
| 1855 | #define DMA_PACKET_POLL_REG_MEM 0xe | ||
| 1838 | #define DMA_PACKET_NOP 0xf | 1856 | #define DMA_PACKET_NOP 0xf |
| 1839 | 1857 | ||
| 1840 | #define VCE_STATUS 0x20004 | 1858 | #define VCE_STATUS 0x20004 |
