diff options
202 files changed, 7441 insertions, 3196 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index d1d9ae6173b8..1b71f6ceae0a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -5910,7 +5910,7 @@ M: Ingo Molnar <mingo@redhat.com> | |||
| 5910 | M: Peter Zijlstra <peterz@infradead.org> | 5910 | M: Peter Zijlstra <peterz@infradead.org> |
| 5911 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git sched/core | 5911 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git sched/core |
| 5912 | S: Maintained | 5912 | S: Maintained |
| 5913 | F: kernel/sched* | 5913 | F: kernel/sched/ |
| 5914 | F: include/linux/sched.h | 5914 | F: include/linux/sched.h |
| 5915 | 5915 | ||
| 5916 | SCORE ARCHITECTURE | 5916 | SCORE ARCHITECTURE |
| @@ -1,7 +1,7 @@ | |||
| 1 | VERSION = 3 | 1 | VERSION = 3 |
| 2 | PATCHLEVEL = 5 | 2 | PATCHLEVEL = 5 |
| 3 | SUBLEVEL = 0 | 3 | SUBLEVEL = 0 |
| 4 | EXTRAVERSION = -rc6 | 4 | EXTRAVERSION = -rc7 |
| 5 | NAME = Saber-toothed Squirrel | 5 | NAME = Saber-toothed Squirrel |
| 6 | 6 | ||
| 7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c index e9fafcf163de..373c3c00d24c 100644 --- a/arch/arm/mach-exynos/pm_domains.c +++ b/arch/arm/mach-exynos/pm_domains.c | |||
| @@ -119,7 +119,9 @@ static __init void exynos_pm_add_dev_to_genpd(struct platform_device *pdev, | |||
| 119 | struct exynos_pm_domain *pd) | 119 | struct exynos_pm_domain *pd) |
| 120 | { | 120 | { |
| 121 | if (pdev->dev.bus) { | 121 | if (pdev->dev.bus) { |
| 122 | if (pm_genpd_add_device(&pd->pd, &pdev->dev)) | 122 | if (!pm_genpd_add_device(&pd->pd, &pdev->dev)) |
| 123 | pm_genpd_dev_need_restore(&pdev->dev, true); | ||
| 124 | else | ||
| 123 | pr_info("%s: error in adding %s device to %s power" | 125 | pr_info("%s: error in adding %s device to %s power" |
| 124 | "domain\n", __func__, dev_name(&pdev->dev), | 126 | "domain\n", __func__, dev_name(&pdev->dev), |
| 125 | pd->name); | 127 | pd->name); |
| @@ -151,9 +153,12 @@ static __init int exynos4_pm_init_power_domain(void) | |||
| 151 | if (of_have_populated_dt()) | 153 | if (of_have_populated_dt()) |
| 152 | return exynos_pm_dt_parse_domains(); | 154 | return exynos_pm_dt_parse_domains(); |
| 153 | 155 | ||
| 154 | for (idx = 0; idx < ARRAY_SIZE(exynos4_pm_domains); idx++) | 156 | for (idx = 0; idx < ARRAY_SIZE(exynos4_pm_domains); idx++) { |
| 155 | pm_genpd_init(&exynos4_pm_domains[idx]->pd, NULL, | 157 | struct exynos_pm_domain *pd = exynos4_pm_domains[idx]; |
| 156 | exynos4_pm_domains[idx]->is_off); | 158 | int on = __raw_readl(pd->base + 0x4) & S5P_INT_LOCAL_PWR_EN; |
| 159 | |||
| 160 | pm_genpd_init(&pd->pd, NULL, !on); | ||
| 161 | } | ||
| 157 | 162 | ||
| 158 | #ifdef CONFIG_S5P_DEV_FIMD0 | 163 | #ifdef CONFIG_S5P_DEV_FIMD0 |
| 159 | exynos_pm_add_dev_to_genpd(&s5p_device_fimd0, &exynos4_pd_lcd0); | 164 | exynos_pm_add_dev_to_genpd(&s5p_device_fimd0, &exynos4_pd_lcd0); |
diff --git a/arch/arm/mach-s3c24xx/clock-s3c2440.c b/arch/arm/mach-s3c24xx/clock-s3c2440.c index 414364eb426c..cb2883d553b5 100644 --- a/arch/arm/mach-s3c24xx/clock-s3c2440.c +++ b/arch/arm/mach-s3c24xx/clock-s3c2440.c | |||
| @@ -106,7 +106,7 @@ static struct clk s3c2440_clk_cam_upll = { | |||
| 106 | static struct clk s3c2440_clk_ac97 = { | 106 | static struct clk s3c2440_clk_ac97 = { |
| 107 | .name = "ac97", | 107 | .name = "ac97", |
| 108 | .enable = s3c2410_clkcon_enable, | 108 | .enable = s3c2410_clkcon_enable, |
| 109 | .ctrlbit = S3C2440_CLKCON_CAMERA, | 109 | .ctrlbit = S3C2440_CLKCON_AC97, |
| 110 | }; | 110 | }; |
| 111 | 111 | ||
| 112 | static unsigned long s3c2440_fclk_n_getrate(struct clk *clk) | 112 | static unsigned long s3c2440_fclk_n_getrate(struct clk *clk) |
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c index 33ecd0c9f0c3..b1e05ccff3ac 100644 --- a/arch/arm/plat-samsung/adc.c +++ b/arch/arm/plat-samsung/adc.c | |||
| @@ -157,11 +157,13 @@ int s3c_adc_start(struct s3c_adc_client *client, | |||
| 157 | return -EINVAL; | 157 | return -EINVAL; |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | if (client->is_ts && adc->ts_pend) | ||
| 161 | return -EAGAIN; | ||
| 162 | |||
| 163 | spin_lock_irqsave(&adc->lock, flags); | 160 | spin_lock_irqsave(&adc->lock, flags); |
| 164 | 161 | ||
| 162 | if (client->is_ts && adc->ts_pend) { | ||
| 163 | spin_unlock_irqrestore(&adc->lock, flags); | ||
| 164 | return -EAGAIN; | ||
| 165 | } | ||
| 166 | |||
| 165 | client->channel = channel; | 167 | client->channel = channel; |
| 166 | client->nr_samples = nr_samples; | 168 | client->nr_samples = nr_samples; |
| 167 | 169 | ||
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index 1d214cb9d770..6303974c2ee0 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c | |||
| @@ -126,7 +126,8 @@ struct platform_device s3c_device_adc = { | |||
| 126 | #ifdef CONFIG_CPU_S3C2440 | 126 | #ifdef CONFIG_CPU_S3C2440 |
| 127 | static struct resource s3c_camif_resource[] = { | 127 | static struct resource s3c_camif_resource[] = { |
| 128 | [0] = DEFINE_RES_MEM(S3C2440_PA_CAMIF, S3C2440_SZ_CAMIF), | 128 | [0] = DEFINE_RES_MEM(S3C2440_PA_CAMIF, S3C2440_SZ_CAMIF), |
| 129 | [1] = DEFINE_RES_IRQ(IRQ_CAM), | 129 | [1] = DEFINE_RES_IRQ(IRQ_S3C2440_CAM_C), |
| 130 | [2] = DEFINE_RES_IRQ(IRQ_S3C2440_CAM_P), | ||
| 130 | }; | 131 | }; |
| 131 | 132 | ||
| 132 | struct platform_device s3c_device_camif = { | 133 | struct platform_device s3c_device_camif = { |
diff --git a/arch/arm/plat-samsung/s5p-clock.c b/arch/arm/plat-samsung/s5p-clock.c index 031a61899bef..48a159911037 100644 --- a/arch/arm/plat-samsung/s5p-clock.c +++ b/arch/arm/plat-samsung/s5p-clock.c | |||
| @@ -37,6 +37,7 @@ struct clk clk_ext_xtal_mux = { | |||
| 37 | struct clk clk_xusbxti = { | 37 | struct clk clk_xusbxti = { |
| 38 | .name = "xusbxti", | 38 | .name = "xusbxti", |
| 39 | .id = -1, | 39 | .id = -1, |
| 40 | .rate = 24000000, | ||
| 40 | }; | 41 | }; |
| 41 | 42 | ||
| 42 | struct clk s5p_clk_27m = { | 43 | struct clk s5p_clk_27m = { |
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 88e466b159dc..43b39d61b538 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c | |||
| @@ -705,7 +705,6 @@ static void stack_proc(void *arg) | |||
| 705 | struct task_struct *from = current, *to = arg; | 705 | struct task_struct *from = current, *to = arg; |
| 706 | 706 | ||
| 707 | to->thread.saved_task = from; | 707 | to->thread.saved_task = from; |
| 708 | rcu_switch_from(from); | ||
| 709 | switch_to(from, to, from); | 708 | switch_to(from, to, from); |
| 710 | } | 709 | } |
| 711 | 710 | ||
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c index 7515cf0e1805..5db36caf4289 100644 --- a/arch/x86/kernel/vsyscall_64.c +++ b/arch/x86/kernel/vsyscall_64.c | |||
| @@ -139,6 +139,19 @@ static int addr_to_vsyscall_nr(unsigned long addr) | |||
| 139 | return nr; | 139 | return nr; |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | #ifdef CONFIG_SECCOMP | ||
| 143 | static int vsyscall_seccomp(struct task_struct *tsk, int syscall_nr) | ||
| 144 | { | ||
| 145 | if (!seccomp_mode(&tsk->seccomp)) | ||
| 146 | return 0; | ||
| 147 | task_pt_regs(tsk)->orig_ax = syscall_nr; | ||
| 148 | task_pt_regs(tsk)->ax = syscall_nr; | ||
| 149 | return __secure_computing(syscall_nr); | ||
| 150 | } | ||
| 151 | #else | ||
| 152 | #define vsyscall_seccomp(_tsk, _nr) 0 | ||
| 153 | #endif | ||
| 154 | |||
| 142 | static bool write_ok_or_segv(unsigned long ptr, size_t size) | 155 | static bool write_ok_or_segv(unsigned long ptr, size_t size) |
| 143 | { | 156 | { |
| 144 | /* | 157 | /* |
| @@ -174,6 +187,7 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) | |||
| 174 | int vsyscall_nr; | 187 | int vsyscall_nr; |
| 175 | int prev_sig_on_uaccess_error; | 188 | int prev_sig_on_uaccess_error; |
| 176 | long ret; | 189 | long ret; |
| 190 | int skip; | ||
| 177 | 191 | ||
| 178 | /* | 192 | /* |
| 179 | * No point in checking CS -- the only way to get here is a user mode | 193 | * No point in checking CS -- the only way to get here is a user mode |
| @@ -205,9 +219,6 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) | |||
| 205 | } | 219 | } |
| 206 | 220 | ||
| 207 | tsk = current; | 221 | tsk = current; |
| 208 | if (seccomp_mode(&tsk->seccomp)) | ||
| 209 | do_exit(SIGKILL); | ||
| 210 | |||
| 211 | /* | 222 | /* |
| 212 | * With a real vsyscall, page faults cause SIGSEGV. We want to | 223 | * With a real vsyscall, page faults cause SIGSEGV. We want to |
| 213 | * preserve that behavior to make writing exploits harder. | 224 | * preserve that behavior to make writing exploits harder. |
| @@ -222,8 +233,13 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) | |||
| 222 | * address 0". | 233 | * address 0". |
| 223 | */ | 234 | */ |
| 224 | ret = -EFAULT; | 235 | ret = -EFAULT; |
| 236 | skip = 0; | ||
| 225 | switch (vsyscall_nr) { | 237 | switch (vsyscall_nr) { |
| 226 | case 0: | 238 | case 0: |
| 239 | skip = vsyscall_seccomp(tsk, __NR_gettimeofday); | ||
| 240 | if (skip) | ||
| 241 | break; | ||
| 242 | |||
| 227 | if (!write_ok_or_segv(regs->di, sizeof(struct timeval)) || | 243 | if (!write_ok_or_segv(regs->di, sizeof(struct timeval)) || |
| 228 | !write_ok_or_segv(regs->si, sizeof(struct timezone))) | 244 | !write_ok_or_segv(regs->si, sizeof(struct timezone))) |
| 229 | break; | 245 | break; |
| @@ -234,6 +250,10 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) | |||
| 234 | break; | 250 | break; |
| 235 | 251 | ||
| 236 | case 1: | 252 | case 1: |
| 253 | skip = vsyscall_seccomp(tsk, __NR_time); | ||
| 254 | if (skip) | ||
| 255 | break; | ||
| 256 | |||
| 237 | if (!write_ok_or_segv(regs->di, sizeof(time_t))) | 257 | if (!write_ok_or_segv(regs->di, sizeof(time_t))) |
| 238 | break; | 258 | break; |
| 239 | 259 | ||
| @@ -241,6 +261,10 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) | |||
| 241 | break; | 261 | break; |
| 242 | 262 | ||
| 243 | case 2: | 263 | case 2: |
| 264 | skip = vsyscall_seccomp(tsk, __NR_getcpu); | ||
| 265 | if (skip) | ||
| 266 | break; | ||
| 267 | |||
| 244 | if (!write_ok_or_segv(regs->di, sizeof(unsigned)) || | 268 | if (!write_ok_or_segv(regs->di, sizeof(unsigned)) || |
| 245 | !write_ok_or_segv(regs->si, sizeof(unsigned))) | 269 | !write_ok_or_segv(regs->si, sizeof(unsigned))) |
| 246 | break; | 270 | break; |
| @@ -253,6 +277,12 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) | |||
| 253 | 277 | ||
| 254 | current_thread_info()->sig_on_uaccess_error = prev_sig_on_uaccess_error; | 278 | current_thread_info()->sig_on_uaccess_error = prev_sig_on_uaccess_error; |
| 255 | 279 | ||
| 280 | if (skip) { | ||
| 281 | if ((long)regs->ax <= 0L) /* seccomp errno emulation */ | ||
| 282 | goto do_ret; | ||
| 283 | goto done; /* seccomp trace/trap */ | ||
| 284 | } | ||
| 285 | |||
| 256 | if (ret == -EFAULT) { | 286 | if (ret == -EFAULT) { |
| 257 | /* Bad news -- userspace fed a bad pointer to a vsyscall. */ | 287 | /* Bad news -- userspace fed a bad pointer to a vsyscall. */ |
| 258 | warn_bad_vsyscall(KERN_INFO, regs, | 288 | warn_bad_vsyscall(KERN_INFO, regs, |
| @@ -271,10 +301,11 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) | |||
| 271 | 301 | ||
| 272 | regs->ax = ret; | 302 | regs->ax = ret; |
| 273 | 303 | ||
| 304 | do_ret: | ||
| 274 | /* Emulate a ret instruction. */ | 305 | /* Emulate a ret instruction. */ |
| 275 | regs->ip = caller; | 306 | regs->ip = caller; |
| 276 | regs->sp += 8; | 307 | regs->sp += 8; |
| 277 | 308 | done: | |
| 278 | return true; | 309 | return true; |
| 279 | 310 | ||
| 280 | sigsegv: | 311 | sigsegv: |
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 23ce09686418..fe6626035495 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c | |||
| @@ -638,7 +638,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data, | |||
| 638 | /* Create the new outer package and populate it */ | 638 | /* Create the new outer package and populate it */ |
| 639 | 639 | ||
| 640 | status = | 640 | status = |
| 641 | acpi_ns_wrap_with_package(data, *elements, | 641 | acpi_ns_wrap_with_package(data, return_object, |
| 642 | return_object_ptr); | 642 | return_object_ptr); |
| 643 | if (ACPI_FAILURE(status)) { | 643 | if (ACPI_FAILURE(status)) { |
| 644 | return (status); | 644 | return (status); |
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index c850de4c9a14..eff722278ff5 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
| @@ -189,10 +189,12 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) | |||
| 189 | * Processor (CPU3, 0x03, 0x00000410, 0x06) {} | 189 | * Processor (CPU3, 0x03, 0x00000410, 0x06) {} |
| 190 | * } | 190 | * } |
| 191 | * | 191 | * |
| 192 | * Ignores apic_id and always return 0 for CPU0's handle. | 192 | * Ignores apic_id and always returns 0 for the processor |
| 193 | * handle with acpi id 0 if nr_cpu_ids is 1. | ||
| 194 | * This should be the case if SMP tables are not found. | ||
| 193 | * Return -1 for other CPU's handle. | 195 | * Return -1 for other CPU's handle. |
| 194 | */ | 196 | */ |
| 195 | if (acpi_id == 0) | 197 | if (nr_cpu_ids <= 1 && acpi_id == 0) |
| 196 | return acpi_id; | 198 | return acpi_id; |
| 197 | else | 199 | else |
| 198 | return apic_id; | 200 | return apic_id; |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index bbca966f8f66..3bba65510d23 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
| @@ -1597,14 +1597,12 @@ static int loop_add(struct loop_device **l, int i) | |||
| 1597 | struct gendisk *disk; | 1597 | struct gendisk *disk; |
| 1598 | int err; | 1598 | int err; |
| 1599 | 1599 | ||
| 1600 | err = -ENOMEM; | ||
| 1600 | lo = kzalloc(sizeof(*lo), GFP_KERNEL); | 1601 | lo = kzalloc(sizeof(*lo), GFP_KERNEL); |
| 1601 | if (!lo) { | 1602 | if (!lo) |
| 1602 | err = -ENOMEM; | ||
| 1603 | goto out; | 1603 | goto out; |
| 1604 | } | ||
| 1605 | 1604 | ||
| 1606 | err = idr_pre_get(&loop_index_idr, GFP_KERNEL); | 1605 | if (!idr_pre_get(&loop_index_idr, GFP_KERNEL)) |
| 1607 | if (err < 0) | ||
| 1608 | goto out_free_dev; | 1606 | goto out_free_dev; |
| 1609 | 1607 | ||
| 1610 | if (i >= 0) { | 1608 | if (i >= 0) { |
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 0a4185279417..b130df0a1958 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <asm/smp.h> | 12 | #include <asm/smp.h> |
| 13 | #include "agp.h" | 13 | #include "agp.h" |
| 14 | #include "intel-agp.h" | 14 | #include "intel-agp.h" |
| 15 | #include <drm/intel-gtt.h> | ||
| 15 | 16 | ||
| 16 | int intel_agp_enabled; | 17 | int intel_agp_enabled; |
| 17 | EXPORT_SYMBOL(intel_agp_enabled); | 18 | EXPORT_SYMBOL(intel_agp_enabled); |
| @@ -747,7 +748,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, | |||
| 747 | 748 | ||
| 748 | bridge->capndx = cap_ptr; | 749 | bridge->capndx = cap_ptr; |
| 749 | 750 | ||
| 750 | if (intel_gmch_probe(pdev, bridge)) | 751 | if (intel_gmch_probe(pdev, NULL, bridge)) |
| 751 | goto found_gmch; | 752 | goto found_gmch; |
| 752 | 753 | ||
| 753 | for (i = 0; intel_agp_chipsets[i].name != NULL; i++) { | 754 | for (i = 0; intel_agp_chipsets[i].name != NULL; i++) { |
| @@ -824,7 +825,7 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev) | |||
| 824 | 825 | ||
| 825 | agp_remove_bridge(bridge); | 826 | agp_remove_bridge(bridge); |
| 826 | 827 | ||
| 827 | intel_gmch_remove(pdev); | 828 | intel_gmch_remove(); |
| 828 | 829 | ||
| 829 | agp_put_bridge(bridge); | 830 | agp_put_bridge(bridge); |
| 830 | } | 831 | } |
| @@ -902,17 +903,6 @@ static struct pci_device_id agp_intel_pci_table[] = { | |||
| 902 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB), | 903 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB), |
| 903 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), | 904 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), |
| 904 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), | 905 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), |
| 905 | ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB), | ||
| 906 | ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB), | ||
| 907 | ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB), | ||
| 908 | ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_HB), | ||
| 909 | ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_HB), | ||
| 910 | ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB), | ||
| 911 | ID(PCI_DEVICE_ID_INTEL_VALLEYVIEW_HB), | ||
| 912 | ID(PCI_DEVICE_ID_INTEL_HASWELL_HB), | ||
| 913 | ID(PCI_DEVICE_ID_INTEL_HASWELL_M_HB), | ||
| 914 | ID(PCI_DEVICE_ID_INTEL_HASWELL_S_HB), | ||
| 915 | ID(PCI_DEVICE_ID_INTEL_HASWELL_E_HB), | ||
| 916 | { } | 906 | { } |
| 917 | }; | 907 | }; |
| 918 | 908 | ||
diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index 8e2d9140f300..57226424690c 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h | |||
| @@ -251,7 +251,4 @@ | |||
| 251 | #define PCI_DEVICE_ID_INTEL_HASWELL_SDV 0x0c16 /* SDV */ | 251 | #define PCI_DEVICE_ID_INTEL_HASWELL_SDV 0x0c16 /* SDV */ |
| 252 | #define PCI_DEVICE_ID_INTEL_HASWELL_E_HB 0x0c04 | 252 | #define PCI_DEVICE_ID_INTEL_HASWELL_E_HB 0x0c04 |
| 253 | 253 | ||
| 254 | int intel_gmch_probe(struct pci_dev *pdev, | ||
| 255 | struct agp_bridge_data *bridge); | ||
| 256 | void intel_gmch_remove(struct pci_dev *pdev); | ||
| 257 | #endif | 254 | #endif |
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 1237e7575c3f..9ed92ef5829b 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c | |||
| @@ -66,7 +66,6 @@ static struct _intel_private { | |||
| 66 | struct pci_dev *bridge_dev; | 66 | struct pci_dev *bridge_dev; |
| 67 | u8 __iomem *registers; | 67 | u8 __iomem *registers; |
| 68 | phys_addr_t gtt_bus_addr; | 68 | phys_addr_t gtt_bus_addr; |
| 69 | phys_addr_t gma_bus_addr; | ||
| 70 | u32 PGETBL_save; | 69 | u32 PGETBL_save; |
| 71 | u32 __iomem *gtt; /* I915G */ | 70 | u32 __iomem *gtt; /* I915G */ |
| 72 | bool clear_fake_agp; /* on first access via agp, fill with scratch */ | 71 | bool clear_fake_agp; /* on first access via agp, fill with scratch */ |
| @@ -76,6 +75,7 @@ static struct _intel_private { | |||
| 76 | struct resource ifp_resource; | 75 | struct resource ifp_resource; |
| 77 | int resource_valid; | 76 | int resource_valid; |
| 78 | struct page *scratch_page; | 77 | struct page *scratch_page; |
| 78 | int refcount; | ||
| 79 | } intel_private; | 79 | } intel_private; |
| 80 | 80 | ||
| 81 | #define INTEL_GTT_GEN intel_private.driver->gen | 81 | #define INTEL_GTT_GEN intel_private.driver->gen |
| @@ -648,6 +648,7 @@ static void intel_gtt_cleanup(void) | |||
| 648 | 648 | ||
| 649 | static int intel_gtt_init(void) | 649 | static int intel_gtt_init(void) |
| 650 | { | 650 | { |
| 651 | u32 gma_addr; | ||
| 651 | u32 gtt_map_size; | 652 | u32 gtt_map_size; |
| 652 | int ret; | 653 | int ret; |
| 653 | 654 | ||
| @@ -694,6 +695,15 @@ static int intel_gtt_init(void) | |||
| 694 | return ret; | 695 | return ret; |
| 695 | } | 696 | } |
| 696 | 697 | ||
| 698 | if (INTEL_GTT_GEN <= 2) | ||
| 699 | pci_read_config_dword(intel_private.pcidev, I810_GMADDR, | ||
| 700 | &gma_addr); | ||
| 701 | else | ||
| 702 | pci_read_config_dword(intel_private.pcidev, I915_GMADDR, | ||
| 703 | &gma_addr); | ||
| 704 | |||
| 705 | intel_private.base.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); | ||
| 706 | |||
| 697 | return 0; | 707 | return 0; |
| 698 | } | 708 | } |
| 699 | 709 | ||
| @@ -767,20 +777,10 @@ static void i830_write_entry(dma_addr_t addr, unsigned int entry, | |||
| 767 | writel(addr | pte_flags, intel_private.gtt + entry); | 777 | writel(addr | pte_flags, intel_private.gtt + entry); |
| 768 | } | 778 | } |
| 769 | 779 | ||
| 770 | static bool intel_enable_gtt(void) | 780 | bool intel_enable_gtt(void) |
| 771 | { | 781 | { |
| 772 | u32 gma_addr; | ||
| 773 | u8 __iomem *reg; | 782 | u8 __iomem *reg; |
| 774 | 783 | ||
| 775 | if (INTEL_GTT_GEN <= 2) | ||
| 776 | pci_read_config_dword(intel_private.pcidev, I810_GMADDR, | ||
| 777 | &gma_addr); | ||
| 778 | else | ||
| 779 | pci_read_config_dword(intel_private.pcidev, I915_GMADDR, | ||
| 780 | &gma_addr); | ||
| 781 | |||
| 782 | intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); | ||
| 783 | |||
| 784 | if (INTEL_GTT_GEN >= 6) | 784 | if (INTEL_GTT_GEN >= 6) |
| 785 | return true; | 785 | return true; |
| 786 | 786 | ||
| @@ -823,6 +823,7 @@ static bool intel_enable_gtt(void) | |||
| 823 | 823 | ||
| 824 | return true; | 824 | return true; |
| 825 | } | 825 | } |
| 826 | EXPORT_SYMBOL(intel_enable_gtt); | ||
| 826 | 827 | ||
| 827 | static int i830_setup(void) | 828 | static int i830_setup(void) |
| 828 | { | 829 | { |
| @@ -860,7 +861,7 @@ static int intel_fake_agp_configure(void) | |||
| 860 | return -EIO; | 861 | return -EIO; |
| 861 | 862 | ||
| 862 | intel_private.clear_fake_agp = true; | 863 | intel_private.clear_fake_agp = true; |
| 863 | agp_bridge->gart_bus_addr = intel_private.gma_bus_addr; | 864 | agp_bridge->gart_bus_addr = intel_private.base.gma_bus_addr; |
| 864 | 865 | ||
| 865 | return 0; | 866 | return 0; |
| 866 | } | 867 | } |
| @@ -1182,9 +1183,17 @@ static void gen6_write_entry(dma_addr_t addr, unsigned int entry, | |||
| 1182 | static void valleyview_write_entry(dma_addr_t addr, unsigned int entry, | 1183 | static void valleyview_write_entry(dma_addr_t addr, unsigned int entry, |
| 1183 | unsigned int flags) | 1184 | unsigned int flags) |
| 1184 | { | 1185 | { |
| 1186 | unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; | ||
| 1187 | unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; | ||
| 1185 | u32 pte_flags; | 1188 | u32 pte_flags; |
| 1186 | 1189 | ||
| 1187 | pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID; | 1190 | if (type_mask == AGP_USER_MEMORY) |
| 1191 | pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID; | ||
| 1192 | else { | ||
| 1193 | pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; | ||
| 1194 | if (gfdt) | ||
| 1195 | pte_flags |= GEN6_PTE_GFDT; | ||
| 1196 | } | ||
| 1188 | 1197 | ||
| 1189 | /* gen6 has bit11-4 for physical addr bit39-32 */ | 1198 | /* gen6 has bit11-4 for physical addr bit39-32 */ |
| 1190 | addr |= (addr >> 28) & 0xff0; | 1199 | addr |= (addr >> 28) & 0xff0; |
| @@ -1244,6 +1253,7 @@ static int i9xx_setup(void) | |||
| 1244 | switch (INTEL_GTT_GEN) { | 1253 | switch (INTEL_GTT_GEN) { |
| 1245 | case 5: | 1254 | case 5: |
| 1246 | case 6: | 1255 | case 6: |
| 1256 | case 7: | ||
| 1247 | gtt_offset = MB(2); | 1257 | gtt_offset = MB(2); |
| 1248 | break; | 1258 | break; |
| 1249 | case 4: | 1259 | case 4: |
| @@ -1379,7 +1389,6 @@ static const struct intel_gtt_driver valleyview_gtt_driver = { | |||
| 1379 | .write_entry = valleyview_write_entry, | 1389 | .write_entry = valleyview_write_entry, |
| 1380 | .dma_mask_size = 40, | 1390 | .dma_mask_size = 40, |
| 1381 | .check_flags = gen6_check_flags, | 1391 | .check_flags = gen6_check_flags, |
| 1382 | .chipset_flush = i9xx_chipset_flush, | ||
| 1383 | }; | 1392 | }; |
| 1384 | 1393 | ||
| 1385 | /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of | 1394 | /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of |
| @@ -1523,14 +1532,32 @@ static int find_gmch(u16 device) | |||
| 1523 | return 1; | 1532 | return 1; |
| 1524 | } | 1533 | } |
| 1525 | 1534 | ||
| 1526 | int intel_gmch_probe(struct pci_dev *pdev, | 1535 | int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, |
| 1527 | struct agp_bridge_data *bridge) | 1536 | struct agp_bridge_data *bridge) |
| 1528 | { | 1537 | { |
| 1529 | int i, mask; | 1538 | int i, mask; |
| 1530 | intel_private.driver = NULL; | 1539 | |
| 1540 | /* | ||
| 1541 | * Can be called from the fake agp driver but also directly from | ||
| 1542 | * drm/i915.ko. Hence we need to check whether everything is set up | ||
| 1543 | * already. | ||
| 1544 | */ | ||
| 1545 | if (intel_private.driver) { | ||
| 1546 | intel_private.refcount++; | ||
| 1547 | return 1; | ||
| 1548 | } | ||
| 1531 | 1549 | ||
| 1532 | for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) { | 1550 | for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) { |
| 1533 | if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { | 1551 | if (gpu_pdev) { |
| 1552 | if (gpu_pdev->device == | ||
| 1553 | intel_gtt_chipsets[i].gmch_chip_id) { | ||
| 1554 | intel_private.pcidev = pci_dev_get(gpu_pdev); | ||
| 1555 | intel_private.driver = | ||
| 1556 | intel_gtt_chipsets[i].gtt_driver; | ||
| 1557 | |||
| 1558 | break; | ||
| 1559 | } | ||
| 1560 | } else if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { | ||
| 1534 | intel_private.driver = | 1561 | intel_private.driver = |
| 1535 | intel_gtt_chipsets[i].gtt_driver; | 1562 | intel_gtt_chipsets[i].gtt_driver; |
| 1536 | break; | 1563 | break; |
| @@ -1540,13 +1567,17 @@ int intel_gmch_probe(struct pci_dev *pdev, | |||
| 1540 | if (!intel_private.driver) | 1567 | if (!intel_private.driver) |
| 1541 | return 0; | 1568 | return 0; |
| 1542 | 1569 | ||
| 1543 | bridge->driver = &intel_fake_agp_driver; | 1570 | intel_private.refcount++; |
| 1544 | bridge->dev_private_data = &intel_private; | 1571 | |
| 1545 | bridge->dev = pdev; | 1572 | if (bridge) { |
| 1573 | bridge->driver = &intel_fake_agp_driver; | ||
| 1574 | bridge->dev_private_data = &intel_private; | ||
| 1575 | bridge->dev = bridge_pdev; | ||
| 1576 | } | ||
| 1546 | 1577 | ||
| 1547 | intel_private.bridge_dev = pci_dev_get(pdev); | 1578 | intel_private.bridge_dev = pci_dev_get(bridge_pdev); |
| 1548 | 1579 | ||
| 1549 | dev_info(&pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); | 1580 | dev_info(&bridge_pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); |
| 1550 | 1581 | ||
| 1551 | mask = intel_private.driver->dma_mask_size; | 1582 | mask = intel_private.driver->dma_mask_size; |
| 1552 | if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) | 1583 | if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) |
| @@ -1556,11 +1587,11 @@ int intel_gmch_probe(struct pci_dev *pdev, | |||
| 1556 | pci_set_consistent_dma_mask(intel_private.pcidev, | 1587 | pci_set_consistent_dma_mask(intel_private.pcidev, |
| 1557 | DMA_BIT_MASK(mask)); | 1588 | DMA_BIT_MASK(mask)); |
| 1558 | 1589 | ||
| 1559 | /*if (bridge->driver == &intel_810_driver) | 1590 | if (intel_gtt_init() != 0) { |
| 1560 | return 1;*/ | 1591 | intel_gmch_remove(); |
| 1561 | 1592 | ||
| 1562 | if (intel_gtt_init() != 0) | ||
| 1563 | return 0; | 1593 | return 0; |
| 1594 | } | ||
| 1564 | 1595 | ||
| 1565 | return 1; | 1596 | return 1; |
| 1566 | } | 1597 | } |
| @@ -1579,12 +1610,16 @@ void intel_gtt_chipset_flush(void) | |||
| 1579 | } | 1610 | } |
| 1580 | EXPORT_SYMBOL(intel_gtt_chipset_flush); | 1611 | EXPORT_SYMBOL(intel_gtt_chipset_flush); |
| 1581 | 1612 | ||
| 1582 | void intel_gmch_remove(struct pci_dev *pdev) | 1613 | void intel_gmch_remove(void) |
| 1583 | { | 1614 | { |
| 1615 | if (--intel_private.refcount) | ||
| 1616 | return; | ||
| 1617 | |||
| 1584 | if (intel_private.pcidev) | 1618 | if (intel_private.pcidev) |
| 1585 | pci_dev_put(intel_private.pcidev); | 1619 | pci_dev_put(intel_private.pcidev); |
| 1586 | if (intel_private.bridge_dev) | 1620 | if (intel_private.bridge_dev) |
| 1587 | pci_dev_put(intel_private.bridge_dev); | 1621 | pci_dev_put(intel_private.bridge_dev); |
| 1622 | intel_private.driver = NULL; | ||
| 1588 | } | 1623 | } |
| 1589 | EXPORT_SYMBOL(intel_gmch_remove); | 1624 | EXPORT_SYMBOL(intel_gmch_remove); |
| 1590 | 1625 | ||
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 65f9d231af14..7282c081fb53 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c | |||
| @@ -460,8 +460,8 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
| 460 | } | 460 | } |
| 461 | 461 | ||
| 462 | static bool ast_crtc_mode_fixup(struct drm_crtc *crtc, | 462 | static bool ast_crtc_mode_fixup(struct drm_crtc *crtc, |
| 463 | struct drm_display_mode *mode, | 463 | const struct drm_display_mode *mode, |
| 464 | struct drm_display_mode *adjusted_mode) | 464 | struct drm_display_mode *adjusted_mode) |
| 465 | { | 465 | { |
| 466 | return true; | 466 | return true; |
| 467 | } | 467 | } |
| @@ -680,7 +680,7 @@ static void ast_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
| 680 | } | 680 | } |
| 681 | 681 | ||
| 682 | static bool ast_mode_fixup(struct drm_encoder *encoder, | 682 | static bool ast_mode_fixup(struct drm_encoder *encoder, |
| 683 | struct drm_display_mode *mode, | 683 | const struct drm_display_mode *mode, |
| 684 | struct drm_display_mode *adjusted_mode) | 684 | struct drm_display_mode *adjusted_mode) |
| 685 | { | 685 | { |
| 686 | return true; | 686 | return true; |
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 100f6308c509..a44d31aa4e3c 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c | |||
| @@ -97,7 +97,7 @@ static void cirrus_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
| 97 | * to just pass that straight through, so this does nothing | 97 | * to just pass that straight through, so this does nothing |
| 98 | */ | 98 | */ |
| 99 | static bool cirrus_crtc_mode_fixup(struct drm_crtc *crtc, | 99 | static bool cirrus_crtc_mode_fixup(struct drm_crtc *crtc, |
| 100 | struct drm_display_mode *mode, | 100 | const struct drm_display_mode *mode, |
| 101 | struct drm_display_mode *adjusted_mode) | 101 | struct drm_display_mode *adjusted_mode) |
| 102 | { | 102 | { |
| 103 | return true; | 103 | return true; |
| @@ -429,8 +429,8 @@ void cirrus_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
| 429 | 429 | ||
| 430 | 430 | ||
| 431 | static bool cirrus_encoder_mode_fixup(struct drm_encoder *encoder, | 431 | static bool cirrus_encoder_mode_fixup(struct drm_encoder *encoder, |
| 432 | struct drm_display_mode *mode, | 432 | const struct drm_display_mode *mode, |
| 433 | struct drm_display_mode *adjusted_mode) | 433 | struct drm_display_mode *adjusted_mode) |
| 434 | { | 434 | { |
| 435 | return true; | 435 | return true; |
| 436 | } | 436 | } |
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 348b367debeb..b356c719f2f1 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c | |||
| @@ -641,8 +641,6 @@ int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request) | |||
| 641 | 641 | ||
| 642 | if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) | 642 | if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) |
| 643 | return -EINVAL; | 643 | return -EINVAL; |
| 644 | if (dev->queue_count) | ||
| 645 | return -EBUSY; /* Not while in use */ | ||
| 646 | 644 | ||
| 647 | /* Make sure buffers are located in AGP memory that we own */ | 645 | /* Make sure buffers are located in AGP memory that we own */ |
| 648 | valid = 0; | 646 | valid = 0; |
| @@ -704,7 +702,6 @@ int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request) | |||
| 704 | buf->next = NULL; | 702 | buf->next = NULL; |
| 705 | buf->waiting = 0; | 703 | buf->waiting = 0; |
| 706 | buf->pending = 0; | 704 | buf->pending = 0; |
| 707 | init_waitqueue_head(&buf->dma_wait); | ||
| 708 | buf->file_priv = NULL; | 705 | buf->file_priv = NULL; |
| 709 | 706 | ||
| 710 | buf->dev_priv_size = dev->driver->dev_priv_size; | 707 | buf->dev_priv_size = dev->driver->dev_priv_size; |
| @@ -796,13 +793,11 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request) | |||
| 796 | order = drm_order(request->size); | 793 | order = drm_order(request->size); |
| 797 | size = 1 << order; | 794 | size = 1 << order; |
| 798 | 795 | ||
| 799 | DRM_DEBUG("count=%d, size=%d (%d), order=%d, queue_count=%d\n", | 796 | DRM_DEBUG("count=%d, size=%d (%d), order=%d\n", |
| 800 | request->count, request->size, size, order, dev->queue_count); | 797 | request->count, request->size, size, order); |
| 801 | 798 | ||
| 802 | if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) | 799 | if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) |
| 803 | return -EINVAL; | 800 | return -EINVAL; |
| 804 | if (dev->queue_count) | ||
| 805 | return -EBUSY; /* Not while in use */ | ||
| 806 | 801 | ||
| 807 | alignment = (request->flags & _DRM_PAGE_ALIGN) | 802 | alignment = (request->flags & _DRM_PAGE_ALIGN) |
| 808 | ? PAGE_ALIGN(size) : size; | 803 | ? PAGE_ALIGN(size) : size; |
| @@ -904,7 +899,6 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request) | |||
| 904 | buf->next = NULL; | 899 | buf->next = NULL; |
| 905 | buf->waiting = 0; | 900 | buf->waiting = 0; |
| 906 | buf->pending = 0; | 901 | buf->pending = 0; |
| 907 | init_waitqueue_head(&buf->dma_wait); | ||
| 908 | buf->file_priv = NULL; | 902 | buf->file_priv = NULL; |
| 909 | 903 | ||
| 910 | buf->dev_priv_size = dev->driver->dev_priv_size; | 904 | buf->dev_priv_size = dev->driver->dev_priv_size; |
| @@ -1019,8 +1013,6 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request | |||
| 1019 | 1013 | ||
| 1020 | if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) | 1014 | if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) |
| 1021 | return -EINVAL; | 1015 | return -EINVAL; |
| 1022 | if (dev->queue_count) | ||
| 1023 | return -EBUSY; /* Not while in use */ | ||
| 1024 | 1016 | ||
| 1025 | spin_lock(&dev->count_lock); | 1017 | spin_lock(&dev->count_lock); |
| 1026 | if (dev->buf_use) { | 1018 | if (dev->buf_use) { |
| @@ -1071,7 +1063,6 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request | |||
| 1071 | buf->next = NULL; | 1063 | buf->next = NULL; |
| 1072 | buf->waiting = 0; | 1064 | buf->waiting = 0; |
| 1073 | buf->pending = 0; | 1065 | buf->pending = 0; |
| 1074 | init_waitqueue_head(&buf->dma_wait); | ||
| 1075 | buf->file_priv = NULL; | 1066 | buf->file_priv = NULL; |
| 1076 | 1067 | ||
| 1077 | buf->dev_priv_size = dev->driver->dev_priv_size; | 1068 | buf->dev_priv_size = dev->driver->dev_priv_size; |
| @@ -1177,8 +1168,6 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request | |||
| 1177 | 1168 | ||
| 1178 | if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) | 1169 | if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) |
| 1179 | return -EINVAL; | 1170 | return -EINVAL; |
| 1180 | if (dev->queue_count) | ||
| 1181 | return -EBUSY; /* Not while in use */ | ||
| 1182 | 1171 | ||
| 1183 | spin_lock(&dev->count_lock); | 1172 | spin_lock(&dev->count_lock); |
| 1184 | if (dev->buf_use) { | 1173 | if (dev->buf_use) { |
| @@ -1228,7 +1217,6 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request | |||
| 1228 | buf->next = NULL; | 1217 | buf->next = NULL; |
| 1229 | buf->waiting = 0; | 1218 | buf->waiting = 0; |
| 1230 | buf->pending = 0; | 1219 | buf->pending = 0; |
| 1231 | init_waitqueue_head(&buf->dma_wait); | ||
| 1232 | buf->file_priv = NULL; | 1220 | buf->file_priv = NULL; |
| 1233 | 1221 | ||
| 1234 | buf->dev_priv_size = dev->driver->dev_priv_size; | 1222 | buf->dev_priv_size = dev->driver->dev_priv_size; |
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 1c7a1c0d3edd..70b13fc19396 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c | |||
| @@ -46,7 +46,6 @@ static struct drm_info_list drm_debugfs_list[] = { | |||
| 46 | {"name", drm_name_info, 0}, | 46 | {"name", drm_name_info, 0}, |
| 47 | {"vm", drm_vm_info, 0}, | 47 | {"vm", drm_vm_info, 0}, |
| 48 | {"clients", drm_clients_info, 0}, | 48 | {"clients", drm_clients_info, 0}, |
| 49 | {"queues", drm_queues_info, 0}, | ||
| 50 | {"bufs", drm_bufs_info, 0}, | 49 | {"bufs", drm_bufs_info, 0}, |
| 51 | {"gem_names", drm_gem_name_info, DRIVER_GEM}, | 50 | {"gem_names", drm_gem_name_info, DRIVER_GEM}, |
| 52 | #if DRM_DEBUG_CODE | 51 | #if DRM_DEBUG_CODE |
diff --git a/drivers/gpu/drm/drm_dma.c b/drivers/gpu/drm/drm_dma.c index cfb4e333ec0f..08f5e5309b22 100644 --- a/drivers/gpu/drm/drm_dma.c +++ b/drivers/gpu/drm/drm_dma.c | |||
| @@ -120,11 +120,6 @@ void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf) | |||
| 120 | buf->pending = 0; | 120 | buf->pending = 0; |
| 121 | buf->file_priv = NULL; | 121 | buf->file_priv = NULL; |
| 122 | buf->used = 0; | 122 | buf->used = 0; |
| 123 | |||
| 124 | if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) | ||
| 125 | && waitqueue_active(&buf->dma_wait)) { | ||
| 126 | wake_up_interruptible(&buf->dma_wait); | ||
| 127 | } | ||
| 128 | } | 123 | } |
| 129 | 124 | ||
| 130 | /** | 125 | /** |
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 8a9d0792e4ec..9238de4009fa 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
| @@ -182,7 +182,6 @@ static struct drm_ioctl_desc drm_ioctls[] = { | |||
| 182 | int drm_lastclose(struct drm_device * dev) | 182 | int drm_lastclose(struct drm_device * dev) |
| 183 | { | 183 | { |
| 184 | struct drm_vma_entry *vma, *vma_temp; | 184 | struct drm_vma_entry *vma, *vma_temp; |
| 185 | int i; | ||
| 186 | 185 | ||
| 187 | DRM_DEBUG("\n"); | 186 | DRM_DEBUG("\n"); |
| 188 | 187 | ||
| @@ -228,16 +227,6 @@ int drm_lastclose(struct drm_device * dev) | |||
| 228 | kfree(vma); | 227 | kfree(vma); |
| 229 | } | 228 | } |
| 230 | 229 | ||
| 231 | if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) { | ||
| 232 | for (i = 0; i < dev->queue_count; i++) { | ||
| 233 | kfree(dev->queuelist[i]); | ||
| 234 | dev->queuelist[i] = NULL; | ||
| 235 | } | ||
| 236 | kfree(dev->queuelist); | ||
| 237 | dev->queuelist = NULL; | ||
| 238 | } | ||
| 239 | dev->queue_count = 0; | ||
| 240 | |||
| 241 | if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && | 230 | if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && |
| 242 | !drm_core_check_feature(dev, DRIVER_MODESET)) | 231 | !drm_core_check_feature(dev, DRIVER_MODESET)) |
| 243 | drm_dma_takedown(dev); | 232 | drm_dma_takedown(dev); |
| @@ -486,7 +475,7 @@ long drm_ioctl(struct file *filp, | |||
| 486 | kfree(kdata); | 475 | kfree(kdata); |
| 487 | atomic_dec(&dev->ioctl_count); | 476 | atomic_dec(&dev->ioctl_count); |
| 488 | if (retcode) | 477 | if (retcode) |
| 489 | DRM_DEBUG("ret = %x\n", retcode); | 478 | DRM_DEBUG("ret = %d\n", retcode); |
| 490 | return retcode; | 479 | return retcode; |
| 491 | } | 480 | } |
| 492 | 481 | ||
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 5683b7fdd746..f546d1e8af82 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
| @@ -228,7 +228,7 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) | |||
| 228 | int i, ret; | 228 | int i, ret; |
| 229 | for (i = 0; i < fb_helper->crtc_count; i++) { | 229 | for (i = 0; i < fb_helper->crtc_count; i++) { |
| 230 | struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; | 230 | struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; |
| 231 | ret = drm_crtc_helper_set_config(mode_set); | 231 | ret = mode_set->crtc->funcs->set_config(mode_set); |
| 232 | if (ret) | 232 | if (ret) |
| 233 | error = true; | 233 | error = true; |
| 234 | } | 234 | } |
| @@ -1353,7 +1353,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) | |||
| 1353 | struct drm_device *dev = fb_helper->dev; | 1353 | struct drm_device *dev = fb_helper->dev; |
| 1354 | int count = 0; | 1354 | int count = 0; |
| 1355 | u32 max_width, max_height, bpp_sel; | 1355 | u32 max_width, max_height, bpp_sel; |
| 1356 | bool bound = false, crtcs_bound = false; | 1356 | int bound = 0, crtcs_bound = 0; |
| 1357 | struct drm_crtc *crtc; | 1357 | struct drm_crtc *crtc; |
| 1358 | 1358 | ||
| 1359 | if (!fb_helper->fb) | 1359 | if (!fb_helper->fb) |
| @@ -1362,12 +1362,12 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) | |||
| 1362 | mutex_lock(&dev->mode_config.mutex); | 1362 | mutex_lock(&dev->mode_config.mutex); |
| 1363 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 1363 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
| 1364 | if (crtc->fb) | 1364 | if (crtc->fb) |
| 1365 | crtcs_bound = true; | 1365 | crtcs_bound++; |
| 1366 | if (crtc->fb == fb_helper->fb) | 1366 | if (crtc->fb == fb_helper->fb) |
| 1367 | bound = true; | 1367 | bound++; |
| 1368 | } | 1368 | } |
| 1369 | 1369 | ||
| 1370 | if (!bound && crtcs_bound) { | 1370 | if (bound < crtcs_bound) { |
| 1371 | fb_helper->delayed_hotplug = true; | 1371 | fb_helper->delayed_hotplug = true; |
| 1372 | mutex_unlock(&dev->mode_config.mutex); | 1372 | mutex_unlock(&dev->mode_config.mutex); |
| 1373 | return 0; | 1373 | return 0; |
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 123de28f94ef..5062eec673f1 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c | |||
| @@ -75,10 +75,6 @@ static int drm_setup(struct drm_device * dev) | |||
| 75 | 75 | ||
| 76 | dev->sigdata.lock = NULL; | 76 | dev->sigdata.lock = NULL; |
| 77 | 77 | ||
| 78 | dev->queue_count = 0; | ||
| 79 | dev->queue_reserved = 0; | ||
| 80 | dev->queue_slots = 0; | ||
| 81 | dev->queuelist = NULL; | ||
| 82 | dev->context_flag = 0; | 78 | dev->context_flag = 0; |
| 83 | dev->interrupt_flag = 0; | 79 | dev->interrupt_flag = 0; |
| 84 | dev->dma_flag = 0; | 80 | dev->dma_flag = 0; |
| @@ -144,12 +140,12 @@ int drm_open(struct inode *inode, struct file *filp) | |||
| 144 | } | 140 | } |
| 145 | if (!retcode) { | 141 | if (!retcode) { |
| 146 | mutex_lock(&dev->struct_mutex); | 142 | mutex_lock(&dev->struct_mutex); |
| 147 | if (minor->type == DRM_MINOR_LEGACY) { | 143 | if (dev->dev_mapping == NULL) |
| 148 | if (dev->dev_mapping == NULL) | 144 | dev->dev_mapping = &inode->i_data; |
| 149 | dev->dev_mapping = inode->i_mapping; | 145 | /* ihold ensures nobody can remove inode with our i_data */ |
| 150 | else if (dev->dev_mapping != inode->i_mapping) | 146 | ihold(container_of(dev->dev_mapping, struct inode, i_data)); |
| 151 | retcode = -ENODEV; | 147 | inode->i_mapping = dev->dev_mapping; |
| 152 | } | 148 | filp->f_mapping = dev->dev_mapping; |
| 153 | mutex_unlock(&dev->struct_mutex); | 149 | mutex_unlock(&dev->struct_mutex); |
| 154 | } | 150 | } |
| 155 | 151 | ||
| @@ -370,72 +366,16 @@ int drm_fasync(int fd, struct file *filp, int on) | |||
| 370 | } | 366 | } |
| 371 | EXPORT_SYMBOL(drm_fasync); | 367 | EXPORT_SYMBOL(drm_fasync); |
| 372 | 368 | ||
| 373 | /* | ||
| 374 | * Reclaim locked buffers; note that this may be a bad idea if the current | ||
| 375 | * context doesn't have the hw lock... | ||
| 376 | */ | ||
| 377 | static void drm_reclaim_locked_buffers(struct drm_device *dev, struct file *f) | ||
| 378 | { | ||
| 379 | struct drm_file *file_priv = f->private_data; | ||
| 380 | |||
| 381 | if (drm_i_have_hw_lock(dev, file_priv)) { | ||
| 382 | dev->driver->reclaim_buffers_locked(dev, file_priv); | ||
| 383 | } else { | ||
| 384 | unsigned long _end = jiffies + 3 * DRM_HZ; | ||
| 385 | int locked = 0; | ||
| 386 | |||
| 387 | drm_idlelock_take(&file_priv->master->lock); | ||
| 388 | |||
| 389 | /* | ||
| 390 | * Wait for a while. | ||
| 391 | */ | ||
| 392 | do { | ||
| 393 | spin_lock_bh(&file_priv->master->lock.spinlock); | ||
| 394 | locked = file_priv->master->lock.idle_has_lock; | ||
| 395 | spin_unlock_bh(&file_priv->master->lock.spinlock); | ||
| 396 | if (locked) | ||
| 397 | break; | ||
| 398 | schedule(); | ||
| 399 | } while (!time_after_eq(jiffies, _end)); | ||
| 400 | |||
| 401 | if (!locked) { | ||
| 402 | DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n" | ||
| 403 | "\tdriver to use reclaim_buffers_idlelocked() instead.\n" | ||
| 404 | "\tI will go on reclaiming the buffers anyway.\n"); | ||
| 405 | } | ||
| 406 | |||
| 407 | dev->driver->reclaim_buffers_locked(dev, file_priv); | ||
| 408 | drm_idlelock_release(&file_priv->master->lock); | ||
| 409 | } | ||
| 410 | } | ||
| 411 | |||
| 412 | static void drm_master_release(struct drm_device *dev, struct file *filp) | 369 | static void drm_master_release(struct drm_device *dev, struct file *filp) |
| 413 | { | 370 | { |
| 414 | struct drm_file *file_priv = filp->private_data; | 371 | struct drm_file *file_priv = filp->private_data; |
| 415 | 372 | ||
| 416 | if (dev->driver->reclaim_buffers_locked && | ||
| 417 | file_priv->master->lock.hw_lock) | ||
| 418 | drm_reclaim_locked_buffers(dev, filp); | ||
| 419 | |||
| 420 | if (dev->driver->reclaim_buffers_idlelocked && | ||
| 421 | file_priv->master->lock.hw_lock) { | ||
| 422 | drm_idlelock_take(&file_priv->master->lock); | ||
| 423 | dev->driver->reclaim_buffers_idlelocked(dev, file_priv); | ||
| 424 | drm_idlelock_release(&file_priv->master->lock); | ||
| 425 | } | ||
| 426 | |||
| 427 | |||
| 428 | if (drm_i_have_hw_lock(dev, file_priv)) { | 373 | if (drm_i_have_hw_lock(dev, file_priv)) { |
| 429 | DRM_DEBUG("File %p released, freeing lock for context %d\n", | 374 | DRM_DEBUG("File %p released, freeing lock for context %d\n", |
| 430 | filp, _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock)); | 375 | filp, _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock)); |
| 431 | drm_lock_free(&file_priv->master->lock, | 376 | drm_lock_free(&file_priv->master->lock, |
| 432 | _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock)); | 377 | _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock)); |
| 433 | } | 378 | } |
| 434 | |||
| 435 | if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && | ||
| 436 | !dev->driver->reclaim_buffers_locked) { | ||
| 437 | dev->driver->reclaim_buffers(dev, file_priv); | ||
| 438 | } | ||
| 439 | } | 379 | } |
| 440 | 380 | ||
| 441 | static void drm_events_release(struct drm_file *file_priv) | 381 | static void drm_events_release(struct drm_file *file_priv) |
| @@ -505,6 +445,9 @@ int drm_release(struct inode *inode, struct file *filp) | |||
| 505 | if (file_priv->minor->master) | 445 | if (file_priv->minor->master) |
| 506 | drm_master_release(dev, filp); | 446 | drm_master_release(dev, filp); |
| 507 | 447 | ||
| 448 | if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) | ||
| 449 | drm_core_reclaim_buffers(dev, file_priv); | ||
| 450 | |||
| 508 | drm_events_release(file_priv); | 451 | drm_events_release(file_priv); |
| 509 | 452 | ||
| 510 | if (dev->driver->driver_features & DRIVER_MODESET) | 453 | if (dev->driver->driver_features & DRIVER_MODESET) |
| @@ -566,6 +509,9 @@ int drm_release(struct inode *inode, struct file *filp) | |||
| 566 | } | 509 | } |
| 567 | } | 510 | } |
| 568 | 511 | ||
| 512 | BUG_ON(dev->dev_mapping == NULL); | ||
| 513 | iput(container_of(dev->dev_mapping, struct inode, i_data)); | ||
| 514 | |||
| 569 | /* drop the reference held my the file priv */ | 515 | /* drop the reference held my the file priv */ |
| 570 | drm_master_put(&file_priv->master); | 516 | drm_master_put(&file_priv->master); |
| 571 | file_priv->is_master = 0; | 517 | file_priv->is_master = 0; |
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index d58e69da1fb5..fbe0842038b5 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
| @@ -354,7 +354,7 @@ drm_gem_create_mmap_offset(struct drm_gem_object *obj) | |||
| 354 | 354 | ||
| 355 | /* Get a DRM GEM mmap offset allocated... */ | 355 | /* Get a DRM GEM mmap offset allocated... */ |
| 356 | list->file_offset_node = drm_mm_search_free(&mm->offset_manager, | 356 | list->file_offset_node = drm_mm_search_free(&mm->offset_manager, |
| 357 | obj->size / PAGE_SIZE, 0, 0); | 357 | obj->size / PAGE_SIZE, 0, false); |
| 358 | 358 | ||
| 359 | if (!list->file_offset_node) { | 359 | if (!list->file_offset_node) { |
| 360 | DRM_ERROR("failed to allocate offset for bo %d\n", obj->name); | 360 | DRM_ERROR("failed to allocate offset for bo %d\n", obj->name); |
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index ab1162da70f8..8928edbb94c7 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c | |||
| @@ -110,42 +110,6 @@ int drm_vm_info(struct seq_file *m, void *data) | |||
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | /** | 112 | /** |
| 113 | * Called when "/proc/dri/.../queues" is read. | ||
| 114 | */ | ||
| 115 | int drm_queues_info(struct seq_file *m, void *data) | ||
| 116 | { | ||
| 117 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
| 118 | struct drm_device *dev = node->minor->dev; | ||
| 119 | int i; | ||
| 120 | struct drm_queue *q; | ||
| 121 | |||
| 122 | mutex_lock(&dev->struct_mutex); | ||
| 123 | seq_printf(m, " ctx/flags use fin" | ||
| 124 | " blk/rw/rwf wait flushed queued" | ||
| 125 | " locks\n\n"); | ||
| 126 | for (i = 0; i < dev->queue_count; i++) { | ||
| 127 | q = dev->queuelist[i]; | ||
| 128 | atomic_inc(&q->use_count); | ||
| 129 | seq_printf(m, "%5d/0x%03x %5d %5d" | ||
| 130 | " %5d/%c%c/%c%c%c %5Zd\n", | ||
| 131 | i, | ||
| 132 | q->flags, | ||
| 133 | atomic_read(&q->use_count), | ||
| 134 | atomic_read(&q->finalization), | ||
| 135 | atomic_read(&q->block_count), | ||
| 136 | atomic_read(&q->block_read) ? 'r' : '-', | ||
| 137 | atomic_read(&q->block_write) ? 'w' : '-', | ||
| 138 | waitqueue_active(&q->read_queue) ? 'r' : '-', | ||
| 139 | waitqueue_active(&q->write_queue) ? 'w' : '-', | ||
| 140 | waitqueue_active(&q->flush_queue) ? 'f' : '-', | ||
| 141 | DRM_BUFCOUNT(&q->waitlist)); | ||
| 142 | atomic_dec(&q->use_count); | ||
| 143 | } | ||
| 144 | mutex_unlock(&dev->struct_mutex); | ||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | /** | ||
| 149 | * Called when "/proc/dri/.../bufs" is read. | 113 | * Called when "/proc/dri/.../bufs" is read. |
| 150 | */ | 114 | */ |
| 151 | int drm_bufs_info(struct seq_file *m, void *data) | 115 | int drm_bufs_info(struct seq_file *m, void *data) |
| @@ -235,7 +199,7 @@ int drm_clients_info(struct seq_file *m, void *data) | |||
| 235 | } | 199 | } |
| 236 | 200 | ||
| 237 | 201 | ||
| 238 | int drm_gem_one_name_info(int id, void *ptr, void *data) | 202 | static int drm_gem_one_name_info(int id, void *ptr, void *data) |
| 239 | { | 203 | { |
| 240 | struct drm_gem_object *obj = ptr; | 204 | struct drm_gem_object *obj = ptr; |
| 241 | struct seq_file *m = data; | 205 | struct seq_file *m = data; |
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index c798eeae0a03..03f16f352fe2 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
| @@ -974,7 +974,6 @@ EXPORT_SYMBOL(drm_vblank_off); | |||
| 974 | * drm_vblank_pre_modeset - account for vblanks across mode sets | 974 | * drm_vblank_pre_modeset - account for vblanks across mode sets |
| 975 | * @dev: DRM device | 975 | * @dev: DRM device |
| 976 | * @crtc: CRTC in question | 976 | * @crtc: CRTC in question |
| 977 | * @post: post or pre mode set? | ||
| 978 | * | 977 | * |
| 979 | * Account for vblank events across mode setting events, which will likely | 978 | * Account for vblank events across mode setting events, which will likely |
| 980 | * reset the hardware frame counter. | 979 | * reset the hardware frame counter. |
| @@ -1037,6 +1036,10 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, | |||
| 1037 | if (!dev->num_crtcs) | 1036 | if (!dev->num_crtcs) |
| 1038 | return 0; | 1037 | return 0; |
| 1039 | 1038 | ||
| 1039 | /* KMS drivers handle this internally */ | ||
| 1040 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | ||
| 1041 | return 0; | ||
| 1042 | |||
| 1040 | crtc = modeset->crtc; | 1043 | crtc = modeset->crtc; |
| 1041 | if (crtc >= dev->num_crtcs) | 1044 | if (crtc >= dev->num_crtcs) |
| 1042 | return -EINVAL; | 1045 | return -EINVAL; |
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index 521152041691..32039553e172 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c | |||
| @@ -70,10 +70,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
| 70 | lock->context, task_pid_nr(current), | 70 | lock->context, task_pid_nr(current), |
| 71 | master->lock.hw_lock->lock, lock->flags); | 71 | master->lock.hw_lock->lock, lock->flags); |
| 72 | 72 | ||
| 73 | if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE)) | ||
| 74 | if (lock->context < 0) | ||
| 75 | return -EINVAL; | ||
| 76 | |||
| 77 | add_wait_queue(&master->lock.lock_queue, &entry); | 73 | add_wait_queue(&master->lock.lock_queue, &entry); |
| 78 | spin_lock_bh(&master->lock.spinlock); | 74 | spin_lock_bh(&master->lock.spinlock); |
| 79 | master->lock.user_waiters++; | 75 | master->lock.user_waiters++; |
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 961fb54f4266..9bb82f7f0061 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c | |||
| @@ -118,45 +118,53 @@ static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node) | |||
| 118 | 118 | ||
| 119 | static void drm_mm_insert_helper(struct drm_mm_node *hole_node, | 119 | static void drm_mm_insert_helper(struct drm_mm_node *hole_node, |
| 120 | struct drm_mm_node *node, | 120 | struct drm_mm_node *node, |
| 121 | unsigned long size, unsigned alignment) | 121 | unsigned long size, unsigned alignment, |
| 122 | unsigned long color) | ||
| 122 | { | 123 | { |
| 123 | struct drm_mm *mm = hole_node->mm; | 124 | struct drm_mm *mm = hole_node->mm; |
| 124 | unsigned long tmp = 0, wasted = 0; | ||
| 125 | unsigned long hole_start = drm_mm_hole_node_start(hole_node); | 125 | unsigned long hole_start = drm_mm_hole_node_start(hole_node); |
| 126 | unsigned long hole_end = drm_mm_hole_node_end(hole_node); | 126 | unsigned long hole_end = drm_mm_hole_node_end(hole_node); |
| 127 | unsigned long adj_start = hole_start; | ||
| 128 | unsigned long adj_end = hole_end; | ||
| 127 | 129 | ||
| 128 | BUG_ON(!hole_node->hole_follows || node->allocated); | 130 | BUG_ON(!hole_node->hole_follows || node->allocated); |
| 129 | 131 | ||
| 130 | if (alignment) | 132 | if (mm->color_adjust) |
| 131 | tmp = hole_start % alignment; | 133 | mm->color_adjust(hole_node, color, &adj_start, &adj_end); |
| 132 | 134 | ||
| 133 | if (!tmp) { | 135 | if (alignment) { |
| 136 | unsigned tmp = adj_start % alignment; | ||
| 137 | if (tmp) | ||
| 138 | adj_start += alignment - tmp; | ||
| 139 | } | ||
| 140 | |||
| 141 | if (adj_start == hole_start) { | ||
| 134 | hole_node->hole_follows = 0; | 142 | hole_node->hole_follows = 0; |
| 135 | list_del_init(&hole_node->hole_stack); | 143 | list_del(&hole_node->hole_stack); |
| 136 | } else | 144 | } |
| 137 | wasted = alignment - tmp; | ||
| 138 | 145 | ||
| 139 | node->start = hole_start + wasted; | 146 | node->start = adj_start; |
| 140 | node->size = size; | 147 | node->size = size; |
| 141 | node->mm = mm; | 148 | node->mm = mm; |
| 149 | node->color = color; | ||
| 142 | node->allocated = 1; | 150 | node->allocated = 1; |
| 143 | 151 | ||
| 144 | INIT_LIST_HEAD(&node->hole_stack); | 152 | INIT_LIST_HEAD(&node->hole_stack); |
| 145 | list_add(&node->node_list, &hole_node->node_list); | 153 | list_add(&node->node_list, &hole_node->node_list); |
| 146 | 154 | ||
| 147 | BUG_ON(node->start + node->size > hole_end); | 155 | BUG_ON(node->start + node->size > adj_end); |
| 148 | 156 | ||
| 157 | node->hole_follows = 0; | ||
| 149 | if (node->start + node->size < hole_end) { | 158 | if (node->start + node->size < hole_end) { |
| 150 | list_add(&node->hole_stack, &mm->hole_stack); | 159 | list_add(&node->hole_stack, &mm->hole_stack); |
| 151 | node->hole_follows = 1; | 160 | node->hole_follows = 1; |
| 152 | } else { | ||
| 153 | node->hole_follows = 0; | ||
| 154 | } | 161 | } |
| 155 | } | 162 | } |
| 156 | 163 | ||
| 157 | struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node, | 164 | struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node, |
| 158 | unsigned long size, | 165 | unsigned long size, |
| 159 | unsigned alignment, | 166 | unsigned alignment, |
| 167 | unsigned long color, | ||
| 160 | int atomic) | 168 | int atomic) |
| 161 | { | 169 | { |
| 162 | struct drm_mm_node *node; | 170 | struct drm_mm_node *node; |
| @@ -165,7 +173,7 @@ struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node, | |||
| 165 | if (unlikely(node == NULL)) | 173 | if (unlikely(node == NULL)) |
| 166 | return NULL; | 174 | return NULL; |
| 167 | 175 | ||
| 168 | drm_mm_insert_helper(hole_node, node, size, alignment); | 176 | drm_mm_insert_helper(hole_node, node, size, alignment, color); |
| 169 | 177 | ||
| 170 | return node; | 178 | return node; |
| 171 | } | 179 | } |
| @@ -181,11 +189,11 @@ int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, | |||
| 181 | { | 189 | { |
| 182 | struct drm_mm_node *hole_node; | 190 | struct drm_mm_node *hole_node; |
| 183 | 191 | ||
| 184 | hole_node = drm_mm_search_free(mm, size, alignment, 0); | 192 | hole_node = drm_mm_search_free(mm, size, alignment, false); |
| 185 | if (!hole_node) | 193 | if (!hole_node) |
| 186 | return -ENOSPC; | 194 | return -ENOSPC; |
| 187 | 195 | ||
| 188 | drm_mm_insert_helper(hole_node, node, size, alignment); | 196 | drm_mm_insert_helper(hole_node, node, size, alignment, 0); |
| 189 | 197 | ||
| 190 | return 0; | 198 | return 0; |
| 191 | } | 199 | } |
| @@ -194,50 +202,57 @@ EXPORT_SYMBOL(drm_mm_insert_node); | |||
| 194 | static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, | 202 | static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, |
| 195 | struct drm_mm_node *node, | 203 | struct drm_mm_node *node, |
| 196 | unsigned long size, unsigned alignment, | 204 | unsigned long size, unsigned alignment, |
| 205 | unsigned long color, | ||
| 197 | unsigned long start, unsigned long end) | 206 | unsigned long start, unsigned long end) |
| 198 | { | 207 | { |
| 199 | struct drm_mm *mm = hole_node->mm; | 208 | struct drm_mm *mm = hole_node->mm; |
| 200 | unsigned long tmp = 0, wasted = 0; | ||
| 201 | unsigned long hole_start = drm_mm_hole_node_start(hole_node); | 209 | unsigned long hole_start = drm_mm_hole_node_start(hole_node); |
| 202 | unsigned long hole_end = drm_mm_hole_node_end(hole_node); | 210 | unsigned long hole_end = drm_mm_hole_node_end(hole_node); |
| 211 | unsigned long adj_start = hole_start; | ||
| 212 | unsigned long adj_end = hole_end; | ||
| 203 | 213 | ||
| 204 | BUG_ON(!hole_node->hole_follows || node->allocated); | 214 | BUG_ON(!hole_node->hole_follows || node->allocated); |
| 205 | 215 | ||
| 206 | if (hole_start < start) | 216 | if (mm->color_adjust) |
| 207 | wasted += start - hole_start; | 217 | mm->color_adjust(hole_node, color, &adj_start, &adj_end); |
| 208 | if (alignment) | ||
| 209 | tmp = (hole_start + wasted) % alignment; | ||
| 210 | 218 | ||
| 211 | if (tmp) | 219 | if (adj_start < start) |
| 212 | wasted += alignment - tmp; | 220 | adj_start = start; |
| 221 | |||
| 222 | if (alignment) { | ||
| 223 | unsigned tmp = adj_start % alignment; | ||
| 224 | if (tmp) | ||
| 225 | adj_start += alignment - tmp; | ||
| 226 | } | ||
| 213 | 227 | ||
| 214 | if (!wasted) { | 228 | if (adj_start == hole_start) { |
| 215 | hole_node->hole_follows = 0; | 229 | hole_node->hole_follows = 0; |
| 216 | list_del_init(&hole_node->hole_stack); | 230 | list_del(&hole_node->hole_stack); |
| 217 | } | 231 | } |
| 218 | 232 | ||
| 219 | node->start = hole_start + wasted; | 233 | node->start = adj_start; |
| 220 | node->size = size; | 234 | node->size = size; |
| 221 | node->mm = mm; | 235 | node->mm = mm; |
| 236 | node->color = color; | ||
| 222 | node->allocated = 1; | 237 | node->allocated = 1; |
| 223 | 238 | ||
| 224 | INIT_LIST_HEAD(&node->hole_stack); | 239 | INIT_LIST_HEAD(&node->hole_stack); |
| 225 | list_add(&node->node_list, &hole_node->node_list); | 240 | list_add(&node->node_list, &hole_node->node_list); |
| 226 | 241 | ||
| 227 | BUG_ON(node->start + node->size > hole_end); | 242 | BUG_ON(node->start + node->size > adj_end); |
| 228 | BUG_ON(node->start + node->size > end); | 243 | BUG_ON(node->start + node->size > end); |
| 229 | 244 | ||
| 245 | node->hole_follows = 0; | ||
| 230 | if (node->start + node->size < hole_end) { | 246 | if (node->start + node->size < hole_end) { |
| 231 | list_add(&node->hole_stack, &mm->hole_stack); | 247 | list_add(&node->hole_stack, &mm->hole_stack); |
| 232 | node->hole_follows = 1; | 248 | node->hole_follows = 1; |
| 233 | } else { | ||
| 234 | node->hole_follows = 0; | ||
| 235 | } | 249 | } |
| 236 | } | 250 | } |
| 237 | 251 | ||
| 238 | struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node, | 252 | struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node, |
| 239 | unsigned long size, | 253 | unsigned long size, |
| 240 | unsigned alignment, | 254 | unsigned alignment, |
| 255 | unsigned long color, | ||
| 241 | unsigned long start, | 256 | unsigned long start, |
| 242 | unsigned long end, | 257 | unsigned long end, |
| 243 | int atomic) | 258 | int atomic) |
| @@ -248,7 +263,7 @@ struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node | |||
| 248 | if (unlikely(node == NULL)) | 263 | if (unlikely(node == NULL)) |
| 249 | return NULL; | 264 | return NULL; |
| 250 | 265 | ||
| 251 | drm_mm_insert_helper_range(hole_node, node, size, alignment, | 266 | drm_mm_insert_helper_range(hole_node, node, size, alignment, color, |
| 252 | start, end); | 267 | start, end); |
| 253 | 268 | ||
| 254 | return node; | 269 | return node; |
| @@ -267,11 +282,11 @@ int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node, | |||
| 267 | struct drm_mm_node *hole_node; | 282 | struct drm_mm_node *hole_node; |
| 268 | 283 | ||
| 269 | hole_node = drm_mm_search_free_in_range(mm, size, alignment, | 284 | hole_node = drm_mm_search_free_in_range(mm, size, alignment, |
| 270 | start, end, 0); | 285 | start, end, false); |
| 271 | if (!hole_node) | 286 | if (!hole_node) |
| 272 | return -ENOSPC; | 287 | return -ENOSPC; |
| 273 | 288 | ||
| 274 | drm_mm_insert_helper_range(hole_node, node, size, alignment, | 289 | drm_mm_insert_helper_range(hole_node, node, size, alignment, 0, |
| 275 | start, end); | 290 | start, end); |
| 276 | 291 | ||
| 277 | return 0; | 292 | return 0; |
| @@ -336,27 +351,23 @@ EXPORT_SYMBOL(drm_mm_put_block); | |||
| 336 | static int check_free_hole(unsigned long start, unsigned long end, | 351 | static int check_free_hole(unsigned long start, unsigned long end, |
| 337 | unsigned long size, unsigned alignment) | 352 | unsigned long size, unsigned alignment) |
| 338 | { | 353 | { |
| 339 | unsigned wasted = 0; | ||
| 340 | |||
| 341 | if (end - start < size) | 354 | if (end - start < size) |
| 342 | return 0; | 355 | return 0; |
| 343 | 356 | ||
| 344 | if (alignment) { | 357 | if (alignment) { |
| 345 | unsigned tmp = start % alignment; | 358 | unsigned tmp = start % alignment; |
| 346 | if (tmp) | 359 | if (tmp) |
| 347 | wasted = alignment - tmp; | 360 | start += alignment - tmp; |
| 348 | } | ||
| 349 | |||
| 350 | if (end >= start + size + wasted) { | ||
| 351 | return 1; | ||
| 352 | } | 361 | } |
| 353 | 362 | ||
| 354 | return 0; | 363 | return end >= start + size; |
| 355 | } | 364 | } |
| 356 | 365 | ||
| 357 | struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, | 366 | struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, |
| 358 | unsigned long size, | 367 | unsigned long size, |
| 359 | unsigned alignment, int best_match) | 368 | unsigned alignment, |
| 369 | unsigned long color, | ||
| 370 | bool best_match) | ||
| 360 | { | 371 | { |
| 361 | struct drm_mm_node *entry; | 372 | struct drm_mm_node *entry; |
| 362 | struct drm_mm_node *best; | 373 | struct drm_mm_node *best; |
| @@ -368,10 +379,17 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, | |||
| 368 | best_size = ~0UL; | 379 | best_size = ~0UL; |
| 369 | 380 | ||
| 370 | list_for_each_entry(entry, &mm->hole_stack, hole_stack) { | 381 | list_for_each_entry(entry, &mm->hole_stack, hole_stack) { |
| 382 | unsigned long adj_start = drm_mm_hole_node_start(entry); | ||
| 383 | unsigned long adj_end = drm_mm_hole_node_end(entry); | ||
| 384 | |||
| 385 | if (mm->color_adjust) { | ||
| 386 | mm->color_adjust(entry, color, &adj_start, &adj_end); | ||
| 387 | if (adj_end <= adj_start) | ||
| 388 | continue; | ||
| 389 | } | ||
| 390 | |||
| 371 | BUG_ON(!entry->hole_follows); | 391 | BUG_ON(!entry->hole_follows); |
| 372 | if (!check_free_hole(drm_mm_hole_node_start(entry), | 392 | if (!check_free_hole(adj_start, adj_end, size, alignment)) |
| 373 | drm_mm_hole_node_end(entry), | ||
| 374 | size, alignment)) | ||
| 375 | continue; | 393 | continue; |
| 376 | 394 | ||
| 377 | if (!best_match) | 395 | if (!best_match) |
| @@ -385,14 +403,15 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, | |||
| 385 | 403 | ||
| 386 | return best; | 404 | return best; |
| 387 | } | 405 | } |
| 388 | EXPORT_SYMBOL(drm_mm_search_free); | 406 | EXPORT_SYMBOL(drm_mm_search_free_generic); |
| 389 | 407 | ||
| 390 | struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, | 408 | struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm, |
| 391 | unsigned long size, | 409 | unsigned long size, |
| 392 | unsigned alignment, | 410 | unsigned alignment, |
| 393 | unsigned long start, | 411 | unsigned long color, |
| 394 | unsigned long end, | 412 | unsigned long start, |
| 395 | int best_match) | 413 | unsigned long end, |
| 414 | bool best_match) | ||
| 396 | { | 415 | { |
| 397 | struct drm_mm_node *entry; | 416 | struct drm_mm_node *entry; |
| 398 | struct drm_mm_node *best; | 417 | struct drm_mm_node *best; |
| @@ -410,6 +429,13 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, | |||
| 410 | end : drm_mm_hole_node_end(entry); | 429 | end : drm_mm_hole_node_end(entry); |
| 411 | 430 | ||
| 412 | BUG_ON(!entry->hole_follows); | 431 | BUG_ON(!entry->hole_follows); |
| 432 | |||
| 433 | if (mm->color_adjust) { | ||
| 434 | mm->color_adjust(entry, color, &adj_start, &adj_end); | ||
| 435 | if (adj_end <= adj_start) | ||
| 436 | continue; | ||
| 437 | } | ||
| 438 | |||
| 413 | if (!check_free_hole(adj_start, adj_end, size, alignment)) | 439 | if (!check_free_hole(adj_start, adj_end, size, alignment)) |
| 414 | continue; | 440 | continue; |
| 415 | 441 | ||
| @@ -424,7 +450,7 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, | |||
| 424 | 450 | ||
| 425 | return best; | 451 | return best; |
| 426 | } | 452 | } |
| 427 | EXPORT_SYMBOL(drm_mm_search_free_in_range); | 453 | EXPORT_SYMBOL(drm_mm_search_free_in_range_generic); |
| 428 | 454 | ||
| 429 | /** | 455 | /** |
| 430 | * Moves an allocation. To be used with embedded struct drm_mm_node. | 456 | * Moves an allocation. To be used with embedded struct drm_mm_node. |
| @@ -437,6 +463,7 @@ void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new) | |||
| 437 | new->mm = old->mm; | 463 | new->mm = old->mm; |
| 438 | new->start = old->start; | 464 | new->start = old->start; |
| 439 | new->size = old->size; | 465 | new->size = old->size; |
| 466 | new->color = old->color; | ||
| 440 | 467 | ||
| 441 | old->allocated = 0; | 468 | old->allocated = 0; |
| 442 | new->allocated = 1; | 469 | new->allocated = 1; |
| @@ -452,9 +479,12 @@ EXPORT_SYMBOL(drm_mm_replace_node); | |||
| 452 | * Warning: As long as the scan list is non-empty, no other operations than | 479 | * Warning: As long as the scan list is non-empty, no other operations than |
| 453 | * adding/removing nodes to/from the scan list are allowed. | 480 | * adding/removing nodes to/from the scan list are allowed. |
| 454 | */ | 481 | */ |
| 455 | void drm_mm_init_scan(struct drm_mm *mm, unsigned long size, | 482 | void drm_mm_init_scan(struct drm_mm *mm, |
| 456 | unsigned alignment) | 483 | unsigned long size, |
| 484 | unsigned alignment, | ||
| 485 | unsigned long color) | ||
| 457 | { | 486 | { |
| 487 | mm->scan_color = color; | ||
| 458 | mm->scan_alignment = alignment; | 488 | mm->scan_alignment = alignment; |
| 459 | mm->scan_size = size; | 489 | mm->scan_size = size; |
| 460 | mm->scanned_blocks = 0; | 490 | mm->scanned_blocks = 0; |
| @@ -474,11 +504,14 @@ EXPORT_SYMBOL(drm_mm_init_scan); | |||
| 474 | * Warning: As long as the scan list is non-empty, no other operations than | 504 | * Warning: As long as the scan list is non-empty, no other operations than |
| 475 | * adding/removing nodes to/from the scan list are allowed. | 505 | * adding/removing nodes to/from the scan list are allowed. |
| 476 | */ | 506 | */ |
| 477 | void drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size, | 507 | void drm_mm_init_scan_with_range(struct drm_mm *mm, |
| 508 | unsigned long size, | ||
| 478 | unsigned alignment, | 509 | unsigned alignment, |
| 510 | unsigned long color, | ||
| 479 | unsigned long start, | 511 | unsigned long start, |
| 480 | unsigned long end) | 512 | unsigned long end) |
| 481 | { | 513 | { |
| 514 | mm->scan_color = color; | ||
| 482 | mm->scan_alignment = alignment; | 515 | mm->scan_alignment = alignment; |
| 483 | mm->scan_size = size; | 516 | mm->scan_size = size; |
| 484 | mm->scanned_blocks = 0; | 517 | mm->scanned_blocks = 0; |
| @@ -522,17 +555,21 @@ int drm_mm_scan_add_block(struct drm_mm_node *node) | |||
| 522 | 555 | ||
| 523 | hole_start = drm_mm_hole_node_start(prev_node); | 556 | hole_start = drm_mm_hole_node_start(prev_node); |
| 524 | hole_end = drm_mm_hole_node_end(prev_node); | 557 | hole_end = drm_mm_hole_node_end(prev_node); |
| 558 | |||
| 559 | adj_start = hole_start; | ||
| 560 | adj_end = hole_end; | ||
| 561 | |||
| 562 | if (mm->color_adjust) | ||
| 563 | mm->color_adjust(prev_node, mm->scan_color, &adj_start, &adj_end); | ||
| 564 | |||
| 525 | if (mm->scan_check_range) { | 565 | if (mm->scan_check_range) { |
| 526 | adj_start = hole_start < mm->scan_start ? | 566 | if (adj_start < mm->scan_start) |
| 527 | mm->scan_start : hole_start; | 567 | adj_start = mm->scan_start; |
| 528 | adj_end = hole_end > mm->scan_end ? | 568 | if (adj_end > mm->scan_end) |
| 529 | mm->scan_end : hole_end; | 569 | adj_end = mm->scan_end; |
| 530 | } else { | ||
| 531 | adj_start = hole_start; | ||
| 532 | adj_end = hole_end; | ||
| 533 | } | 570 | } |
| 534 | 571 | ||
| 535 | if (check_free_hole(adj_start , adj_end, | 572 | if (check_free_hole(adj_start, adj_end, |
| 536 | mm->scan_size, mm->scan_alignment)) { | 573 | mm->scan_size, mm->scan_alignment)) { |
| 537 | mm->scan_hit_start = hole_start; | 574 | mm->scan_hit_start = hole_start; |
| 538 | mm->scan_hit_size = hole_end; | 575 | mm->scan_hit_size = hole_end; |
| @@ -616,6 +653,8 @@ int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size) | |||
| 616 | mm->head_node.size = start - mm->head_node.start; | 653 | mm->head_node.size = start - mm->head_node.start; |
| 617 | list_add_tail(&mm->head_node.hole_stack, &mm->hole_stack); | 654 | list_add_tail(&mm->head_node.hole_stack, &mm->hole_stack); |
| 618 | 655 | ||
| 656 | mm->color_adjust = NULL; | ||
| 657 | |||
| 619 | return 0; | 658 | return 0; |
| 620 | } | 659 | } |
| 621 | EXPORT_SYMBOL(drm_mm_init); | 660 | EXPORT_SYMBOL(drm_mm_init); |
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index 13f3d936472f..5320364582ce 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c | |||
| @@ -465,3 +465,52 @@ void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver) | |||
| 465 | DRM_INFO("Module unloaded\n"); | 465 | DRM_INFO("Module unloaded\n"); |
| 466 | } | 466 | } |
| 467 | EXPORT_SYMBOL(drm_pci_exit); | 467 | EXPORT_SYMBOL(drm_pci_exit); |
| 468 | |||
| 469 | int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask) | ||
| 470 | { | ||
| 471 | struct pci_dev *root; | ||
| 472 | int pos; | ||
| 473 | u32 lnkcap, lnkcap2; | ||
| 474 | |||
| 475 | *mask = 0; | ||
| 476 | if (!dev->pdev) | ||
| 477 | return -EINVAL; | ||
| 478 | |||
| 479 | if (!pci_is_pcie(dev->pdev)) | ||
| 480 | return -EINVAL; | ||
| 481 | |||
| 482 | root = dev->pdev->bus->self; | ||
| 483 | |||
| 484 | pos = pci_pcie_cap(root); | ||
| 485 | if (!pos) | ||
| 486 | return -EINVAL; | ||
| 487 | |||
| 488 | /* we've been informed via and serverworks don't make the cut */ | ||
| 489 | if (root->vendor == PCI_VENDOR_ID_VIA || | ||
| 490 | root->vendor == PCI_VENDOR_ID_SERVERWORKS) | ||
| 491 | return -EINVAL; | ||
| 492 | |||
| 493 | pci_read_config_dword(root, pos + PCI_EXP_LNKCAP, &lnkcap); | ||
| 494 | pci_read_config_dword(root, pos + PCI_EXP_LNKCAP2, &lnkcap2); | ||
| 495 | |||
| 496 | lnkcap &= PCI_EXP_LNKCAP_SLS; | ||
| 497 | lnkcap2 &= 0xfe; | ||
| 498 | |||
| 499 | if (lnkcap2) { /* PCIE GEN 3.0 */ | ||
| 500 | if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB) | ||
| 501 | *mask |= DRM_PCIE_SPEED_25; | ||
| 502 | if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB) | ||
| 503 | *mask |= DRM_PCIE_SPEED_50; | ||
| 504 | if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB) | ||
| 505 | *mask |= DRM_PCIE_SPEED_80; | ||
| 506 | } else { | ||
| 507 | if (lnkcap & 1) | ||
| 508 | *mask |= DRM_PCIE_SPEED_25; | ||
| 509 | if (lnkcap & 2) | ||
| 510 | *mask |= DRM_PCIE_SPEED_50; | ||
| 511 | } | ||
| 512 | |||
| 513 | DRM_INFO("probing gen 2 caps for device %x:%x = %x/%x\n", root->vendor, root->device, lnkcap, lnkcap2); | ||
| 514 | return 0; | ||
| 515 | } | ||
| 516 | EXPORT_SYMBOL(drm_pcie_get_speed_cap_mask); | ||
diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c index fff87221f9e9..371c695322d9 100644 --- a/drivers/gpu/drm/drm_proc.c +++ b/drivers/gpu/drm/drm_proc.c | |||
| @@ -53,7 +53,6 @@ static struct drm_info_list drm_proc_list[] = { | |||
| 53 | {"name", drm_name_info, 0}, | 53 | {"name", drm_name_info, 0}, |
| 54 | {"vm", drm_vm_info, 0}, | 54 | {"vm", drm_vm_info, 0}, |
| 55 | {"clients", drm_clients_info, 0}, | 55 | {"clients", drm_clients_info, 0}, |
| 56 | {"queues", drm_queues_info, 0}, | ||
| 57 | {"bufs", drm_bufs_info, 0}, | 56 | {"bufs", drm_bufs_info, 0}, |
| 58 | {"gem_names", drm_gem_name_info, DRIVER_GEM}, | 57 | {"gem_names", drm_gem_name_info, DRIVER_GEM}, |
| 59 | #if DRM_DEBUG_CODE | 58 | #if DRM_DEBUG_CODE |
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 45cf1dd3eb9c..45ac8d6c92b7 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c | |||
| @@ -134,6 +134,7 @@ void drm_sysfs_destroy(void) | |||
| 134 | return; | 134 | return; |
| 135 | class_remove_file(drm_class, &class_attr_version.attr); | 135 | class_remove_file(drm_class, &class_attr_version.attr); |
| 136 | class_destroy(drm_class); | 136 | class_destroy(drm_class); |
| 137 | drm_class = NULL; | ||
| 137 | } | 138 | } |
| 138 | 139 | ||
| 139 | /** | 140 | /** |
| @@ -554,6 +555,9 @@ void drm_sysfs_device_remove(struct drm_minor *minor) | |||
| 554 | 555 | ||
| 555 | int drm_class_device_register(struct device *dev) | 556 | int drm_class_device_register(struct device *dev) |
| 556 | { | 557 | { |
| 558 | if (!drm_class || IS_ERR(drm_class)) | ||
| 559 | return -ENOENT; | ||
| 560 | |||
| 557 | dev->class = drm_class; | 561 | dev->class = drm_class; |
| 558 | return device_register(dev); | 562 | return device_register(dev); |
| 559 | } | 563 | } |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 4afb625128d7..32a34c85899b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c | |||
| @@ -237,7 +237,7 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc) | |||
| 237 | 237 | ||
| 238 | static bool | 238 | static bool |
| 239 | exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc, | 239 | exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc, |
| 240 | struct drm_display_mode *mode, | 240 | const struct drm_display_mode *mode, |
| 241 | struct drm_display_mode *adjusted_mode) | 241 | struct drm_display_mode *adjusted_mode) |
| 242 | { | 242 | { |
| 243 | DRM_DEBUG_KMS("%s\n", __FILE__); | 243 | DRM_DEBUG_KMS("%s\n", __FILE__); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index c82c90c443e7..277653d5fda0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h | |||
| @@ -174,7 +174,7 @@ struct exynos_drm_manager_ops { | |||
| 174 | void (*apply)(struct device *subdrv_dev); | 174 | void (*apply)(struct device *subdrv_dev); |
| 175 | void (*mode_fixup)(struct device *subdrv_dev, | 175 | void (*mode_fixup)(struct device *subdrv_dev, |
| 176 | struct drm_connector *connector, | 176 | struct drm_connector *connector, |
| 177 | struct drm_display_mode *mode, | 177 | const struct drm_display_mode *mode, |
| 178 | struct drm_display_mode *adjusted_mode); | 178 | struct drm_display_mode *adjusted_mode); |
| 179 | void (*mode_set)(struct device *subdrv_dev, void *mode); | 179 | void (*mode_set)(struct device *subdrv_dev, void *mode); |
| 180 | void (*get_max_resol)(struct device *subdrv_dev, unsigned int *width, | 180 | void (*get_max_resol)(struct device *subdrv_dev, unsigned int *width, |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 23d5ad379f86..4a13a747f5d4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c | |||
| @@ -108,7 +108,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
| 108 | 108 | ||
| 109 | static bool | 109 | static bool |
| 110 | exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder, | 110 | exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder, |
| 111 | struct drm_display_mode *mode, | 111 | const struct drm_display_mode *mode, |
| 112 | struct drm_display_mode *adjusted_mode) | 112 | struct drm_display_mode *adjusted_mode) |
| 113 | { | 113 | { |
| 114 | struct drm_device *dev = encoder->dev; | 114 | struct drm_device *dev = encoder->dev; |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index 5d9d2c2f8f3f..8ffcdf8b9e22 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c | |||
| @@ -142,7 +142,7 @@ static void drm_hdmi_disable_vblank(struct device *subdrv_dev) | |||
| 142 | 142 | ||
| 143 | static void drm_hdmi_mode_fixup(struct device *subdrv_dev, | 143 | static void drm_hdmi_mode_fixup(struct device *subdrv_dev, |
| 144 | struct drm_connector *connector, | 144 | struct drm_connector *connector, |
| 145 | struct drm_display_mode *mode, | 145 | const struct drm_display_mode *mode, |
| 146 | struct drm_display_mode *adjusted_mode) | 146 | struct drm_display_mode *adjusted_mode) |
| 147 | { | 147 | { |
| 148 | struct drm_hdmi_context *ctx = to_context(subdrv_dev); | 148 | struct drm_hdmi_context *ctx = to_context(subdrv_dev); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h index bd8126996e52..a91c42088e42 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h | |||
| @@ -51,7 +51,7 @@ struct exynos_hdmi_ops { | |||
| 51 | 51 | ||
| 52 | /* manager */ | 52 | /* manager */ |
| 53 | void (*mode_fixup)(void *ctx, struct drm_connector *connector, | 53 | void (*mode_fixup)(void *ctx, struct drm_connector *connector, |
| 54 | struct drm_display_mode *mode, | 54 | const struct drm_display_mode *mode, |
| 55 | struct drm_display_mode *adjusted_mode); | 55 | struct drm_display_mode *adjusted_mode); |
| 56 | void (*mode_set)(void *ctx, void *mode); | 56 | void (*mode_set)(void *ctx, void *mode); |
| 57 | void (*get_max_resol)(void *ctx, unsigned int *width, | 57 | void (*get_max_resol)(void *ctx, unsigned int *width, |
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index a137e9e39a33..066bde3f19c4 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c | |||
| @@ -1940,7 +1940,7 @@ static void hdmi_conf_apply(struct hdmi_context *hdata) | |||
| 1940 | } | 1940 | } |
| 1941 | 1941 | ||
| 1942 | static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, | 1942 | static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, |
| 1943 | struct drm_display_mode *mode, | 1943 | const struct drm_display_mode *mode, |
| 1944 | struct drm_display_mode *adjusted_mode) | 1944 | struct drm_display_mode *adjusted_mode) |
| 1945 | { | 1945 | { |
| 1946 | struct drm_display_mode *m; | 1946 | struct drm_display_mode *m; |
diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c index 187422018601..8c175345d85c 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_crt.c +++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c | |||
| @@ -82,7 +82,7 @@ static int cdv_intel_crt_mode_valid(struct drm_connector *connector, | |||
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | static bool cdv_intel_crt_mode_fixup(struct drm_encoder *encoder, | 84 | static bool cdv_intel_crt_mode_fixup(struct drm_encoder *encoder, |
| 85 | struct drm_display_mode *mode, | 85 | const struct drm_display_mode *mode, |
| 86 | struct drm_display_mode *adjusted_mode) | 86 | struct drm_display_mode *adjusted_mode) |
| 87 | { | 87 | { |
| 88 | return true; | 88 | return true; |
diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index c3e9a0f701df..a68509ba22a8 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c | |||
| @@ -913,7 +913,7 @@ static void cdv_intel_crtc_commit(struct drm_crtc *crtc) | |||
| 913 | } | 913 | } |
| 914 | 914 | ||
| 915 | static bool cdv_intel_crtc_mode_fixup(struct drm_crtc *crtc, | 915 | static bool cdv_intel_crtc_mode_fixup(struct drm_crtc *crtc, |
| 916 | struct drm_display_mode *mode, | 916 | const struct drm_display_mode *mode, |
| 917 | struct drm_display_mode *adjusted_mode) | 917 | struct drm_display_mode *adjusted_mode) |
| 918 | { | 918 | { |
| 919 | return true; | 919 | return true; |
diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c index 88b59d4a7b7f..a86f87b9ddde 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c | |||
| @@ -90,7 +90,7 @@ static void cdv_hdmi_mode_set(struct drm_encoder *encoder, | |||
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | static bool cdv_hdmi_mode_fixup(struct drm_encoder *encoder, | 92 | static bool cdv_hdmi_mode_fixup(struct drm_encoder *encoder, |
| 93 | struct drm_display_mode *mode, | 93 | const struct drm_display_mode *mode, |
| 94 | struct drm_display_mode *adjusted_mode) | 94 | struct drm_display_mode *adjusted_mode) |
| 95 | { | 95 | { |
| 96 | return true; | 96 | return true; |
diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c index ff5b58eb878c..c7f9468b74ba 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c | |||
| @@ -270,7 +270,7 @@ static int cdv_intel_lvds_mode_valid(struct drm_connector *connector, | |||
| 270 | } | 270 | } |
| 271 | 271 | ||
| 272 | static bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder, | 272 | static bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder, |
| 273 | struct drm_display_mode *mode, | 273 | const struct drm_display_mode *mode, |
| 274 | struct drm_display_mode *adjusted_mode) | 274 | struct drm_display_mode *adjusted_mode) |
| 275 | { | 275 | { |
| 276 | struct drm_device *dev = encoder->dev; | 276 | struct drm_device *dev = encoder->dev; |
diff --git a/drivers/gpu/drm/gma500/intel_bios.c b/drivers/gpu/drm/gma500/intel_bios.c index 973d7f6d66b7..8d7caf0f363e 100644 --- a/drivers/gpu/drm/gma500/intel_bios.c +++ b/drivers/gpu/drm/gma500/intel_bios.c | |||
| @@ -427,7 +427,7 @@ parse_device_mapping(struct drm_psb_private *dev_priv, | |||
| 427 | * | 427 | * |
| 428 | * Returns 0 on success, nonzero on failure. | 428 | * Returns 0 on success, nonzero on failure. |
| 429 | */ | 429 | */ |
| 430 | bool psb_intel_init_bios(struct drm_device *dev) | 430 | int psb_intel_init_bios(struct drm_device *dev) |
| 431 | { | 431 | { |
| 432 | struct drm_psb_private *dev_priv = dev->dev_private; | 432 | struct drm_psb_private *dev_priv = dev->dev_private; |
| 433 | struct pci_dev *pdev = dev->pdev; | 433 | struct pci_dev *pdev = dev->pdev; |
diff --git a/drivers/gpu/drm/gma500/intel_bios.h b/drivers/gpu/drm/gma500/intel_bios.h index 0a738663eb5a..2e95523b84b1 100644 --- a/drivers/gpu/drm/gma500/intel_bios.h +++ b/drivers/gpu/drm/gma500/intel_bios.h | |||
| @@ -431,7 +431,7 @@ struct bdb_driver_features { | |||
| 431 | u8 custom_vbt_version; | 431 | u8 custom_vbt_version; |
| 432 | } __attribute__((packed)); | 432 | } __attribute__((packed)); |
| 433 | 433 | ||
| 434 | extern bool psb_intel_init_bios(struct drm_device *dev); | 434 | extern int psb_intel_init_bios(struct drm_device *dev); |
| 435 | extern void psb_intel_destroy_bios(struct drm_device *dev); | 435 | extern void psb_intel_destroy_bios(struct drm_device *dev); |
| 436 | 436 | ||
| 437 | /* | 437 | /* |
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c index b34ff097b979..d4813e03f5ee 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c +++ b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c | |||
| @@ -684,7 +684,7 @@ void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode) | |||
| 684 | } | 684 | } |
| 685 | 685 | ||
| 686 | bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, | 686 | bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, |
| 687 | struct drm_display_mode *mode, | 687 | const struct drm_display_mode *mode, |
| 688 | struct drm_display_mode *adjusted_mode) | 688 | struct drm_display_mode *adjusted_mode) |
| 689 | { | 689 | { |
| 690 | struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); | 690 | struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); |
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h index 6f762478b959..2b40663e1696 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h +++ b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h | |||
| @@ -65,7 +65,7 @@ extern struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, | |||
| 65 | /* MDFLD DPI helper functions */ | 65 | /* MDFLD DPI helper functions */ |
| 66 | extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode); | 66 | extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode); |
| 67 | extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, | 67 | extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, |
| 68 | struct drm_display_mode *mode, | 68 | const struct drm_display_mode *mode, |
| 69 | struct drm_display_mode *adjusted_mode); | 69 | struct drm_display_mode *adjusted_mode); |
| 70 | extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder); | 70 | extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder); |
| 71 | extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder); | 71 | extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder); |
diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c index 3f3cd619c79f..dec6a9aea3c6 100644 --- a/drivers/gpu/drm/gma500/mdfld_intel_display.c +++ b/drivers/gpu/drm/gma500/mdfld_intel_display.c | |||
| @@ -117,7 +117,7 @@ static void psb_intel_crtc_commit(struct drm_crtc *crtc) | |||
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, | 119 | static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, |
| 120 | struct drm_display_mode *mode, | 120 | const struct drm_display_mode *mode, |
| 121 | struct drm_display_mode *adjusted_mode) | 121 | struct drm_display_mode *adjusted_mode) |
| 122 | { | 122 | { |
| 123 | return true; | 123 | return true; |
diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c index f821c835ca90..cdafd2acc72f 100644 --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c | |||
| @@ -487,7 +487,7 @@ oaktrail_crtc_mode_set_exit: | |||
| 487 | } | 487 | } |
| 488 | 488 | ||
| 489 | static bool oaktrail_crtc_mode_fixup(struct drm_crtc *crtc, | 489 | static bool oaktrail_crtc_mode_fixup(struct drm_crtc *crtc, |
| 490 | struct drm_display_mode *mode, | 490 | const struct drm_display_mode *mode, |
| 491 | struct drm_display_mode *adjusted_mode) | 491 | struct drm_display_mode *adjusted_mode) |
| 492 | { | 492 | { |
| 493 | return true; | 493 | return true; |
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c index c10899c953b9..2eb3dc4e9c9b 100644 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c +++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c | |||
| @@ -191,7 +191,7 @@ static int oaktrail_hdmi_mode_valid(struct drm_connector *connector, | |||
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | static bool oaktrail_hdmi_mode_fixup(struct drm_encoder *encoder, | 193 | static bool oaktrail_hdmi_mode_fixup(struct drm_encoder *encoder, |
| 194 | struct drm_display_mode *mode, | 194 | const struct drm_display_mode *mode, |
| 195 | struct drm_display_mode *adjusted_mode) | 195 | struct drm_display_mode *adjusted_mode) |
| 196 | { | 196 | { |
| 197 | return true; | 197 | return true; |
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index caba6e08693c..cd1dd1b14c76 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c | |||
| @@ -632,7 +632,6 @@ static struct drm_driver driver = { | |||
| 632 | .open = psb_driver_open, | 632 | .open = psb_driver_open, |
| 633 | .preclose = psb_driver_preclose, | 633 | .preclose = psb_driver_preclose, |
| 634 | .postclose = psb_driver_close, | 634 | .postclose = psb_driver_close, |
| 635 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 636 | 635 | ||
| 637 | .gem_init_object = psb_gem_init_object, | 636 | .gem_init_object = psb_gem_init_object, |
| 638 | .gem_free_object = psb_gem_free_object, | 637 | .gem_free_object = psb_gem_free_object, |
diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index 36c3c99612f6..30dc22a7156c 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c | |||
| @@ -543,7 +543,7 @@ void psb_intel_encoder_destroy(struct drm_encoder *encoder) | |||
| 543 | } | 543 | } |
| 544 | 544 | ||
| 545 | static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, | 545 | static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, |
| 546 | struct drm_display_mode *mode, | 546 | const struct drm_display_mode *mode, |
| 547 | struct drm_display_mode *adjusted_mode) | 547 | struct drm_display_mode *adjusted_mode) |
| 548 | { | 548 | { |
| 549 | return true; | 549 | return true; |
diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h index 2515f83248cb..ebe1a28f60e1 100644 --- a/drivers/gpu/drm/gma500/psb_intel_drv.h +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h | |||
| @@ -268,7 +268,7 @@ extern struct drm_framebuffer *psb_intel_framebuffer_create(struct drm_device | |||
| 268 | *mode_cmd, | 268 | *mode_cmd, |
| 269 | void *mm_private); | 269 | void *mm_private); |
| 270 | extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, | 270 | extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, |
| 271 | struct drm_display_mode *mode, | 271 | const struct drm_display_mode *mode, |
| 272 | struct drm_display_mode *adjusted_mode); | 272 | struct drm_display_mode *adjusted_mode); |
| 273 | extern int psb_intel_lvds_mode_valid(struct drm_connector *connector, | 273 | extern int psb_intel_lvds_mode_valid(struct drm_connector *connector, |
| 274 | struct drm_display_mode *mode); | 274 | struct drm_display_mode *mode); |
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c index c83f5b5d1057..37adc9edf974 100644 --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c +++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c | |||
| @@ -375,7 +375,7 @@ int psb_intel_lvds_mode_valid(struct drm_connector *connector, | |||
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, | 377 | bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, |
| 378 | struct drm_display_mode *mode, | 378 | const struct drm_display_mode *mode, |
| 379 | struct drm_display_mode *adjusted_mode) | 379 | struct drm_display_mode *adjusted_mode) |
| 380 | { | 380 | { |
| 381 | struct drm_device *dev = encoder->dev; | 381 | struct drm_device *dev = encoder->dev; |
diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c index d39b15be7649..0466c7b985f8 100644 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c | |||
| @@ -901,7 +901,7 @@ static bool psb_intel_sdvo_set_tv_format(struct psb_intel_sdvo *psb_intel_sdvo) | |||
| 901 | 901 | ||
| 902 | static bool | 902 | static bool |
| 903 | psb_intel_sdvo_set_output_timings_from_mode(struct psb_intel_sdvo *psb_intel_sdvo, | 903 | psb_intel_sdvo_set_output_timings_from_mode(struct psb_intel_sdvo *psb_intel_sdvo, |
| 904 | struct drm_display_mode *mode) | 904 | const struct drm_display_mode *mode) |
| 905 | { | 905 | { |
| 906 | struct psb_intel_sdvo_dtd output_dtd; | 906 | struct psb_intel_sdvo_dtd output_dtd; |
| 907 | 907 | ||
| @@ -918,7 +918,7 @@ psb_intel_sdvo_set_output_timings_from_mode(struct psb_intel_sdvo *psb_intel_sdv | |||
| 918 | 918 | ||
| 919 | static bool | 919 | static bool |
| 920 | psb_intel_sdvo_set_input_timings_for_mode(struct psb_intel_sdvo *psb_intel_sdvo, | 920 | psb_intel_sdvo_set_input_timings_for_mode(struct psb_intel_sdvo *psb_intel_sdvo, |
| 921 | struct drm_display_mode *mode, | 921 | const struct drm_display_mode *mode, |
| 922 | struct drm_display_mode *adjusted_mode) | 922 | struct drm_display_mode *adjusted_mode) |
| 923 | { | 923 | { |
| 924 | /* Reset the input timing to the screen. Assume always input 0. */ | 924 | /* Reset the input timing to the screen. Assume always input 0. */ |
| @@ -942,7 +942,7 @@ psb_intel_sdvo_set_input_timings_for_mode(struct psb_intel_sdvo *psb_intel_sdvo, | |||
| 942 | } | 942 | } |
| 943 | 943 | ||
| 944 | static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder, | 944 | static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder, |
| 945 | struct drm_display_mode *mode, | 945 | const struct drm_display_mode *mode, |
| 946 | struct drm_display_mode *adjusted_mode) | 946 | struct drm_display_mode *adjusted_mode) |
| 947 | { | 947 | { |
| 948 | struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder); | 948 | struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder); |
diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c index d3f2e8785010..36d952280c50 100644 --- a/drivers/gpu/drm/i2c/ch7006_drv.c +++ b/drivers/gpu/drm/i2c/ch7006_drv.c | |||
| @@ -88,7 +88,7 @@ static void ch7006_encoder_restore(struct drm_encoder *encoder) | |||
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | static bool ch7006_encoder_mode_fixup(struct drm_encoder *encoder, | 90 | static bool ch7006_encoder_mode_fixup(struct drm_encoder *encoder, |
| 91 | struct drm_display_mode *mode, | 91 | const struct drm_display_mode *mode, |
| 92 | struct drm_display_mode *adjusted_mode) | 92 | struct drm_display_mode *adjusted_mode) |
| 93 | { | 93 | { |
| 94 | struct ch7006_priv *priv = to_ch7006_priv(encoder); | 94 | struct ch7006_priv *priv = to_ch7006_priv(encoder); |
diff --git a/drivers/gpu/drm/i2c/ch7006_mode.c b/drivers/gpu/drm/i2c/ch7006_mode.c index c860f24a5afc..9b83574141a6 100644 --- a/drivers/gpu/drm/i2c/ch7006_mode.c +++ b/drivers/gpu/drm/i2c/ch7006_mode.c | |||
| @@ -172,7 +172,7 @@ struct ch7006_mode ch7006_modes[] = { | |||
| 172 | }; | 172 | }; |
| 173 | 173 | ||
| 174 | struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, | 174 | struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, |
| 175 | struct drm_display_mode *drm_mode) | 175 | const struct drm_display_mode *drm_mode) |
| 176 | { | 176 | { |
| 177 | struct ch7006_priv *priv = to_ch7006_priv(encoder); | 177 | struct ch7006_priv *priv = to_ch7006_priv(encoder); |
| 178 | struct ch7006_mode *mode; | 178 | struct ch7006_mode *mode; |
diff --git a/drivers/gpu/drm/i2c/ch7006_priv.h b/drivers/gpu/drm/i2c/ch7006_priv.h index 17667b7d57e7..09599f4c0c9a 100644 --- a/drivers/gpu/drm/i2c/ch7006_priv.h +++ b/drivers/gpu/drm/i2c/ch7006_priv.h | |||
| @@ -111,7 +111,7 @@ extern struct ch7006_tv_norm_info ch7006_tv_norms[]; | |||
| 111 | extern struct ch7006_mode ch7006_modes[]; | 111 | extern struct ch7006_mode ch7006_modes[]; |
| 112 | 112 | ||
| 113 | struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, | 113 | struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, |
| 114 | struct drm_display_mode *drm_mode); | 114 | const struct drm_display_mode *drm_mode); |
| 115 | 115 | ||
| 116 | void ch7006_setup_levels(struct drm_encoder *encoder); | 116 | void ch7006_setup_levels(struct drm_encoder *encoder); |
| 117 | void ch7006_setup_subcarrier(struct drm_encoder *encoder); | 117 | void ch7006_setup_subcarrier(struct drm_encoder *encoder); |
diff --git a/drivers/gpu/drm/i2c/sil164_drv.c b/drivers/gpu/drm/i2c/sil164_drv.c index b7d45ab4ba69..30b8ae5e5c4a 100644 --- a/drivers/gpu/drm/i2c/sil164_drv.c +++ b/drivers/gpu/drm/i2c/sil164_drv.c | |||
| @@ -254,7 +254,7 @@ sil164_encoder_restore(struct drm_encoder *encoder) | |||
| 254 | 254 | ||
| 255 | static bool | 255 | static bool |
| 256 | sil164_encoder_mode_fixup(struct drm_encoder *encoder, | 256 | sil164_encoder_mode_fixup(struct drm_encoder *encoder, |
| 257 | struct drm_display_mode *mode, | 257 | const struct drm_display_mode *mode, |
| 258 | struct drm_display_mode *adjusted_mode) | 258 | struct drm_display_mode *adjusted_mode) |
| 259 | { | 259 | { |
| 260 | return true; | 260 | return true; |
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index fa9439159ebd..57d892eaaa6e 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c | |||
| @@ -881,7 +881,7 @@ static int i810_flush_queue(struct drm_device *dev) | |||
| 881 | } | 881 | } |
| 882 | 882 | ||
| 883 | /* Must be called with the lock held */ | 883 | /* Must be called with the lock held */ |
| 884 | static void i810_reclaim_buffers(struct drm_device *dev, | 884 | void i810_driver_reclaim_buffers(struct drm_device *dev, |
| 885 | struct drm_file *file_priv) | 885 | struct drm_file *file_priv) |
| 886 | { | 886 | { |
| 887 | struct drm_device_dma *dma = dev->dma; | 887 | struct drm_device_dma *dma = dev->dma; |
| @@ -1220,12 +1220,17 @@ void i810_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) | |||
| 1220 | if (dev_priv->page_flipping) | 1220 | if (dev_priv->page_flipping) |
| 1221 | i810_do_cleanup_pageflip(dev); | 1221 | i810_do_cleanup_pageflip(dev); |
| 1222 | } | 1222 | } |
| 1223 | } | ||
| 1224 | 1223 | ||
| 1225 | void i810_driver_reclaim_buffers_locked(struct drm_device *dev, | 1224 | if (file_priv->master && file_priv->master->lock.hw_lock) { |
| 1226 | struct drm_file *file_priv) | 1225 | drm_idlelock_take(&file_priv->master->lock); |
| 1227 | { | 1226 | i810_driver_reclaim_buffers(dev, file_priv); |
| 1228 | i810_reclaim_buffers(dev, file_priv); | 1227 | drm_idlelock_release(&file_priv->master->lock); |
| 1228 | } else { | ||
| 1229 | /* master disappeared, clean up stuff anyway and hope nothing | ||
| 1230 | * goes wrong */ | ||
| 1231 | i810_driver_reclaim_buffers(dev, file_priv); | ||
| 1232 | } | ||
| 1233 | |||
| 1229 | } | 1234 | } |
| 1230 | 1235 | ||
| 1231 | int i810_driver_dma_quiescent(struct drm_device *dev) | 1236 | int i810_driver_dma_quiescent(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index ec12f7dc717a..f9924ad04d09 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c | |||
| @@ -57,13 +57,12 @@ static const struct file_operations i810_driver_fops = { | |||
| 57 | static struct drm_driver driver = { | 57 | static struct drm_driver driver = { |
| 58 | .driver_features = | 58 | .driver_features = |
| 59 | DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | | 59 | DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | |
| 60 | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE, | 60 | DRIVER_HAVE_DMA, |
| 61 | .dev_priv_size = sizeof(drm_i810_buf_priv_t), | 61 | .dev_priv_size = sizeof(drm_i810_buf_priv_t), |
| 62 | .load = i810_driver_load, | 62 | .load = i810_driver_load, |
| 63 | .lastclose = i810_driver_lastclose, | 63 | .lastclose = i810_driver_lastclose, |
| 64 | .preclose = i810_driver_preclose, | 64 | .preclose = i810_driver_preclose, |
| 65 | .device_is_agp = i810_driver_device_is_agp, | 65 | .device_is_agp = i810_driver_device_is_agp, |
| 66 | .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked, | ||
| 67 | .dma_quiescent = i810_driver_dma_quiescent, | 66 | .dma_quiescent = i810_driver_dma_quiescent, |
| 68 | .ioctls = i810_ioctls, | 67 | .ioctls = i810_ioctls, |
| 69 | .fops = &i810_driver_fops, | 68 | .fops = &i810_driver_fops, |
diff --git a/drivers/gpu/drm/i810/i810_drv.h b/drivers/gpu/drm/i810/i810_drv.h index c9339f481795..6e0acad9e0f5 100644 --- a/drivers/gpu/drm/i810/i810_drv.h +++ b/drivers/gpu/drm/i810/i810_drv.h | |||
| @@ -116,14 +116,12 @@ typedef struct drm_i810_private { | |||
| 116 | 116 | ||
| 117 | /* i810_dma.c */ | 117 | /* i810_dma.c */ |
| 118 | extern int i810_driver_dma_quiescent(struct drm_device *dev); | 118 | extern int i810_driver_dma_quiescent(struct drm_device *dev); |
| 119 | extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev, | 119 | void i810_driver_reclaim_buffers(struct drm_device *dev, |
| 120 | struct drm_file *file_priv); | 120 | struct drm_file *file_priv); |
| 121 | extern int i810_driver_load(struct drm_device *, unsigned long flags); | 121 | extern int i810_driver_load(struct drm_device *, unsigned long flags); |
| 122 | extern void i810_driver_lastclose(struct drm_device *dev); | 122 | extern void i810_driver_lastclose(struct drm_device *dev); |
| 123 | extern void i810_driver_preclose(struct drm_device *dev, | 123 | extern void i810_driver_preclose(struct drm_device *dev, |
| 124 | struct drm_file *file_priv); | 124 | struct drm_file *file_priv); |
| 125 | extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev, | ||
| 126 | struct drm_file *file_priv); | ||
| 127 | extern int i810_driver_device_is_agp(struct drm_device *dev); | 125 | extern int i810_driver_device_is_agp(struct drm_device *dev); |
| 128 | 126 | ||
| 129 | extern long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg); | 127 | extern long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg); |
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 2e9268da58d8..b0bacdba6d7e 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile | |||
| @@ -7,6 +7,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \ | |||
| 7 | i915_debugfs.o \ | 7 | i915_debugfs.o \ |
| 8 | i915_suspend.o \ | 8 | i915_suspend.o \ |
| 9 | i915_gem.o \ | 9 | i915_gem.o \ |
| 10 | i915_gem_context.o \ | ||
| 10 | i915_gem_debug.o \ | 11 | i915_gem_debug.o \ |
| 11 | i915_gem_evict.o \ | 12 | i915_gem_evict.o \ |
| 12 | i915_gem_execbuffer.o \ | 13 | i915_gem_execbuffer.o \ |
diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h index 8c2ad014c47f..58914691a77b 100644 --- a/drivers/gpu/drm/i915/dvo.h +++ b/drivers/gpu/drm/i915/dvo.h | |||
| @@ -86,7 +86,7 @@ struct intel_dvo_dev_ops { | |||
| 86 | * buses with clock limitations. | 86 | * buses with clock limitations. |
| 87 | */ | 87 | */ |
| 88 | bool (*mode_fixup)(struct intel_dvo_device *dvo, | 88 | bool (*mode_fixup)(struct intel_dvo_device *dvo, |
| 89 | struct drm_display_mode *mode, | 89 | const struct drm_display_mode *mode, |
| 90 | struct drm_display_mode *adjusted_mode); | 90 | struct drm_display_mode *adjusted_mode); |
| 91 | 91 | ||
| 92 | /* | 92 | /* |
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 5363e9c66c27..2909b123baf5 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
| @@ -713,6 +713,7 @@ static int i915_error_state(struct seq_file *m, void *unused) | |||
| 713 | seq_printf(m, "EIR: 0x%08x\n", error->eir); | 713 | seq_printf(m, "EIR: 0x%08x\n", error->eir); |
| 714 | seq_printf(m, "IER: 0x%08x\n", error->ier); | 714 | seq_printf(m, "IER: 0x%08x\n", error->ier); |
| 715 | seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); | 715 | seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); |
| 716 | seq_printf(m, "CCID: 0x%08x\n", error->ccid); | ||
| 716 | 717 | ||
| 717 | for (i = 0; i < dev_priv->num_fence_regs; i++) | 718 | for (i = 0; i < dev_priv->num_fence_regs; i++) |
| 718 | seq_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); | 719 | seq_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); |
| @@ -1765,6 +1766,64 @@ static const struct file_operations i915_max_freq_fops = { | |||
| 1765 | }; | 1766 | }; |
| 1766 | 1767 | ||
| 1767 | static ssize_t | 1768 | static ssize_t |
| 1769 | i915_min_freq_read(struct file *filp, char __user *ubuf, size_t max, | ||
| 1770 | loff_t *ppos) | ||
| 1771 | { | ||
| 1772 | struct drm_device *dev = filp->private_data; | ||
| 1773 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 1774 | char buf[80]; | ||
| 1775 | int len; | ||
| 1776 | |||
| 1777 | len = snprintf(buf, sizeof(buf), | ||
| 1778 | "min freq: %d\n", dev_priv->min_delay * 50); | ||
| 1779 | |||
| 1780 | if (len > sizeof(buf)) | ||
| 1781 | len = sizeof(buf); | ||
| 1782 | |||
| 1783 | return simple_read_from_buffer(ubuf, max, ppos, buf, len); | ||
| 1784 | } | ||
| 1785 | |||
| 1786 | static ssize_t | ||
| 1787 | i915_min_freq_write(struct file *filp, const char __user *ubuf, size_t cnt, | ||
| 1788 | loff_t *ppos) | ||
| 1789 | { | ||
| 1790 | struct drm_device *dev = filp->private_data; | ||
| 1791 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1792 | char buf[20]; | ||
| 1793 | int val = 1; | ||
| 1794 | |||
| 1795 | if (cnt > 0) { | ||
| 1796 | if (cnt > sizeof(buf) - 1) | ||
| 1797 | return -EINVAL; | ||
| 1798 | |||
| 1799 | if (copy_from_user(buf, ubuf, cnt)) | ||
| 1800 | return -EFAULT; | ||
| 1801 | buf[cnt] = 0; | ||
| 1802 | |||
| 1803 | val = simple_strtoul(buf, NULL, 0); | ||
| 1804 | } | ||
| 1805 | |||
| 1806 | DRM_DEBUG_DRIVER("Manually setting min freq to %d\n", val); | ||
| 1807 | |||
| 1808 | /* | ||
| 1809 | * Turbo will still be enabled, but won't go below the set value. | ||
| 1810 | */ | ||
| 1811 | dev_priv->min_delay = val / 50; | ||
| 1812 | |||
| 1813 | gen6_set_rps(dev, val / 50); | ||
| 1814 | |||
| 1815 | return cnt; | ||
| 1816 | } | ||
| 1817 | |||
| 1818 | static const struct file_operations i915_min_freq_fops = { | ||
| 1819 | .owner = THIS_MODULE, | ||
| 1820 | .open = simple_open, | ||
| 1821 | .read = i915_min_freq_read, | ||
| 1822 | .write = i915_min_freq_write, | ||
| 1823 | .llseek = default_llseek, | ||
| 1824 | }; | ||
| 1825 | |||
| 1826 | static ssize_t | ||
| 1768 | i915_cache_sharing_read(struct file *filp, | 1827 | i915_cache_sharing_read(struct file *filp, |
| 1769 | char __user *ubuf, | 1828 | char __user *ubuf, |
| 1770 | size_t max, | 1829 | size_t max, |
| @@ -1997,6 +2056,12 @@ int i915_debugfs_init(struct drm_minor *minor) | |||
| 1997 | return ret; | 2056 | return ret; |
| 1998 | 2057 | ||
| 1999 | ret = i915_debugfs_create(minor->debugfs_root, minor, | 2058 | ret = i915_debugfs_create(minor->debugfs_root, minor, |
| 2059 | "i915_min_freq", | ||
| 2060 | &i915_min_freq_fops); | ||
| 2061 | if (ret) | ||
| 2062 | return ret; | ||
| 2063 | |||
| 2064 | ret = i915_debugfs_create(minor->debugfs_root, minor, | ||
| 2000 | "i915_cache_sharing", | 2065 | "i915_cache_sharing", |
| 2001 | &i915_cache_sharing_fops); | 2066 | &i915_cache_sharing_fops); |
| 2002 | if (ret) | 2067 | if (ret) |
| @@ -2028,6 +2093,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor) | |||
| 2028 | 1, minor); | 2093 | 1, minor); |
| 2029 | drm_debugfs_remove_files((struct drm_info_list *) &i915_max_freq_fops, | 2094 | drm_debugfs_remove_files((struct drm_info_list *) &i915_max_freq_fops, |
| 2030 | 1, minor); | 2095 | 1, minor); |
| 2096 | drm_debugfs_remove_files((struct drm_info_list *) &i915_min_freq_fops, | ||
| 2097 | 1, minor); | ||
| 2031 | drm_debugfs_remove_files((struct drm_info_list *) &i915_cache_sharing_fops, | 2098 | drm_debugfs_remove_files((struct drm_info_list *) &i915_cache_sharing_fops, |
| 2032 | 1, minor); | 2099 | 1, minor); |
| 2033 | drm_debugfs_remove_files((struct drm_info_list *) &i915_ring_stop_fops, | 2100 | drm_debugfs_remove_files((struct drm_info_list *) &i915_ring_stop_fops, |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 36822b924eb1..f64ef4b723fd 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
| @@ -1006,6 +1006,9 @@ static int i915_getparam(struct drm_device *dev, void *data, | |||
| 1006 | case I915_PARAM_HAS_ALIASING_PPGTT: | 1006 | case I915_PARAM_HAS_ALIASING_PPGTT: |
| 1007 | value = dev_priv->mm.aliasing_ppgtt ? 1 : 0; | 1007 | value = dev_priv->mm.aliasing_ppgtt ? 1 : 0; |
| 1008 | break; | 1008 | break; |
| 1009 | case I915_PARAM_HAS_WAIT_TIMEOUT: | ||
| 1010 | value = 1; | ||
| 1011 | break; | ||
| 1009 | default: | 1012 | default: |
| 1010 | DRM_DEBUG_DRIVER("Unknown parameter %d\n", | 1013 | DRM_DEBUG_DRIVER("Unknown parameter %d\n", |
| 1011 | param->param); | 1014 | param->param); |
| @@ -1082,8 +1085,8 @@ static int i915_set_status_page(struct drm_device *dev, void *data, | |||
| 1082 | 1085 | ||
| 1083 | ring->status_page.gfx_addr = hws->addr & (0x1ffff<<12); | 1086 | ring->status_page.gfx_addr = hws->addr & (0x1ffff<<12); |
| 1084 | 1087 | ||
| 1085 | dev_priv->dri1.gfx_hws_cpu_addr = ioremap_wc(dev->agp->base + hws->addr, | 1088 | dev_priv->dri1.gfx_hws_cpu_addr = |
| 1086 | 4096); | 1089 | ioremap_wc(dev_priv->mm.gtt_base_addr + hws->addr, 4096); |
| 1087 | if (dev_priv->dri1.gfx_hws_cpu_addr == NULL) { | 1090 | if (dev_priv->dri1.gfx_hws_cpu_addr == NULL) { |
| 1088 | i915_dma_cleanup(dev); | 1091 | i915_dma_cleanup(dev); |
| 1089 | ring->status_page.gfx_addr = 0; | 1092 | ring->status_page.gfx_addr = 0; |
| @@ -1411,7 +1414,7 @@ static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv) | |||
| 1411 | if (!ap) | 1414 | if (!ap) |
| 1412 | return; | 1415 | return; |
| 1413 | 1416 | ||
| 1414 | ap->ranges[0].base = dev_priv->dev->agp->base; | 1417 | ap->ranges[0].base = dev_priv->mm.gtt->gma_bus_addr; |
| 1415 | ap->ranges[0].size = | 1418 | ap->ranges[0].size = |
| 1416 | dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; | 1419 | dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; |
| 1417 | primary = | 1420 | primary = |
| @@ -1467,11 +1470,18 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1467 | goto free_priv; | 1470 | goto free_priv; |
| 1468 | } | 1471 | } |
| 1469 | 1472 | ||
| 1473 | ret = intel_gmch_probe(dev_priv->bridge_dev, dev->pdev, NULL); | ||
| 1474 | if (!ret) { | ||
| 1475 | DRM_ERROR("failed to set up gmch\n"); | ||
| 1476 | ret = -EIO; | ||
| 1477 | goto put_bridge; | ||
| 1478 | } | ||
| 1479 | |||
| 1470 | dev_priv->mm.gtt = intel_gtt_get(); | 1480 | dev_priv->mm.gtt = intel_gtt_get(); |
| 1471 | if (!dev_priv->mm.gtt) { | 1481 | if (!dev_priv->mm.gtt) { |
| 1472 | DRM_ERROR("Failed to initialize GTT\n"); | 1482 | DRM_ERROR("Failed to initialize GTT\n"); |
| 1473 | ret = -ENODEV; | 1483 | ret = -ENODEV; |
| 1474 | goto put_bridge; | 1484 | goto put_gmch; |
| 1475 | } | 1485 | } |
| 1476 | 1486 | ||
| 1477 | i915_kick_out_firmware_fb(dev_priv); | 1487 | i915_kick_out_firmware_fb(dev_priv); |
| @@ -1498,19 +1508,22 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1498 | if (!dev_priv->regs) { | 1508 | if (!dev_priv->regs) { |
| 1499 | DRM_ERROR("failed to map registers\n"); | 1509 | DRM_ERROR("failed to map registers\n"); |
| 1500 | ret = -EIO; | 1510 | ret = -EIO; |
| 1501 | goto put_bridge; | 1511 | goto put_gmch; |
| 1502 | } | 1512 | } |
| 1503 | 1513 | ||
| 1504 | aperture_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; | 1514 | aperture_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; |
| 1515 | dev_priv->mm.gtt_base_addr = dev_priv->mm.gtt->gma_bus_addr; | ||
| 1505 | 1516 | ||
| 1506 | dev_priv->mm.gtt_mapping = | 1517 | dev_priv->mm.gtt_mapping = |
| 1507 | io_mapping_create_wc(dev->agp->base, aperture_size); | 1518 | io_mapping_create_wc(dev_priv->mm.gtt_base_addr, |
| 1519 | aperture_size); | ||
| 1508 | if (dev_priv->mm.gtt_mapping == NULL) { | 1520 | if (dev_priv->mm.gtt_mapping == NULL) { |
| 1509 | ret = -EIO; | 1521 | ret = -EIO; |
| 1510 | goto out_rmmap; | 1522 | goto out_rmmap; |
| 1511 | } | 1523 | } |
| 1512 | 1524 | ||
| 1513 | i915_mtrr_setup(dev_priv, dev->agp->base, aperture_size); | 1525 | i915_mtrr_setup(dev_priv, dev_priv->mm.gtt_base_addr, |
| 1526 | aperture_size); | ||
| 1514 | 1527 | ||
| 1515 | /* The i915 workqueue is primarily used for batched retirement of | 1528 | /* The i915 workqueue is primarily used for batched retirement of |
| 1516 | * requests (and thus managing bo) once the task has been completed | 1529 | * requests (and thus managing bo) once the task has been completed |
| @@ -1534,7 +1547,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1534 | goto out_mtrrfree; | 1547 | goto out_mtrrfree; |
| 1535 | } | 1548 | } |
| 1536 | 1549 | ||
| 1550 | /* This must be called before any calls to HAS_PCH_* */ | ||
| 1551 | intel_detect_pch(dev); | ||
| 1552 | |||
| 1537 | intel_irq_init(dev); | 1553 | intel_irq_init(dev); |
| 1554 | intel_gt_init(dev); | ||
| 1538 | 1555 | ||
| 1539 | /* Try to make sure MCHBAR is enabled before poking at it */ | 1556 | /* Try to make sure MCHBAR is enabled before poking at it */ |
| 1540 | intel_setup_mchbar(dev); | 1557 | intel_setup_mchbar(dev); |
| @@ -1567,7 +1584,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1567 | if (!IS_I945G(dev) && !IS_I945GM(dev)) | 1584 | if (!IS_I945G(dev) && !IS_I945GM(dev)) |
| 1568 | pci_enable_msi(dev->pdev); | 1585 | pci_enable_msi(dev->pdev); |
| 1569 | 1586 | ||
| 1570 | spin_lock_init(&dev_priv->gt_lock); | ||
| 1571 | spin_lock_init(&dev_priv->irq_lock); | 1587 | spin_lock_init(&dev_priv->irq_lock); |
| 1572 | spin_lock_init(&dev_priv->error_lock); | 1588 | spin_lock_init(&dev_priv->error_lock); |
| 1573 | spin_lock_init(&dev_priv->rps_lock); | 1589 | spin_lock_init(&dev_priv->rps_lock); |
| @@ -1586,8 +1602,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1586 | /* Start out suspended */ | 1602 | /* Start out suspended */ |
| 1587 | dev_priv->mm.suspended = 1; | 1603 | dev_priv->mm.suspended = 1; |
| 1588 | 1604 | ||
| 1589 | intel_detect_pch(dev); | ||
| 1590 | |||
| 1591 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 1605 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
| 1592 | ret = i915_load_modeset_init(dev); | 1606 | ret = i915_load_modeset_init(dev); |
| 1593 | if (ret < 0) { | 1607 | if (ret < 0) { |
| @@ -1622,13 +1636,16 @@ out_gem_unload: | |||
| 1622 | destroy_workqueue(dev_priv->wq); | 1636 | destroy_workqueue(dev_priv->wq); |
| 1623 | out_mtrrfree: | 1637 | out_mtrrfree: |
| 1624 | if (dev_priv->mm.gtt_mtrr >= 0) { | 1638 | if (dev_priv->mm.gtt_mtrr >= 0) { |
| 1625 | mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base, | 1639 | mtrr_del(dev_priv->mm.gtt_mtrr, |
| 1626 | dev->agp->agp_info.aper_size * 1024 * 1024); | 1640 | dev_priv->mm.gtt_base_addr, |
| 1641 | aperture_size); | ||
| 1627 | dev_priv->mm.gtt_mtrr = -1; | 1642 | dev_priv->mm.gtt_mtrr = -1; |
| 1628 | } | 1643 | } |
| 1629 | io_mapping_free(dev_priv->mm.gtt_mapping); | 1644 | io_mapping_free(dev_priv->mm.gtt_mapping); |
| 1630 | out_rmmap: | 1645 | out_rmmap: |
| 1631 | pci_iounmap(dev->pdev, dev_priv->regs); | 1646 | pci_iounmap(dev->pdev, dev_priv->regs); |
| 1647 | put_gmch: | ||
| 1648 | intel_gmch_remove(); | ||
| 1632 | put_bridge: | 1649 | put_bridge: |
| 1633 | pci_dev_put(dev_priv->bridge_dev); | 1650 | pci_dev_put(dev_priv->bridge_dev); |
| 1634 | free_priv: | 1651 | free_priv: |
| @@ -1660,8 +1677,9 @@ int i915_driver_unload(struct drm_device *dev) | |||
| 1660 | 1677 | ||
| 1661 | io_mapping_free(dev_priv->mm.gtt_mapping); | 1678 | io_mapping_free(dev_priv->mm.gtt_mapping); |
| 1662 | if (dev_priv->mm.gtt_mtrr >= 0) { | 1679 | if (dev_priv->mm.gtt_mtrr >= 0) { |
| 1663 | mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base, | 1680 | mtrr_del(dev_priv->mm.gtt_mtrr, |
| 1664 | dev->agp->agp_info.aper_size * 1024 * 1024); | 1681 | dev_priv->mm.gtt_base_addr, |
| 1682 | dev_priv->mm.gtt->gtt_mappable_entries * PAGE_SIZE); | ||
| 1665 | dev_priv->mm.gtt_mtrr = -1; | 1683 | dev_priv->mm.gtt_mtrr = -1; |
| 1666 | } | 1684 | } |
| 1667 | 1685 | ||
| @@ -1702,6 +1720,7 @@ int i915_driver_unload(struct drm_device *dev) | |||
| 1702 | mutex_lock(&dev->struct_mutex); | 1720 | mutex_lock(&dev->struct_mutex); |
| 1703 | i915_gem_free_all_phys_object(dev); | 1721 | i915_gem_free_all_phys_object(dev); |
| 1704 | i915_gem_cleanup_ringbuffer(dev); | 1722 | i915_gem_cleanup_ringbuffer(dev); |
| 1723 | i915_gem_context_fini(dev); | ||
| 1705 | mutex_unlock(&dev->struct_mutex); | 1724 | mutex_unlock(&dev->struct_mutex); |
| 1706 | i915_gem_cleanup_aliasing_ppgtt(dev); | 1725 | i915_gem_cleanup_aliasing_ppgtt(dev); |
| 1707 | i915_gem_cleanup_stolen(dev); | 1726 | i915_gem_cleanup_stolen(dev); |
| @@ -1741,6 +1760,8 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file) | |||
| 1741 | spin_lock_init(&file_priv->mm.lock); | 1760 | spin_lock_init(&file_priv->mm.lock); |
| 1742 | INIT_LIST_HEAD(&file_priv->mm.request_list); | 1761 | INIT_LIST_HEAD(&file_priv->mm.request_list); |
| 1743 | 1762 | ||
| 1763 | idr_init(&file_priv->context_idr); | ||
| 1764 | |||
| 1744 | return 0; | 1765 | return 0; |
| 1745 | } | 1766 | } |
| 1746 | 1767 | ||
| @@ -1773,6 +1794,7 @@ void i915_driver_lastclose(struct drm_device * dev) | |||
| 1773 | 1794 | ||
| 1774 | void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) | 1795 | void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) |
| 1775 | { | 1796 | { |
| 1797 | i915_gem_context_close(dev, file_priv); | ||
| 1776 | i915_gem_release(dev, file_priv); | 1798 | i915_gem_release(dev, file_priv); |
| 1777 | } | 1799 | } |
| 1778 | 1800 | ||
| @@ -1826,6 +1848,9 @@ struct drm_ioctl_desc i915_ioctls[] = { | |||
| 1826 | DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 1848 | DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
| 1827 | DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 1849 | DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
| 1828 | DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, intel_sprite_get_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), | 1850 | DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, intel_sprite_get_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), |
| 1851 | DRM_IOCTL_DEF_DRV(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_AUTH|DRM_UNLOCKED), | ||
| 1852 | DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_UNLOCKED), | ||
| 1853 | DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_UNLOCKED), | ||
| 1829 | }; | 1854 | }; |
| 1830 | 1855 | ||
| 1831 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); | 1856 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 9fe9ebe52a7a..ed22612bc847 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include "drm.h" | 32 | #include "drm.h" |
| 33 | #include "i915_drm.h" | 33 | #include "i915_drm.h" |
| 34 | #include "i915_drv.h" | 34 | #include "i915_drv.h" |
| 35 | #include "i915_trace.h" | ||
| 35 | #include "intel_drv.h" | 36 | #include "intel_drv.h" |
| 36 | 37 | ||
| 37 | #include <linux/console.h> | 38 | #include <linux/console.h> |
| @@ -215,7 +216,6 @@ static const struct intel_device_info intel_ironlake_d_info = { | |||
| 215 | .gen = 5, | 216 | .gen = 5, |
| 216 | .need_gfx_hws = 1, .has_hotplug = 1, | 217 | .need_gfx_hws = 1, .has_hotplug = 1, |
| 217 | .has_bsd_ring = 1, | 218 | .has_bsd_ring = 1, |
| 218 | .has_pch_split = 1, | ||
| 219 | }; | 219 | }; |
| 220 | 220 | ||
| 221 | static const struct intel_device_info intel_ironlake_m_info = { | 221 | static const struct intel_device_info intel_ironlake_m_info = { |
| @@ -223,7 +223,6 @@ static const struct intel_device_info intel_ironlake_m_info = { | |||
| 223 | .need_gfx_hws = 1, .has_hotplug = 1, | 223 | .need_gfx_hws = 1, .has_hotplug = 1, |
| 224 | .has_fbc = 1, | 224 | .has_fbc = 1, |
| 225 | .has_bsd_ring = 1, | 225 | .has_bsd_ring = 1, |
| 226 | .has_pch_split = 1, | ||
| 227 | }; | 226 | }; |
| 228 | 227 | ||
| 229 | static const struct intel_device_info intel_sandybridge_d_info = { | 228 | static const struct intel_device_info intel_sandybridge_d_info = { |
| @@ -232,7 +231,6 @@ static const struct intel_device_info intel_sandybridge_d_info = { | |||
| 232 | .has_bsd_ring = 1, | 231 | .has_bsd_ring = 1, |
| 233 | .has_blt_ring = 1, | 232 | .has_blt_ring = 1, |
| 234 | .has_llc = 1, | 233 | .has_llc = 1, |
| 235 | .has_pch_split = 1, | ||
| 236 | .has_force_wake = 1, | 234 | .has_force_wake = 1, |
| 237 | }; | 235 | }; |
| 238 | 236 | ||
| @@ -243,7 +241,6 @@ static const struct intel_device_info intel_sandybridge_m_info = { | |||
| 243 | .has_bsd_ring = 1, | 241 | .has_bsd_ring = 1, |
| 244 | .has_blt_ring = 1, | 242 | .has_blt_ring = 1, |
| 245 | .has_llc = 1, | 243 | .has_llc = 1, |
| 246 | .has_pch_split = 1, | ||
| 247 | .has_force_wake = 1, | 244 | .has_force_wake = 1, |
| 248 | }; | 245 | }; |
| 249 | 246 | ||
| @@ -253,7 +250,6 @@ static const struct intel_device_info intel_ivybridge_d_info = { | |||
| 253 | .has_bsd_ring = 1, | 250 | .has_bsd_ring = 1, |
| 254 | .has_blt_ring = 1, | 251 | .has_blt_ring = 1, |
| 255 | .has_llc = 1, | 252 | .has_llc = 1, |
| 256 | .has_pch_split = 1, | ||
| 257 | .has_force_wake = 1, | 253 | .has_force_wake = 1, |
| 258 | }; | 254 | }; |
| 259 | 255 | ||
| @@ -264,7 +260,6 @@ static const struct intel_device_info intel_ivybridge_m_info = { | |||
| 264 | .has_bsd_ring = 1, | 260 | .has_bsd_ring = 1, |
| 265 | .has_blt_ring = 1, | 261 | .has_blt_ring = 1, |
| 266 | .has_llc = 1, | 262 | .has_llc = 1, |
| 267 | .has_pch_split = 1, | ||
| 268 | .has_force_wake = 1, | 263 | .has_force_wake = 1, |
| 269 | }; | 264 | }; |
| 270 | 265 | ||
| @@ -292,7 +287,6 @@ static const struct intel_device_info intel_haswell_d_info = { | |||
| 292 | .has_bsd_ring = 1, | 287 | .has_bsd_ring = 1, |
| 293 | .has_blt_ring = 1, | 288 | .has_blt_ring = 1, |
| 294 | .has_llc = 1, | 289 | .has_llc = 1, |
| 295 | .has_pch_split = 1, | ||
| 296 | .has_force_wake = 1, | 290 | .has_force_wake = 1, |
| 297 | }; | 291 | }; |
| 298 | 292 | ||
| @@ -302,7 +296,6 @@ static const struct intel_device_info intel_haswell_m_info = { | |||
| 302 | .has_bsd_ring = 1, | 296 | .has_bsd_ring = 1, |
| 303 | .has_blt_ring = 1, | 297 | .has_blt_ring = 1, |
| 304 | .has_llc = 1, | 298 | .has_llc = 1, |
| 305 | .has_pch_split = 1, | ||
| 306 | .has_force_wake = 1, | 299 | .has_force_wake = 1, |
| 307 | }; | 300 | }; |
| 308 | 301 | ||
| @@ -358,6 +351,9 @@ static const struct pci_device_id pciidlist[] = { /* aka */ | |||
| 358 | INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */ | 351 | INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */ |
| 359 | INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */ | 352 | INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */ |
| 360 | INTEL_VGA_DEVICE(0x0c16, &intel_haswell_d_info), /* SDV */ | 353 | INTEL_VGA_DEVICE(0x0c16, &intel_haswell_d_info), /* SDV */ |
| 354 | INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info), | ||
| 355 | INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info), | ||
| 356 | INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info), | ||
| 361 | {0, 0, 0} | 357 | {0, 0, 0} |
| 362 | }; | 358 | }; |
| 363 | 359 | ||
| @@ -429,135 +425,6 @@ bool i915_semaphore_is_enabled(struct drm_device *dev) | |||
| 429 | return 1; | 425 | return 1; |
| 430 | } | 426 | } |
| 431 | 427 | ||
| 432 | void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) | ||
| 433 | { | ||
| 434 | int count; | ||
| 435 | |||
| 436 | count = 0; | ||
| 437 | while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1)) | ||
| 438 | udelay(10); | ||
| 439 | |||
| 440 | I915_WRITE_NOTRACE(FORCEWAKE, 1); | ||
| 441 | POSTING_READ(FORCEWAKE); | ||
| 442 | |||
| 443 | count = 0; | ||
| 444 | while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1) == 0) | ||
| 445 | udelay(10); | ||
| 446 | } | ||
| 447 | |||
| 448 | void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) | ||
| 449 | { | ||
| 450 | int count; | ||
| 451 | |||
| 452 | count = 0; | ||
| 453 | while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1)) | ||
| 454 | udelay(10); | ||
| 455 | |||
| 456 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1)); | ||
| 457 | POSTING_READ(FORCEWAKE_MT); | ||
| 458 | |||
| 459 | count = 0; | ||
| 460 | while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1) == 0) | ||
| 461 | udelay(10); | ||
| 462 | } | ||
| 463 | |||
| 464 | /* | ||
| 465 | * Generally this is called implicitly by the register read function. However, | ||
| 466 | * if some sequence requires the GT to not power down then this function should | ||
| 467 | * be called at the beginning of the sequence followed by a call to | ||
| 468 | * gen6_gt_force_wake_put() at the end of the sequence. | ||
| 469 | */ | ||
| 470 | void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) | ||
| 471 | { | ||
| 472 | unsigned long irqflags; | ||
| 473 | |||
| 474 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); | ||
| 475 | if (dev_priv->forcewake_count++ == 0) | ||
| 476 | dev_priv->display.force_wake_get(dev_priv); | ||
| 477 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); | ||
| 478 | } | ||
| 479 | |||
| 480 | static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) | ||
| 481 | { | ||
| 482 | u32 gtfifodbg; | ||
| 483 | gtfifodbg = I915_READ_NOTRACE(GTFIFODBG); | ||
| 484 | if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK, | ||
| 485 | "MMIO read or write has been dropped %x\n", gtfifodbg)) | ||
| 486 | I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK); | ||
| 487 | } | ||
| 488 | |||
| 489 | void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) | ||
| 490 | { | ||
| 491 | I915_WRITE_NOTRACE(FORCEWAKE, 0); | ||
| 492 | /* The below doubles as a POSTING_READ */ | ||
| 493 | gen6_gt_check_fifodbg(dev_priv); | ||
| 494 | } | ||
| 495 | |||
| 496 | void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) | ||
| 497 | { | ||
| 498 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1)); | ||
| 499 | /* The below doubles as a POSTING_READ */ | ||
| 500 | gen6_gt_check_fifodbg(dev_priv); | ||
| 501 | } | ||
| 502 | |||
| 503 | /* | ||
| 504 | * see gen6_gt_force_wake_get() | ||
| 505 | */ | ||
| 506 | void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) | ||
| 507 | { | ||
| 508 | unsigned long irqflags; | ||
| 509 | |||
| 510 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); | ||
| 511 | if (--dev_priv->forcewake_count == 0) | ||
| 512 | dev_priv->display.force_wake_put(dev_priv); | ||
| 513 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); | ||
| 514 | } | ||
| 515 | |||
| 516 | int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) | ||
| 517 | { | ||
| 518 | int ret = 0; | ||
| 519 | |||
| 520 | if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) { | ||
| 521 | int loop = 500; | ||
| 522 | u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); | ||
| 523 | while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) { | ||
| 524 | udelay(10); | ||
| 525 | fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); | ||
| 526 | } | ||
| 527 | if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES)) | ||
| 528 | ++ret; | ||
| 529 | dev_priv->gt_fifo_count = fifo; | ||
| 530 | } | ||
| 531 | dev_priv->gt_fifo_count--; | ||
| 532 | |||
| 533 | return ret; | ||
| 534 | } | ||
| 535 | |||
| 536 | void vlv_force_wake_get(struct drm_i915_private *dev_priv) | ||
| 537 | { | ||
| 538 | int count; | ||
| 539 | |||
| 540 | count = 0; | ||
| 541 | |||
| 542 | /* Already awake? */ | ||
| 543 | if ((I915_READ(0x130094) & 0xa1) == 0xa1) | ||
| 544 | return; | ||
| 545 | |||
| 546 | I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffffffff); | ||
| 547 | POSTING_READ(FORCEWAKE_VLV); | ||
| 548 | |||
| 549 | count = 0; | ||
| 550 | while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1) == 0) | ||
| 551 | udelay(10); | ||
| 552 | } | ||
| 553 | |||
| 554 | void vlv_force_wake_put(struct drm_i915_private *dev_priv) | ||
| 555 | { | ||
| 556 | I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffff0000); | ||
| 557 | /* FIXME: confirm VLV behavior with Punit folks */ | ||
| 558 | POSTING_READ(FORCEWAKE_VLV); | ||
| 559 | } | ||
| 560 | |||
| 561 | static int i915_drm_freeze(struct drm_device *dev) | 428 | static int i915_drm_freeze(struct drm_device *dev) |
| 562 | { | 429 | { |
| 563 | struct drm_i915_private *dev_priv = dev->dev_private; | 430 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -637,7 +504,7 @@ static int i915_drm_thaw(struct drm_device *dev) | |||
| 637 | 504 | ||
| 638 | /* KMS EnterVT equivalent */ | 505 | /* KMS EnterVT equivalent */ |
| 639 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 506 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
| 640 | if (HAS_PCH_SPLIT(dev)) | 507 | if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) |
| 641 | ironlake_init_pch_refclk(dev); | 508 | ironlake_init_pch_refclk(dev); |
| 642 | 509 | ||
| 643 | mutex_lock(&dev->struct_mutex); | 510 | mutex_lock(&dev->struct_mutex); |
| @@ -794,9 +661,9 @@ static int gen6_do_reset(struct drm_device *dev) | |||
| 794 | 661 | ||
| 795 | /* If reset with a user forcewake, try to restore, otherwise turn it off */ | 662 | /* If reset with a user forcewake, try to restore, otherwise turn it off */ |
| 796 | if (dev_priv->forcewake_count) | 663 | if (dev_priv->forcewake_count) |
| 797 | dev_priv->display.force_wake_get(dev_priv); | 664 | dev_priv->gt.force_wake_get(dev_priv); |
| 798 | else | 665 | else |
| 799 | dev_priv->display.force_wake_put(dev_priv); | 666 | dev_priv->gt.force_wake_put(dev_priv); |
| 800 | 667 | ||
| 801 | /* Restore fifo count */ | 668 | /* Restore fifo count */ |
| 802 | dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); | 669 | dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); |
| @@ -805,7 +672,7 @@ static int gen6_do_reset(struct drm_device *dev) | |||
| 805 | return ret; | 672 | return ret; |
| 806 | } | 673 | } |
| 807 | 674 | ||
| 808 | static int intel_gpu_reset(struct drm_device *dev) | 675 | int intel_gpu_reset(struct drm_device *dev) |
| 809 | { | 676 | { |
| 810 | struct drm_i915_private *dev_priv = dev->dev_private; | 677 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 811 | int ret = -ENODEV; | 678 | int ret = -ENODEV; |
| @@ -863,10 +730,7 @@ int i915_reset(struct drm_device *dev) | |||
| 863 | if (!i915_try_reset) | 730 | if (!i915_try_reset) |
| 864 | return 0; | 731 | return 0; |
| 865 | 732 | ||
| 866 | if (!mutex_trylock(&dev->struct_mutex)) | 733 | mutex_lock(&dev->struct_mutex); |
| 867 | return -EBUSY; | ||
| 868 | |||
| 869 | dev_priv->stop_rings = 0; | ||
| 870 | 734 | ||
| 871 | i915_gem_reset(dev); | 735 | i915_gem_reset(dev); |
| 872 | 736 | ||
| @@ -909,12 +773,16 @@ int i915_reset(struct drm_device *dev) | |||
| 909 | for_each_ring(ring, dev_priv, i) | 773 | for_each_ring(ring, dev_priv, i) |
| 910 | ring->init(ring); | 774 | ring->init(ring); |
| 911 | 775 | ||
| 776 | i915_gem_context_init(dev); | ||
| 912 | i915_gem_init_ppgtt(dev); | 777 | i915_gem_init_ppgtt(dev); |
| 913 | 778 | ||
| 914 | mutex_unlock(&dev->struct_mutex); | 779 | /* |
| 780 | * It would make sense to re-init all the other hw state, at | ||
| 781 | * least the rps/rc6/emon init done within modeset_init_hw. For | ||
| 782 | * some unknown reason, this blows up my ilk, so don't. | ||
| 783 | */ | ||
| 915 | 784 | ||
| 916 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | 785 | mutex_unlock(&dev->struct_mutex); |
| 917 | intel_modeset_init_hw(dev); | ||
| 918 | 786 | ||
| 919 | drm_irq_uninstall(dev); | 787 | drm_irq_uninstall(dev); |
| 920 | drm_irq_install(dev); | 788 | drm_irq_install(dev); |
| @@ -925,10 +793,12 @@ int i915_reset(struct drm_device *dev) | |||
| 925 | return 0; | 793 | return 0; |
| 926 | } | 794 | } |
| 927 | 795 | ||
| 928 | |||
| 929 | static int __devinit | 796 | static int __devinit |
| 930 | i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 797 | i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
| 931 | { | 798 | { |
| 799 | struct intel_device_info *intel_info = | ||
| 800 | (struct intel_device_info *) ent->driver_data; | ||
| 801 | |||
| 932 | /* Only bind to function 0 of the device. Early generations | 802 | /* Only bind to function 0 of the device. Early generations |
| 933 | * used function 1 as a placeholder for multi-head. This causes | 803 | * used function 1 as a placeholder for multi-head. This causes |
| 934 | * us confusion instead, especially on the systems where both | 804 | * us confusion instead, especially on the systems where both |
| @@ -937,6 +807,18 @@ i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 937 | if (PCI_FUNC(pdev->devfn)) | 807 | if (PCI_FUNC(pdev->devfn)) |
| 938 | return -ENODEV; | 808 | return -ENODEV; |
| 939 | 809 | ||
| 810 | /* We've managed to ship a kms-enabled ddx that shipped with an XvMC | ||
| 811 | * implementation for gen3 (and only gen3) that used legacy drm maps | ||
| 812 | * (gasp!) to share buffers between X and the client. Hence we need to | ||
| 813 | * keep around the fake agp stuff for gen3, even when kms is enabled. */ | ||
| 814 | if (intel_info->gen != 3) { | ||
| 815 | driver.driver_features &= | ||
| 816 | ~(DRIVER_USE_AGP | DRIVER_REQUIRE_AGP); | ||
| 817 | } else if (!intel_agp_enabled) { | ||
| 818 | DRM_ERROR("drm/i915 can't work without intel_agp module!\n"); | ||
| 819 | return -ENODEV; | ||
| 820 | } | ||
| 821 | |||
| 940 | return drm_get_pci_dev(pdev, ent, &driver); | 822 | return drm_get_pci_dev(pdev, ent, &driver); |
| 941 | } | 823 | } |
| 942 | 824 | ||
| @@ -1058,7 +940,6 @@ static struct drm_driver driver = { | |||
| 1058 | .resume = i915_resume, | 940 | .resume = i915_resume, |
| 1059 | 941 | ||
| 1060 | .device_is_agp = i915_driver_device_is_agp, | 942 | .device_is_agp = i915_driver_device_is_agp, |
| 1061 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 1062 | .master_create = i915_master_create, | 943 | .master_create = i915_master_create, |
| 1063 | .master_destroy = i915_master_destroy, | 944 | .master_destroy = i915_master_destroy, |
| 1064 | #if defined(CONFIG_DEBUG_FS) | 945 | #if defined(CONFIG_DEBUG_FS) |
| @@ -1097,11 +978,6 @@ static struct pci_driver i915_pci_driver = { | |||
| 1097 | 978 | ||
| 1098 | static int __init i915_init(void) | 979 | static int __init i915_init(void) |
| 1099 | { | 980 | { |
| 1100 | if (!intel_agp_enabled) { | ||
| 1101 | DRM_ERROR("drm/i915 can't work without intel_agp module!\n"); | ||
| 1102 | return -ENODEV; | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | driver.num_ioctls = i915_max_ioctl; | 981 | driver.num_ioctls = i915_max_ioctl; |
| 1106 | 982 | ||
| 1107 | /* | 983 | /* |
| @@ -1149,6 +1025,84 @@ MODULE_LICENSE("GPL and additional rights"); | |||
| 1149 | ((reg) < 0x40000) && \ | 1025 | ((reg) < 0x40000) && \ |
| 1150 | ((reg) != FORCEWAKE)) | 1026 | ((reg) != FORCEWAKE)) |
| 1151 | 1027 | ||
| 1028 | static bool IS_DISPLAYREG(u32 reg) | ||
| 1029 | { | ||
| 1030 | /* | ||
| 1031 | * This should make it easier to transition modules over to the | ||
| 1032 | * new register block scheme, since we can do it incrementally. | ||
| 1033 | */ | ||
| 1034 | if (reg >= 0x180000) | ||
| 1035 | return false; | ||
| 1036 | |||
| 1037 | if (reg >= RENDER_RING_BASE && | ||
| 1038 | reg < RENDER_RING_BASE + 0xff) | ||
| 1039 | return false; | ||
| 1040 | if (reg >= GEN6_BSD_RING_BASE && | ||
| 1041 | reg < GEN6_BSD_RING_BASE + 0xff) | ||
| 1042 | return false; | ||
| 1043 | if (reg >= BLT_RING_BASE && | ||
| 1044 | reg < BLT_RING_BASE + 0xff) | ||
| 1045 | return false; | ||
| 1046 | |||
| 1047 | if (reg == PGTBL_ER) | ||
| 1048 | return false; | ||
| 1049 | |||
| 1050 | if (reg >= IPEIR_I965 && | ||
| 1051 | reg < HWSTAM) | ||
| 1052 | return false; | ||
| 1053 | |||
| 1054 | if (reg == MI_MODE) | ||
| 1055 | return false; | ||
| 1056 | |||
| 1057 | if (reg == GFX_MODE_GEN7) | ||
| 1058 | return false; | ||
| 1059 | |||
| 1060 | if (reg == RENDER_HWS_PGA_GEN7 || | ||
| 1061 | reg == BSD_HWS_PGA_GEN7 || | ||
| 1062 | reg == BLT_HWS_PGA_GEN7) | ||
| 1063 | return false; | ||
| 1064 | |||
| 1065 | if (reg == GEN6_BSD_SLEEP_PSMI_CONTROL || | ||
| 1066 | reg == GEN6_BSD_RNCID) | ||
| 1067 | return false; | ||
| 1068 | |||
| 1069 | if (reg == GEN6_BLITTER_ECOSKPD) | ||
| 1070 | return false; | ||
| 1071 | |||
| 1072 | if (reg >= 0x4000c && | ||
| 1073 | reg <= 0x4002c) | ||
| 1074 | return false; | ||
| 1075 | |||
| 1076 | if (reg >= 0x4f000 && | ||
| 1077 | reg <= 0x4f08f) | ||
| 1078 | return false; | ||
| 1079 | |||
| 1080 | if (reg >= 0x4f100 && | ||
| 1081 | reg <= 0x4f11f) | ||
| 1082 | return false; | ||
| 1083 | |||
| 1084 | if (reg >= VLV_MASTER_IER && | ||
| 1085 | reg <= GEN6_PMIER) | ||
| 1086 | return false; | ||
| 1087 | |||
| 1088 | if (reg >= FENCE_REG_SANDYBRIDGE_0 && | ||
| 1089 | reg < (FENCE_REG_SANDYBRIDGE_0 + (16*8))) | ||
| 1090 | return false; | ||
| 1091 | |||
| 1092 | if (reg >= VLV_IIR_RW && | ||
| 1093 | reg <= VLV_ISR) | ||
| 1094 | return false; | ||
| 1095 | |||
| 1096 | if (reg == FORCEWAKE_VLV || | ||
| 1097 | reg == FORCEWAKE_ACK_VLV) | ||
| 1098 | return false; | ||
| 1099 | |||
| 1100 | if (reg == GEN6_GDRST) | ||
| 1101 | return false; | ||
| 1102 | |||
| 1103 | return true; | ||
| 1104 | } | ||
| 1105 | |||
| 1152 | #define __i915_read(x, y) \ | 1106 | #define __i915_read(x, y) \ |
| 1153 | u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ | 1107 | u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ |
| 1154 | u##x val = 0; \ | 1108 | u##x val = 0; \ |
| @@ -1156,11 +1110,13 @@ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ | |||
| 1156 | unsigned long irqflags; \ | 1110 | unsigned long irqflags; \ |
| 1157 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \ | 1111 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \ |
| 1158 | if (dev_priv->forcewake_count == 0) \ | 1112 | if (dev_priv->forcewake_count == 0) \ |
| 1159 | dev_priv->display.force_wake_get(dev_priv); \ | 1113 | dev_priv->gt.force_wake_get(dev_priv); \ |
| 1160 | val = read##y(dev_priv->regs + reg); \ | 1114 | val = read##y(dev_priv->regs + reg); \ |
| 1161 | if (dev_priv->forcewake_count == 0) \ | 1115 | if (dev_priv->forcewake_count == 0) \ |
| 1162 | dev_priv->display.force_wake_put(dev_priv); \ | 1116 | dev_priv->gt.force_wake_put(dev_priv); \ |
| 1163 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \ | 1117 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \ |
| 1118 | } else if (IS_VALLEYVIEW(dev_priv->dev) && IS_DISPLAYREG(reg)) { \ | ||
| 1119 | val = read##y(dev_priv->regs + reg + 0x180000); \ | ||
| 1164 | } else { \ | 1120 | } else { \ |
| 1165 | val = read##y(dev_priv->regs + reg); \ | 1121 | val = read##y(dev_priv->regs + reg); \ |
| 1166 | } \ | 1122 | } \ |
| @@ -1181,7 +1137,11 @@ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \ | |||
| 1181 | if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ | 1137 | if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ |
| 1182 | __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ | 1138 | __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ |
| 1183 | } \ | 1139 | } \ |
| 1184 | write##y(val, dev_priv->regs + reg); \ | 1140 | if (IS_VALLEYVIEW(dev_priv->dev) && IS_DISPLAYREG(reg)) { \ |
| 1141 | write##y(val, dev_priv->regs + reg + 0x180000); \ | ||
| 1142 | } else { \ | ||
| 1143 | write##y(val, dev_priv->regs + reg); \ | ||
| 1144 | } \ | ||
| 1185 | if (unlikely(__fifo_ret)) { \ | 1145 | if (unlikely(__fifo_ret)) { \ |
| 1186 | gen6_gt_check_fifodbg(dev_priv); \ | 1146 | gen6_gt_check_fifodbg(dev_priv); \ |
| 1187 | } \ | 1147 | } \ |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b0b676abde0d..476c64c4844c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -79,6 +79,10 @@ enum port { | |||
| 79 | 79 | ||
| 80 | #define for_each_pipe(p) for ((p) = 0; (p) < dev_priv->num_pipe; (p)++) | 80 | #define for_each_pipe(p) for ((p) = 0; (p) < dev_priv->num_pipe; (p)++) |
| 81 | 81 | ||
| 82 | #define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \ | ||
| 83 | list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \ | ||
| 84 | if ((intel_encoder)->base.crtc == (__crtc)) | ||
| 85 | |||
| 82 | struct intel_pch_pll { | 86 | struct intel_pch_pll { |
| 83 | int refcount; /* count of number of CRTCs sharing this PLL */ | 87 | int refcount; /* count of number of CRTCs sharing this PLL */ |
| 84 | int active; /* count of number of active CRTCs (i.e. DPMS on) */ | 88 | int active; /* count of number of active CRTCs (i.e. DPMS on) */ |
| @@ -176,6 +180,7 @@ struct drm_i915_error_state { | |||
| 176 | u32 eir; | 180 | u32 eir; |
| 177 | u32 pgtbl_er; | 181 | u32 pgtbl_er; |
| 178 | u32 ier; | 182 | u32 ier; |
| 183 | u32 ccid; | ||
| 179 | bool waiting[I915_NUM_RINGS]; | 184 | bool waiting[I915_NUM_RINGS]; |
| 180 | u32 pipestat[I915_MAX_PIPES]; | 185 | u32 pipestat[I915_MAX_PIPES]; |
| 181 | u32 tail[I915_NUM_RINGS]; | 186 | u32 tail[I915_NUM_RINGS]; |
| @@ -261,8 +266,6 @@ struct drm_i915_display_funcs { | |||
| 261 | struct drm_i915_gem_object *obj); | 266 | struct drm_i915_gem_object *obj); |
| 262 | int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb, | 267 | int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb, |
| 263 | int x, int y); | 268 | int x, int y); |
| 264 | void (*force_wake_get)(struct drm_i915_private *dev_priv); | ||
| 265 | void (*force_wake_put)(struct drm_i915_private *dev_priv); | ||
| 266 | /* clock updates for mode set */ | 269 | /* clock updates for mode set */ |
| 267 | /* cursor updates */ | 270 | /* cursor updates */ |
| 268 | /* render clock increase/decrease */ | 271 | /* render clock increase/decrease */ |
| @@ -270,6 +273,11 @@ struct drm_i915_display_funcs { | |||
| 270 | /* pll clock increase/decrease */ | 273 | /* pll clock increase/decrease */ |
| 271 | }; | 274 | }; |
| 272 | 275 | ||
| 276 | struct drm_i915_gt_funcs { | ||
| 277 | void (*force_wake_get)(struct drm_i915_private *dev_priv); | ||
| 278 | void (*force_wake_put)(struct drm_i915_private *dev_priv); | ||
| 279 | }; | ||
| 280 | |||
| 273 | struct intel_device_info { | 281 | struct intel_device_info { |
| 274 | u8 gen; | 282 | u8 gen; |
| 275 | u8 is_mobile:1; | 283 | u8 is_mobile:1; |
| @@ -284,7 +292,6 @@ struct intel_device_info { | |||
| 284 | u8 is_crestline:1; | 292 | u8 is_crestline:1; |
| 285 | u8 is_ivybridge:1; | 293 | u8 is_ivybridge:1; |
| 286 | u8 is_valleyview:1; | 294 | u8 is_valleyview:1; |
| 287 | u8 has_pch_split:1; | ||
| 288 | u8 has_force_wake:1; | 295 | u8 has_force_wake:1; |
| 289 | u8 is_haswell:1; | 296 | u8 is_haswell:1; |
| 290 | u8 has_fbc:1; | 297 | u8 has_fbc:1; |
| @@ -309,6 +316,17 @@ struct i915_hw_ppgtt { | |||
| 309 | dma_addr_t scratch_page_dma_addr; | 316 | dma_addr_t scratch_page_dma_addr; |
| 310 | }; | 317 | }; |
| 311 | 318 | ||
| 319 | |||
| 320 | /* This must match up with the value previously used for execbuf2.rsvd1. */ | ||
| 321 | #define DEFAULT_CONTEXT_ID 0 | ||
| 322 | struct i915_hw_context { | ||
| 323 | int id; | ||
| 324 | bool is_initialized; | ||
| 325 | struct drm_i915_file_private *file_priv; | ||
| 326 | struct intel_ring_buffer *ring; | ||
| 327 | struct drm_i915_gem_object *obj; | ||
| 328 | }; | ||
| 329 | |||
| 312 | enum no_fbc_reason { | 330 | enum no_fbc_reason { |
| 313 | FBC_NO_OUTPUT, /* no outputs enabled to compress */ | 331 | FBC_NO_OUTPUT, /* no outputs enabled to compress */ |
| 314 | FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */ | 332 | FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */ |
| @@ -321,6 +339,7 @@ enum no_fbc_reason { | |||
| 321 | }; | 339 | }; |
| 322 | 340 | ||
| 323 | enum intel_pch { | 341 | enum intel_pch { |
| 342 | PCH_NONE = 0, /* No PCH present */ | ||
| 324 | PCH_IBX, /* Ibexpeak PCH */ | 343 | PCH_IBX, /* Ibexpeak PCH */ |
| 325 | PCH_CPT, /* Cougarpoint PCH */ | 344 | PCH_CPT, /* Cougarpoint PCH */ |
| 326 | PCH_LPT, /* Lynxpoint PCH */ | 345 | PCH_LPT, /* Lynxpoint PCH */ |
| @@ -350,6 +369,8 @@ typedef struct drm_i915_private { | |||
| 350 | int relative_constants_mode; | 369 | int relative_constants_mode; |
| 351 | 370 | ||
| 352 | void __iomem *regs; | 371 | void __iomem *regs; |
| 372 | |||
| 373 | struct drm_i915_gt_funcs gt; | ||
| 353 | /** gt_fifo_count and the subsequent register write are synchronized | 374 | /** gt_fifo_count and the subsequent register write are synchronized |
| 354 | * with dev->struct_mutex. */ | 375 | * with dev->struct_mutex. */ |
| 355 | unsigned gt_fifo_count; | 376 | unsigned gt_fifo_count; |
| @@ -652,11 +673,14 @@ typedef struct drm_i915_private { | |||
| 652 | unsigned long gtt_end; | 673 | unsigned long gtt_end; |
| 653 | 674 | ||
| 654 | struct io_mapping *gtt_mapping; | 675 | struct io_mapping *gtt_mapping; |
| 676 | phys_addr_t gtt_base_addr; | ||
| 655 | int gtt_mtrr; | 677 | int gtt_mtrr; |
| 656 | 678 | ||
| 657 | /** PPGTT used for aliasing the PPGTT with the GTT */ | 679 | /** PPGTT used for aliasing the PPGTT with the GTT */ |
| 658 | struct i915_hw_ppgtt *aliasing_ppgtt; | 680 | struct i915_hw_ppgtt *aliasing_ppgtt; |
| 659 | 681 | ||
| 682 | u32 *l3_remap_info; | ||
| 683 | |||
| 660 | struct shrinker inactive_shrinker; | 684 | struct shrinker inactive_shrinker; |
| 661 | 685 | ||
| 662 | /** | 686 | /** |
| @@ -817,6 +841,10 @@ typedef struct drm_i915_private { | |||
| 817 | 841 | ||
| 818 | struct drm_property *broadcast_rgb_property; | 842 | struct drm_property *broadcast_rgb_property; |
| 819 | struct drm_property *force_audio_property; | 843 | struct drm_property *force_audio_property; |
| 844 | |||
| 845 | struct work_struct parity_error_work; | ||
| 846 | bool hw_contexts_disabled; | ||
| 847 | uint32_t hw_context_size; | ||
| 820 | } drm_i915_private_t; | 848 | } drm_i915_private_t; |
| 821 | 849 | ||
| 822 | /* Iterate over initialised rings */ | 850 | /* Iterate over initialised rings */ |
| @@ -1026,6 +1054,7 @@ struct drm_i915_file_private { | |||
| 1026 | struct spinlock lock; | 1054 | struct spinlock lock; |
| 1027 | struct list_head request_list; | 1055 | struct list_head request_list; |
| 1028 | } mm; | 1056 | } mm; |
| 1057 | struct idr context_idr; | ||
| 1029 | }; | 1058 | }; |
| 1030 | 1059 | ||
| 1031 | #define INTEL_INFO(dev) (((struct drm_i915_private *) (dev)->dev_private)->info) | 1060 | #define INTEL_INFO(dev) (((struct drm_i915_private *) (dev)->dev_private)->info) |
| @@ -1071,7 +1100,8 @@ struct drm_i915_file_private { | |||
| 1071 | #define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc) | 1100 | #define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc) |
| 1072 | #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) | 1101 | #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) |
| 1073 | 1102 | ||
| 1074 | #define HAS_ALIASING_PPGTT(dev) (INTEL_INFO(dev)->gen >=6) | 1103 | #define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 6) |
| 1104 | #define HAS_ALIASING_PPGTT(dev) (INTEL_INFO(dev)->gen >=6 && !IS_VALLEYVIEW(dev)) | ||
| 1075 | 1105 | ||
| 1076 | #define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) | 1106 | #define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) |
| 1077 | #define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) | 1107 | #define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) |
| @@ -1094,13 +1124,13 @@ struct drm_i915_file_private { | |||
| 1094 | #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) | 1124 | #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) |
| 1095 | #define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) | 1125 | #define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) |
| 1096 | 1126 | ||
| 1097 | #define HAS_PCH_SPLIT(dev) (INTEL_INFO(dev)->has_pch_split) | ||
| 1098 | #define HAS_PIPE_CONTROL(dev) (INTEL_INFO(dev)->gen >= 5) | 1127 | #define HAS_PIPE_CONTROL(dev) (INTEL_INFO(dev)->gen >= 5) |
| 1099 | 1128 | ||
| 1100 | #define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type) | 1129 | #define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type) |
| 1101 | #define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT) | 1130 | #define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT) |
| 1102 | #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) | 1131 | #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) |
| 1103 | #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) | 1132 | #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) |
| 1133 | #define HAS_PCH_SPLIT(dev) (INTEL_PCH_TYPE(dev) != PCH_NONE) | ||
| 1104 | 1134 | ||
| 1105 | #define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake) | 1135 | #define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake) |
| 1106 | 1136 | ||
| @@ -1166,6 +1196,7 @@ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, | |||
| 1166 | extern int i915_emit_box(struct drm_device *dev, | 1196 | extern int i915_emit_box(struct drm_device *dev, |
| 1167 | struct drm_clip_rect *box, | 1197 | struct drm_clip_rect *box, |
| 1168 | int DR1, int DR4); | 1198 | int DR1, int DR4); |
| 1199 | extern int intel_gpu_reset(struct drm_device *dev); | ||
| 1169 | extern int i915_reset(struct drm_device *dev); | 1200 | extern int i915_reset(struct drm_device *dev); |
| 1170 | extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv); | 1201 | extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv); |
| 1171 | extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv); | 1202 | extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv); |
| @@ -1178,6 +1209,7 @@ void i915_hangcheck_elapsed(unsigned long data); | |||
| 1178 | void i915_handle_error(struct drm_device *dev, bool wedged); | 1209 | void i915_handle_error(struct drm_device *dev, bool wedged); |
| 1179 | 1210 | ||
| 1180 | extern void intel_irq_init(struct drm_device *dev); | 1211 | extern void intel_irq_init(struct drm_device *dev); |
| 1212 | extern void intel_gt_init(struct drm_device *dev); | ||
| 1181 | 1213 | ||
| 1182 | void i915_error_state_free(struct kref *error_ref); | 1214 | void i915_error_state_free(struct kref *error_ref); |
| 1183 | 1215 | ||
| @@ -1237,6 +1269,8 @@ int i915_gem_get_tiling(struct drm_device *dev, void *data, | |||
| 1237 | struct drm_file *file_priv); | 1269 | struct drm_file *file_priv); |
| 1238 | int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, | 1270 | int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, |
| 1239 | struct drm_file *file_priv); | 1271 | struct drm_file *file_priv); |
| 1272 | int i915_gem_wait_ioctl(struct drm_device *dev, void *data, | ||
| 1273 | struct drm_file *file_priv); | ||
| 1240 | void i915_gem_load(struct drm_device *dev); | 1274 | void i915_gem_load(struct drm_device *dev); |
| 1241 | int i915_gem_init_object(struct drm_gem_object *obj); | 1275 | int i915_gem_init_object(struct drm_gem_object *obj); |
| 1242 | int __must_check i915_gem_flush_ring(struct intel_ring_buffer *ring, | 1276 | int __must_check i915_gem_flush_ring(struct intel_ring_buffer *ring, |
| @@ -1306,6 +1340,8 @@ i915_gem_object_unpin_fence(struct drm_i915_gem_object *obj) | |||
| 1306 | 1340 | ||
| 1307 | void i915_gem_retire_requests(struct drm_device *dev); | 1341 | void i915_gem_retire_requests(struct drm_device *dev); |
| 1308 | void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring); | 1342 | void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring); |
| 1343 | int __must_check i915_gem_check_wedge(struct drm_i915_private *dev_priv, | ||
| 1344 | bool interruptible); | ||
| 1309 | 1345 | ||
| 1310 | void i915_gem_reset(struct drm_device *dev); | 1346 | void i915_gem_reset(struct drm_device *dev); |
| 1311 | void i915_gem_clflush_object(struct drm_i915_gem_object *obj); | 1347 | void i915_gem_clflush_object(struct drm_i915_gem_object *obj); |
| @@ -1315,6 +1351,7 @@ int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj, | |||
| 1315 | int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj); | 1351 | int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj); |
| 1316 | int __must_check i915_gem_init(struct drm_device *dev); | 1352 | int __must_check i915_gem_init(struct drm_device *dev); |
| 1317 | int __must_check i915_gem_init_hw(struct drm_device *dev); | 1353 | int __must_check i915_gem_init_hw(struct drm_device *dev); |
| 1354 | void i915_gem_l3_remap(struct drm_device *dev); | ||
| 1318 | void i915_gem_init_swizzling(struct drm_device *dev); | 1355 | void i915_gem_init_swizzling(struct drm_device *dev); |
| 1319 | void i915_gem_init_ppgtt(struct drm_device *dev); | 1356 | void i915_gem_init_ppgtt(struct drm_device *dev); |
| 1320 | void i915_gem_cleanup_ringbuffer(struct drm_device *dev); | 1357 | void i915_gem_cleanup_ringbuffer(struct drm_device *dev); |
| @@ -1323,8 +1360,8 @@ int __must_check i915_gem_idle(struct drm_device *dev); | |||
| 1323 | int __must_check i915_add_request(struct intel_ring_buffer *ring, | 1360 | int __must_check i915_add_request(struct intel_ring_buffer *ring, |
| 1324 | struct drm_file *file, | 1361 | struct drm_file *file, |
| 1325 | struct drm_i915_gem_request *request); | 1362 | struct drm_i915_gem_request *request); |
| 1326 | int __must_check i915_wait_request(struct intel_ring_buffer *ring, | 1363 | int __must_check i915_wait_seqno(struct intel_ring_buffer *ring, |
| 1327 | uint32_t seqno); | 1364 | uint32_t seqno); |
| 1328 | int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); | 1365 | int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); |
| 1329 | int __must_check | 1366 | int __must_check |
| 1330 | i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, | 1367 | i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, |
| @@ -1358,6 +1395,16 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, | |||
| 1358 | struct dma_buf *i915_gem_prime_export(struct drm_device *dev, | 1395 | struct dma_buf *i915_gem_prime_export(struct drm_device *dev, |
| 1359 | struct drm_gem_object *gem_obj, int flags); | 1396 | struct drm_gem_object *gem_obj, int flags); |
| 1360 | 1397 | ||
| 1398 | /* i915_gem_context.c */ | ||
| 1399 | void i915_gem_context_init(struct drm_device *dev); | ||
| 1400 | void i915_gem_context_fini(struct drm_device *dev); | ||
| 1401 | void i915_gem_context_close(struct drm_device *dev, struct drm_file *file); | ||
| 1402 | int i915_switch_context(struct intel_ring_buffer *ring, | ||
| 1403 | struct drm_file *file, int to_id); | ||
| 1404 | int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, | ||
| 1405 | struct drm_file *file); | ||
| 1406 | int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, | ||
| 1407 | struct drm_file *file); | ||
| 1361 | 1408 | ||
| 1362 | /* i915_gem_gtt.c */ | 1409 | /* i915_gem_gtt.c */ |
| 1363 | int __must_check i915_gem_init_aliasing_ppgtt(struct drm_device *dev); | 1410 | int __must_check i915_gem_init_aliasing_ppgtt(struct drm_device *dev); |
| @@ -1475,20 +1522,12 @@ extern bool intel_fbc_enabled(struct drm_device *dev); | |||
| 1475 | extern void intel_disable_fbc(struct drm_device *dev); | 1522 | extern void intel_disable_fbc(struct drm_device *dev); |
| 1476 | extern bool ironlake_set_drps(struct drm_device *dev, u8 val); | 1523 | extern bool ironlake_set_drps(struct drm_device *dev, u8 val); |
| 1477 | extern void ironlake_init_pch_refclk(struct drm_device *dev); | 1524 | extern void ironlake_init_pch_refclk(struct drm_device *dev); |
| 1478 | extern void ironlake_enable_rc6(struct drm_device *dev); | ||
| 1479 | extern void gen6_set_rps(struct drm_device *dev, u8 val); | 1525 | extern void gen6_set_rps(struct drm_device *dev, u8 val); |
| 1480 | extern void intel_detect_pch(struct drm_device *dev); | 1526 | extern void intel_detect_pch(struct drm_device *dev); |
| 1481 | extern int intel_trans_dp_port_sel(struct drm_crtc *crtc); | 1527 | extern int intel_trans_dp_port_sel(struct drm_crtc *crtc); |
| 1482 | extern int intel_enable_rc6(const struct drm_device *dev); | 1528 | extern int intel_enable_rc6(const struct drm_device *dev); |
| 1483 | 1529 | ||
| 1484 | extern bool i915_semaphore_is_enabled(struct drm_device *dev); | 1530 | extern bool i915_semaphore_is_enabled(struct drm_device *dev); |
| 1485 | extern void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv); | ||
| 1486 | extern void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv); | ||
| 1487 | extern void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv); | ||
| 1488 | extern void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv); | ||
| 1489 | |||
| 1490 | extern void vlv_force_wake_get(struct drm_i915_private *dev_priv); | ||
| 1491 | extern void vlv_force_wake_put(struct drm_i915_private *dev_priv); | ||
| 1492 | 1531 | ||
| 1493 | /* overlay */ | 1532 | /* overlay */ |
| 1494 | #ifdef CONFIG_DEBUG_FS | 1533 | #ifdef CONFIG_DEBUG_FS |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 288d7b8f49ae..0fdb3d29cbbb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -96,9 +96,18 @@ i915_gem_wait_for_error(struct drm_device *dev) | |||
| 96 | if (!atomic_read(&dev_priv->mm.wedged)) | 96 | if (!atomic_read(&dev_priv->mm.wedged)) |
| 97 | return 0; | 97 | return 0; |
| 98 | 98 | ||
| 99 | ret = wait_for_completion_interruptible(x); | 99 | /* |
| 100 | if (ret) | 100 | * Only wait 10 seconds for the gpu reset to complete to avoid hanging |
| 101 | * userspace. If it takes that long something really bad is going on and | ||
| 102 | * we should simply try to bail out and fail as gracefully as possible. | ||
| 103 | */ | ||
| 104 | ret = wait_for_completion_interruptible_timeout(x, 10*HZ); | ||
| 105 | if (ret == 0) { | ||
| 106 | DRM_ERROR("Timed out waiting for the gpu reset to complete\n"); | ||
| 107 | return -EIO; | ||
| 108 | } else if (ret < 0) { | ||
| 101 | return ret; | 109 | return ret; |
| 110 | } | ||
| 102 | 111 | ||
| 103 | if (atomic_read(&dev_priv->mm.wedged)) { | 112 | if (atomic_read(&dev_priv->mm.wedged)) { |
| 104 | /* GPU is hung, bump the completion count to account for | 113 | /* GPU is hung, bump the completion count to account for |
| @@ -1122,7 +1131,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 1122 | 1131 | ||
| 1123 | obj->fault_mappable = true; | 1132 | obj->fault_mappable = true; |
| 1124 | 1133 | ||
| 1125 | pfn = ((dev->agp->base + obj->gtt_offset) >> PAGE_SHIFT) + | 1134 | pfn = ((dev_priv->mm.gtt_base_addr + obj->gtt_offset) >> PAGE_SHIFT) + |
| 1126 | page_offset; | 1135 | page_offset; |
| 1127 | 1136 | ||
| 1128 | /* Finally, remap it using the new GTT offset */ | 1137 | /* Finally, remap it using the new GTT offset */ |
| @@ -1132,6 +1141,11 @@ unlock: | |||
| 1132 | out: | 1141 | out: |
| 1133 | switch (ret) { | 1142 | switch (ret) { |
| 1134 | case -EIO: | 1143 | case -EIO: |
| 1144 | /* If this -EIO is due to a gpu hang, give the reset code a | ||
| 1145 | * chance to clean up the mess. Otherwise return the proper | ||
| 1146 | * SIGBUS. */ | ||
| 1147 | if (!atomic_read(&dev_priv->mm.wedged)) | ||
| 1148 | return VM_FAULT_SIGBUS; | ||
| 1135 | case -EAGAIN: | 1149 | case -EAGAIN: |
| 1136 | /* Give the error handler a chance to run and move the | 1150 | /* Give the error handler a chance to run and move the |
| 1137 | * objects off the GPU active list. Next time we service the | 1151 | * objects off the GPU active list. Next time we service the |
| @@ -1568,6 +1582,21 @@ i915_add_request(struct intel_ring_buffer *ring, | |||
| 1568 | int was_empty; | 1582 | int was_empty; |
| 1569 | int ret; | 1583 | int ret; |
| 1570 | 1584 | ||
| 1585 | /* | ||
| 1586 | * Emit any outstanding flushes - execbuf can fail to emit the flush | ||
| 1587 | * after having emitted the batchbuffer command. Hence we need to fix | ||
| 1588 | * things up similar to emitting the lazy request. The difference here | ||
| 1589 | * is that the flush _must_ happen before the next request, no matter | ||
| 1590 | * what. | ||
| 1591 | */ | ||
| 1592 | if (ring->gpu_caches_dirty) { | ||
| 1593 | ret = i915_gem_flush_ring(ring, 0, I915_GEM_GPU_DOMAINS); | ||
| 1594 | if (ret) | ||
| 1595 | return ret; | ||
| 1596 | |||
| 1597 | ring->gpu_caches_dirty = false; | ||
| 1598 | } | ||
| 1599 | |||
| 1571 | BUG_ON(request == NULL); | 1600 | BUG_ON(request == NULL); |
| 1572 | seqno = i915_gem_next_request_seqno(ring); | 1601 | seqno = i915_gem_next_request_seqno(ring); |
| 1573 | 1602 | ||
| @@ -1613,6 +1642,9 @@ i915_add_request(struct intel_ring_buffer *ring, | |||
| 1613 | queue_delayed_work(dev_priv->wq, | 1642 | queue_delayed_work(dev_priv->wq, |
| 1614 | &dev_priv->mm.retire_work, HZ); | 1643 | &dev_priv->mm.retire_work, HZ); |
| 1615 | } | 1644 | } |
| 1645 | |||
| 1646 | WARN_ON(!list_empty(&ring->gpu_write_list)); | ||
| 1647 | |||
| 1616 | return 0; | 1648 | return 0; |
| 1617 | } | 1649 | } |
| 1618 | 1650 | ||
| @@ -1827,14 +1859,11 @@ i915_gem_retire_work_handler(struct work_struct *work) | |||
| 1827 | */ | 1859 | */ |
| 1828 | idle = true; | 1860 | idle = true; |
| 1829 | for_each_ring(ring, dev_priv, i) { | 1861 | for_each_ring(ring, dev_priv, i) { |
| 1830 | if (!list_empty(&ring->gpu_write_list)) { | 1862 | if (ring->gpu_caches_dirty) { |
| 1831 | struct drm_i915_gem_request *request; | 1863 | struct drm_i915_gem_request *request; |
| 1832 | int ret; | ||
| 1833 | 1864 | ||
| 1834 | ret = i915_gem_flush_ring(ring, | ||
| 1835 | 0, I915_GEM_GPU_DOMAINS); | ||
| 1836 | request = kzalloc(sizeof(*request), GFP_KERNEL); | 1865 | request = kzalloc(sizeof(*request), GFP_KERNEL); |
| 1837 | if (ret || request == NULL || | 1866 | if (request == NULL || |
| 1838 | i915_add_request(ring, NULL, request)) | 1867 | i915_add_request(ring, NULL, request)) |
| 1839 | kfree(request); | 1868 | kfree(request); |
| 1840 | } | 1869 | } |
| @@ -1848,11 +1877,10 @@ i915_gem_retire_work_handler(struct work_struct *work) | |||
| 1848 | mutex_unlock(&dev->struct_mutex); | 1877 | mutex_unlock(&dev->struct_mutex); |
| 1849 | } | 1878 | } |
| 1850 | 1879 | ||
| 1851 | static int | 1880 | int |
| 1852 | i915_gem_check_wedge(struct drm_i915_private *dev_priv) | 1881 | i915_gem_check_wedge(struct drm_i915_private *dev_priv, |
| 1882 | bool interruptible) | ||
| 1853 | { | 1883 | { |
| 1854 | BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); | ||
| 1855 | |||
| 1856 | if (atomic_read(&dev_priv->mm.wedged)) { | 1884 | if (atomic_read(&dev_priv->mm.wedged)) { |
| 1857 | struct completion *x = &dev_priv->error_completion; | 1885 | struct completion *x = &dev_priv->error_completion; |
| 1858 | bool recovery_complete; | 1886 | bool recovery_complete; |
| @@ -1863,7 +1891,16 @@ i915_gem_check_wedge(struct drm_i915_private *dev_priv) | |||
| 1863 | recovery_complete = x->done > 0; | 1891 | recovery_complete = x->done > 0; |
| 1864 | spin_unlock_irqrestore(&x->wait.lock, flags); | 1892 | spin_unlock_irqrestore(&x->wait.lock, flags); |
| 1865 | 1893 | ||
| 1866 | return recovery_complete ? -EIO : -EAGAIN; | 1894 | /* Non-interruptible callers can't handle -EAGAIN, hence return |
| 1895 | * -EIO unconditionally for these. */ | ||
| 1896 | if (!interruptible) | ||
| 1897 | return -EIO; | ||
| 1898 | |||
| 1899 | /* Recovery complete, but still wedged means reset failure. */ | ||
| 1900 | if (recovery_complete) | ||
| 1901 | return -EIO; | ||
| 1902 | |||
| 1903 | return -EAGAIN; | ||
| 1867 | } | 1904 | } |
| 1868 | 1905 | ||
| 1869 | return 0; | 1906 | return 0; |
| @@ -1899,34 +1936,84 @@ i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno) | |||
| 1899 | return ret; | 1936 | return ret; |
| 1900 | } | 1937 | } |
| 1901 | 1938 | ||
| 1939 | /** | ||
| 1940 | * __wait_seqno - wait until execution of seqno has finished | ||
| 1941 | * @ring: the ring expected to report seqno | ||
| 1942 | * @seqno: duh! | ||
| 1943 | * @interruptible: do an interruptible wait (normally yes) | ||
| 1944 | * @timeout: in - how long to wait (NULL forever); out - how much time remaining | ||
| 1945 | * | ||
| 1946 | * Returns 0 if the seqno was found within the alloted time. Else returns the | ||
| 1947 | * errno with remaining time filled in timeout argument. | ||
| 1948 | */ | ||
| 1902 | static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, | 1949 | static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, |
| 1903 | bool interruptible) | 1950 | bool interruptible, struct timespec *timeout) |
| 1904 | { | 1951 | { |
| 1905 | drm_i915_private_t *dev_priv = ring->dev->dev_private; | 1952 | drm_i915_private_t *dev_priv = ring->dev->dev_private; |
| 1906 | int ret = 0; | 1953 | struct timespec before, now, wait_time={1,0}; |
| 1954 | unsigned long timeout_jiffies; | ||
| 1955 | long end; | ||
| 1956 | bool wait_forever = true; | ||
| 1957 | int ret; | ||
| 1907 | 1958 | ||
| 1908 | if (i915_seqno_passed(ring->get_seqno(ring), seqno)) | 1959 | if (i915_seqno_passed(ring->get_seqno(ring), seqno)) |
| 1909 | return 0; | 1960 | return 0; |
| 1910 | 1961 | ||
| 1911 | trace_i915_gem_request_wait_begin(ring, seqno); | 1962 | trace_i915_gem_request_wait_begin(ring, seqno); |
| 1963 | |||
| 1964 | if (timeout != NULL) { | ||
| 1965 | wait_time = *timeout; | ||
| 1966 | wait_forever = false; | ||
| 1967 | } | ||
| 1968 | |||
| 1969 | timeout_jiffies = timespec_to_jiffies(&wait_time); | ||
| 1970 | |||
| 1912 | if (WARN_ON(!ring->irq_get(ring))) | 1971 | if (WARN_ON(!ring->irq_get(ring))) |
| 1913 | return -ENODEV; | 1972 | return -ENODEV; |
| 1914 | 1973 | ||
| 1974 | /* Record current time in case interrupted by signal, or wedged * */ | ||
| 1975 | getrawmonotonic(&before); | ||
| 1976 | |||
| 1915 | #define EXIT_COND \ | 1977 | #define EXIT_COND \ |
| 1916 | (i915_seqno_passed(ring->get_seqno(ring), seqno) || \ | 1978 | (i915_seqno_passed(ring->get_seqno(ring), seqno) || \ |
| 1917 | atomic_read(&dev_priv->mm.wedged)) | 1979 | atomic_read(&dev_priv->mm.wedged)) |
| 1980 | do { | ||
| 1981 | if (interruptible) | ||
| 1982 | end = wait_event_interruptible_timeout(ring->irq_queue, | ||
| 1983 | EXIT_COND, | ||
| 1984 | timeout_jiffies); | ||
| 1985 | else | ||
| 1986 | end = wait_event_timeout(ring->irq_queue, EXIT_COND, | ||
| 1987 | timeout_jiffies); | ||
| 1918 | 1988 | ||
| 1919 | if (interruptible) | 1989 | ret = i915_gem_check_wedge(dev_priv, interruptible); |
| 1920 | ret = wait_event_interruptible(ring->irq_queue, | 1990 | if (ret) |
| 1921 | EXIT_COND); | 1991 | end = ret; |
| 1922 | else | 1992 | } while (end == 0 && wait_forever); |
| 1923 | wait_event(ring->irq_queue, EXIT_COND); | 1993 | |
| 1994 | getrawmonotonic(&now); | ||
| 1924 | 1995 | ||
| 1925 | ring->irq_put(ring); | 1996 | ring->irq_put(ring); |
| 1926 | trace_i915_gem_request_wait_end(ring, seqno); | 1997 | trace_i915_gem_request_wait_end(ring, seqno); |
| 1927 | #undef EXIT_COND | 1998 | #undef EXIT_COND |
| 1928 | 1999 | ||
| 1929 | return ret; | 2000 | if (timeout) { |
| 2001 | struct timespec sleep_time = timespec_sub(now, before); | ||
| 2002 | *timeout = timespec_sub(*timeout, sleep_time); | ||
| 2003 | } | ||
| 2004 | |||
| 2005 | switch (end) { | ||
| 2006 | case -EAGAIN: /* Wedged */ | ||
| 2007 | case -ERESTARTSYS: /* Signal */ | ||
| 2008 | return (int)end; | ||
| 2009 | case 0: /* Timeout */ | ||
| 2010 | if (timeout) | ||
| 2011 | set_normalized_timespec(timeout, 0, 0); | ||
| 2012 | return -ETIME; | ||
| 2013 | default: /* Completed */ | ||
| 2014 | WARN_ON(end < 0); /* We're not aware of other errors */ | ||
| 2015 | return 0; | ||
| 2016 | } | ||
| 1930 | } | 2017 | } |
| 1931 | 2018 | ||
| 1932 | /** | 2019 | /** |
| @@ -1934,15 +2021,14 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, | |||
| 1934 | * request and object lists appropriately for that event. | 2021 | * request and object lists appropriately for that event. |
| 1935 | */ | 2022 | */ |
| 1936 | int | 2023 | int |
| 1937 | i915_wait_request(struct intel_ring_buffer *ring, | 2024 | i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno) |
| 1938 | uint32_t seqno) | ||
| 1939 | { | 2025 | { |
| 1940 | drm_i915_private_t *dev_priv = ring->dev->dev_private; | 2026 | drm_i915_private_t *dev_priv = ring->dev->dev_private; |
| 1941 | int ret = 0; | 2027 | int ret = 0; |
| 1942 | 2028 | ||
| 1943 | BUG_ON(seqno == 0); | 2029 | BUG_ON(seqno == 0); |
| 1944 | 2030 | ||
| 1945 | ret = i915_gem_check_wedge(dev_priv); | 2031 | ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); |
| 1946 | if (ret) | 2032 | if (ret) |
| 1947 | return ret; | 2033 | return ret; |
| 1948 | 2034 | ||
| @@ -1950,9 +2036,7 @@ i915_wait_request(struct intel_ring_buffer *ring, | |||
| 1950 | if (ret) | 2036 | if (ret) |
| 1951 | return ret; | 2037 | return ret; |
| 1952 | 2038 | ||
| 1953 | ret = __wait_seqno(ring, seqno, dev_priv->mm.interruptible); | 2039 | ret = __wait_seqno(ring, seqno, dev_priv->mm.interruptible, NULL); |
| 1954 | if (atomic_read(&dev_priv->mm.wedged)) | ||
| 1955 | ret = -EAGAIN; | ||
| 1956 | 2040 | ||
| 1957 | return ret; | 2041 | return ret; |
| 1958 | } | 2042 | } |
| @@ -1975,7 +2059,32 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj) | |||
| 1975 | * it. | 2059 | * it. |
| 1976 | */ | 2060 | */ |
| 1977 | if (obj->active) { | 2061 | if (obj->active) { |
| 1978 | ret = i915_wait_request(obj->ring, obj->last_rendering_seqno); | 2062 | ret = i915_wait_seqno(obj->ring, obj->last_rendering_seqno); |
| 2063 | if (ret) | ||
| 2064 | return ret; | ||
| 2065 | i915_gem_retire_requests_ring(obj->ring); | ||
| 2066 | } | ||
| 2067 | |||
| 2068 | return 0; | ||
| 2069 | } | ||
| 2070 | |||
| 2071 | /** | ||
| 2072 | * Ensures that an object will eventually get non-busy by flushing any required | ||
| 2073 | * write domains, emitting any outstanding lazy request and retiring and | ||
| 2074 | * completed requests. | ||
| 2075 | */ | ||
| 2076 | static int | ||
| 2077 | i915_gem_object_flush_active(struct drm_i915_gem_object *obj) | ||
| 2078 | { | ||
| 2079 | int ret; | ||
| 2080 | |||
| 2081 | if (obj->active) { | ||
| 2082 | ret = i915_gem_object_flush_gpu_write_domain(obj); | ||
| 2083 | if (ret) | ||
| 2084 | return ret; | ||
| 2085 | |||
| 2086 | ret = i915_gem_check_olr(obj->ring, | ||
| 2087 | obj->last_rendering_seqno); | ||
| 1979 | if (ret) | 2088 | if (ret) |
| 1980 | return ret; | 2089 | return ret; |
| 1981 | i915_gem_retire_requests_ring(obj->ring); | 2090 | i915_gem_retire_requests_ring(obj->ring); |
| @@ -1985,6 +2094,90 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj) | |||
| 1985 | } | 2094 | } |
| 1986 | 2095 | ||
| 1987 | /** | 2096 | /** |
| 2097 | * i915_gem_wait_ioctl - implements DRM_IOCTL_I915_GEM_WAIT | ||
| 2098 | * @DRM_IOCTL_ARGS: standard ioctl arguments | ||
| 2099 | * | ||
| 2100 | * Returns 0 if successful, else an error is returned with the remaining time in | ||
| 2101 | * the timeout parameter. | ||
| 2102 | * -ETIME: object is still busy after timeout | ||
| 2103 | * -ERESTARTSYS: signal interrupted the wait | ||
| 2104 | * -ENONENT: object doesn't exist | ||
| 2105 | * Also possible, but rare: | ||
| 2106 | * -EAGAIN: GPU wedged | ||
| 2107 | * -ENOMEM: damn | ||
| 2108 | * -ENODEV: Internal IRQ fail | ||
| 2109 | * -E?: The add request failed | ||
| 2110 | * | ||
| 2111 | * The wait ioctl with a timeout of 0 reimplements the busy ioctl. With any | ||
| 2112 | * non-zero timeout parameter the wait ioctl will wait for the given number of | ||
| 2113 | * nanoseconds on an object becoming unbusy. Since the wait itself does so | ||
| 2114 | * without holding struct_mutex the object may become re-busied before this | ||
| 2115 | * function completes. A similar but shorter * race condition exists in the busy | ||
| 2116 | * ioctl | ||
| 2117 | */ | ||
| 2118 | int | ||
| 2119 | i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) | ||
| 2120 | { | ||
| 2121 | struct drm_i915_gem_wait *args = data; | ||
| 2122 | struct drm_i915_gem_object *obj; | ||
| 2123 | struct intel_ring_buffer *ring = NULL; | ||
| 2124 | struct timespec timeout_stack, *timeout = NULL; | ||
| 2125 | u32 seqno = 0; | ||
| 2126 | int ret = 0; | ||
| 2127 | |||
| 2128 | if (args->timeout_ns >= 0) { | ||
| 2129 | timeout_stack = ns_to_timespec(args->timeout_ns); | ||
| 2130 | timeout = &timeout_stack; | ||
| 2131 | } | ||
| 2132 | |||
| 2133 | ret = i915_mutex_lock_interruptible(dev); | ||
| 2134 | if (ret) | ||
| 2135 | return ret; | ||
| 2136 | |||
| 2137 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->bo_handle)); | ||
| 2138 | if (&obj->base == NULL) { | ||
| 2139 | mutex_unlock(&dev->struct_mutex); | ||
| 2140 | return -ENOENT; | ||
| 2141 | } | ||
| 2142 | |||
| 2143 | /* Need to make sure the object gets inactive eventually. */ | ||
| 2144 | ret = i915_gem_object_flush_active(obj); | ||
| 2145 | if (ret) | ||
| 2146 | goto out; | ||
| 2147 | |||
| 2148 | if (obj->active) { | ||
| 2149 | seqno = obj->last_rendering_seqno; | ||
| 2150 | ring = obj->ring; | ||
| 2151 | } | ||
| 2152 | |||
| 2153 | if (seqno == 0) | ||
| 2154 | goto out; | ||
| 2155 | |||
| 2156 | /* Do this after OLR check to make sure we make forward progress polling | ||
| 2157 | * on this IOCTL with a 0 timeout (like busy ioctl) | ||
| 2158 | */ | ||
| 2159 | if (!args->timeout_ns) { | ||
| 2160 | ret = -ETIME; | ||
| 2161 | goto out; | ||
| 2162 | } | ||
| 2163 | |||
| 2164 | drm_gem_object_unreference(&obj->base); | ||
| 2165 | mutex_unlock(&dev->struct_mutex); | ||
| 2166 | |||
| 2167 | ret = __wait_seqno(ring, seqno, true, timeout); | ||
| 2168 | if (timeout) { | ||
| 2169 | WARN_ON(!timespec_valid(timeout)); | ||
| 2170 | args->timeout_ns = timespec_to_ns(timeout); | ||
| 2171 | } | ||
| 2172 | return ret; | ||
| 2173 | |||
| 2174 | out: | ||
| 2175 | drm_gem_object_unreference(&obj->base); | ||
| 2176 | mutex_unlock(&dev->struct_mutex); | ||
| 2177 | return ret; | ||
| 2178 | } | ||
| 2179 | |||
| 2180 | /** | ||
| 1988 | * i915_gem_object_sync - sync an object to a ring. | 2181 | * i915_gem_object_sync - sync an object to a ring. |
| 1989 | * | 2182 | * |
| 1990 | * @obj: object which may be in use on another ring. | 2183 | * @obj: object which may be in use on another ring. |
| @@ -2160,7 +2353,7 @@ static int i915_ring_idle(struct intel_ring_buffer *ring) | |||
| 2160 | return ret; | 2353 | return ret; |
| 2161 | } | 2354 | } |
| 2162 | 2355 | ||
| 2163 | return i915_wait_request(ring, i915_gem_next_request_seqno(ring)); | 2356 | return i915_wait_seqno(ring, i915_gem_next_request_seqno(ring)); |
| 2164 | } | 2357 | } |
| 2165 | 2358 | ||
| 2166 | int i915_gpu_idle(struct drm_device *dev) | 2359 | int i915_gpu_idle(struct drm_device *dev) |
| @@ -2178,6 +2371,10 @@ int i915_gpu_idle(struct drm_device *dev) | |||
| 2178 | /* Is the device fubar? */ | 2371 | /* Is the device fubar? */ |
| 2179 | if (WARN_ON(!list_empty(&ring->gpu_write_list))) | 2372 | if (WARN_ON(!list_empty(&ring->gpu_write_list))) |
| 2180 | return -EBUSY; | 2373 | return -EBUSY; |
| 2374 | |||
| 2375 | ret = i915_switch_context(ring, NULL, DEFAULT_CONTEXT_ID); | ||
| 2376 | if (ret) | ||
| 2377 | return ret; | ||
| 2181 | } | 2378 | } |
| 2182 | 2379 | ||
| 2183 | return 0; | 2380 | return 0; |
| @@ -2364,7 +2561,7 @@ i915_gem_object_flush_fence(struct drm_i915_gem_object *obj) | |||
| 2364 | } | 2561 | } |
| 2365 | 2562 | ||
| 2366 | if (obj->last_fenced_seqno) { | 2563 | if (obj->last_fenced_seqno) { |
| 2367 | ret = i915_wait_request(obj->ring, obj->last_fenced_seqno); | 2564 | ret = i915_wait_seqno(obj->ring, obj->last_fenced_seqno); |
| 2368 | if (ret) | 2565 | if (ret) |
| 2369 | return ret; | 2566 | return ret; |
| 2370 | 2567 | ||
| @@ -2551,8 +2748,8 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, | |||
| 2551 | if (map_and_fenceable) | 2748 | if (map_and_fenceable) |
| 2552 | free_space = | 2749 | free_space = |
| 2553 | drm_mm_search_free_in_range(&dev_priv->mm.gtt_space, | 2750 | drm_mm_search_free_in_range(&dev_priv->mm.gtt_space, |
| 2554 | size, alignment, 0, | 2751 | size, alignment, |
| 2555 | dev_priv->mm.gtt_mappable_end, | 2752 | 0, dev_priv->mm.gtt_mappable_end, |
| 2556 | 0); | 2753 | 0); |
| 2557 | else | 2754 | else |
| 2558 | free_space = drm_mm_search_free(&dev_priv->mm.gtt_space, | 2755 | free_space = drm_mm_search_free(&dev_priv->mm.gtt_space, |
| @@ -2563,7 +2760,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, | |||
| 2563 | obj->gtt_space = | 2760 | obj->gtt_space = |
| 2564 | drm_mm_get_block_range_generic(free_space, | 2761 | drm_mm_get_block_range_generic(free_space, |
| 2565 | size, alignment, 0, | 2762 | size, alignment, 0, |
| 2566 | dev_priv->mm.gtt_mappable_end, | 2763 | 0, dev_priv->mm.gtt_mappable_end, |
| 2567 | 0); | 2764 | 0); |
| 2568 | else | 2765 | else |
| 2569 | obj->gtt_space = | 2766 | obj->gtt_space = |
| @@ -3030,7 +3227,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) | |||
| 3030 | if (seqno == 0) | 3227 | if (seqno == 0) |
| 3031 | return 0; | 3228 | return 0; |
| 3032 | 3229 | ||
| 3033 | ret = __wait_seqno(ring, seqno, true); | 3230 | ret = __wait_seqno(ring, seqno, true, NULL); |
| 3034 | if (ret == 0) | 3231 | if (ret == 0) |
| 3035 | queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); | 3232 | queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); |
| 3036 | 3233 | ||
| @@ -3199,30 +3396,9 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
| 3199 | * become non-busy without any further actions, therefore emit any | 3396 | * become non-busy without any further actions, therefore emit any |
| 3200 | * necessary flushes here. | 3397 | * necessary flushes here. |
| 3201 | */ | 3398 | */ |
| 3202 | args->busy = obj->active; | 3399 | ret = i915_gem_object_flush_active(obj); |
| 3203 | if (args->busy) { | ||
| 3204 | /* Unconditionally flush objects, even when the gpu still uses this | ||
| 3205 | * object. Userspace calling this function indicates that it wants to | ||
| 3206 | * use this buffer rather sooner than later, so issuing the required | ||
| 3207 | * flush earlier is beneficial. | ||
| 3208 | */ | ||
| 3209 | if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { | ||
| 3210 | ret = i915_gem_flush_ring(obj->ring, | ||
| 3211 | 0, obj->base.write_domain); | ||
| 3212 | } else { | ||
| 3213 | ret = i915_gem_check_olr(obj->ring, | ||
| 3214 | obj->last_rendering_seqno); | ||
| 3215 | } | ||
| 3216 | |||
| 3217 | /* Update the active list for the hardware's current position. | ||
| 3218 | * Otherwise this only updates on a delayed timer or when irqs | ||
| 3219 | * are actually unmasked, and our working set ends up being | ||
| 3220 | * larger than required. | ||
| 3221 | */ | ||
| 3222 | i915_gem_retire_requests_ring(obj->ring); | ||
| 3223 | 3400 | ||
| 3224 | args->busy = obj->active; | 3401 | args->busy = obj->active; |
| 3225 | } | ||
| 3226 | 3402 | ||
| 3227 | drm_gem_object_unreference(&obj->base); | 3403 | drm_gem_object_unreference(&obj->base); |
| 3228 | unlock: | 3404 | unlock: |
| @@ -3435,6 +3611,38 @@ i915_gem_idle(struct drm_device *dev) | |||
| 3435 | return 0; | 3611 | return 0; |
| 3436 | } | 3612 | } |
| 3437 | 3613 | ||
| 3614 | void i915_gem_l3_remap(struct drm_device *dev) | ||
| 3615 | { | ||
| 3616 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 3617 | u32 misccpctl; | ||
| 3618 | int i; | ||
| 3619 | |||
| 3620 | if (!IS_IVYBRIDGE(dev)) | ||
| 3621 | return; | ||
| 3622 | |||
| 3623 | if (!dev_priv->mm.l3_remap_info) | ||
| 3624 | return; | ||
| 3625 | |||
| 3626 | misccpctl = I915_READ(GEN7_MISCCPCTL); | ||
| 3627 | I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); | ||
| 3628 | POSTING_READ(GEN7_MISCCPCTL); | ||
| 3629 | |||
| 3630 | for (i = 0; i < GEN7_L3LOG_SIZE; i += 4) { | ||
| 3631 | u32 remap = I915_READ(GEN7_L3LOG_BASE + i); | ||
| 3632 | if (remap && remap != dev_priv->mm.l3_remap_info[i/4]) | ||
| 3633 | DRM_DEBUG("0x%x was already programmed to %x\n", | ||
| 3634 | GEN7_L3LOG_BASE + i, remap); | ||
| 3635 | if (remap && !dev_priv->mm.l3_remap_info[i/4]) | ||
| 3636 | DRM_DEBUG_DRIVER("Clearing remapped register\n"); | ||
| 3637 | I915_WRITE(GEN7_L3LOG_BASE + i, dev_priv->mm.l3_remap_info[i/4]); | ||
| 3638 | } | ||
| 3639 | |||
| 3640 | /* Make sure all the writes land before disabling dop clock gating */ | ||
| 3641 | POSTING_READ(GEN7_L3LOG_BASE); | ||
| 3642 | |||
| 3643 | I915_WRITE(GEN7_MISCCPCTL, misccpctl); | ||
| 3644 | } | ||
| 3645 | |||
| 3438 | void i915_gem_init_swizzling(struct drm_device *dev) | 3646 | void i915_gem_init_swizzling(struct drm_device *dev) |
| 3439 | { | 3647 | { |
| 3440 | drm_i915_private_t *dev_priv = dev->dev_private; | 3648 | drm_i915_private_t *dev_priv = dev->dev_private; |
| @@ -3524,6 +3732,11 @@ i915_gem_init_hw(struct drm_device *dev) | |||
| 3524 | drm_i915_private_t *dev_priv = dev->dev_private; | 3732 | drm_i915_private_t *dev_priv = dev->dev_private; |
| 3525 | int ret; | 3733 | int ret; |
| 3526 | 3734 | ||
| 3735 | if (!intel_enable_gtt()) | ||
| 3736 | return -EIO; | ||
| 3737 | |||
| 3738 | i915_gem_l3_remap(dev); | ||
| 3739 | |||
| 3527 | i915_gem_init_swizzling(dev); | 3740 | i915_gem_init_swizzling(dev); |
| 3528 | 3741 | ||
| 3529 | ret = intel_init_render_ring_buffer(dev); | 3742 | ret = intel_init_render_ring_buffer(dev); |
| @@ -3544,6 +3757,11 @@ i915_gem_init_hw(struct drm_device *dev) | |||
| 3544 | 3757 | ||
| 3545 | dev_priv->next_seqno = 1; | 3758 | dev_priv->next_seqno = 1; |
| 3546 | 3759 | ||
| 3760 | /* | ||
| 3761 | * XXX: There was some w/a described somewhere suggesting loading | ||
| 3762 | * contexts before PPGTT. | ||
| 3763 | */ | ||
| 3764 | i915_gem_context_init(dev); | ||
| 3547 | i915_gem_init_ppgtt(dev); | 3765 | i915_gem_init_ppgtt(dev); |
| 3548 | 3766 | ||
| 3549 | return 0; | 3767 | return 0; |
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c new file mode 100644 index 000000000000..9ae3f2cf414e --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gem_context.c | |||
| @@ -0,0 +1,533 @@ | |||
| 1 | /* | ||
| 2 | * Copyright © 2011-2012 Intel Corporation | ||
| 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 (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| 21 | * IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Ben Widawsky <ben@bwidawsk.net> | ||
| 25 | * | ||
| 26 | */ | ||
| 27 | |||
| 28 | /* | ||
| 29 | * This file implements HW context support. On gen5+ a HW context consists of an | ||
| 30 | * opaque GPU object which is referenced at times of context saves and restores. | ||
| 31 | * With RC6 enabled, the context is also referenced as the GPU enters and exists | ||
| 32 | * from RC6 (GPU has it's own internal power context, except on gen5). Though | ||
| 33 | * something like a context does exist for the media ring, the code only | ||
| 34 | * supports contexts for the render ring. | ||
| 35 | * | ||
| 36 | * In software, there is a distinction between contexts created by the user, | ||
| 37 | * and the default HW context. The default HW context is used by GPU clients | ||
| 38 | * that do not request setup of their own hardware context. The default | ||
| 39 | * context's state is never restored to help prevent programming errors. This | ||
| 40 | * would happen if a client ran and piggy-backed off another clients GPU state. | ||
| 41 | * The default context only exists to give the GPU some offset to load as the | ||
| 42 | * current to invoke a save of the context we actually care about. In fact, the | ||
| 43 | * code could likely be constructed, albeit in a more complicated fashion, to | ||
| 44 | * never use the default context, though that limits the driver's ability to | ||
| 45 | * swap out, and/or destroy other contexts. | ||
| 46 | * | ||
| 47 | * All other contexts are created as a request by the GPU client. These contexts | ||
| 48 | * store GPU state, and thus allow GPU clients to not re-emit state (and | ||
| 49 | * potentially query certain state) at any time. The kernel driver makes | ||
| 50 | * certain that the appropriate commands are inserted. | ||
| 51 | * | ||
| 52 | * The context life cycle is semi-complicated in that context BOs may live | ||
| 53 | * longer than the context itself because of the way the hardware, and object | ||
| 54 | * tracking works. Below is a very crude representation of the state machine | ||
| 55 | * describing the context life. | ||
| 56 | * refcount pincount active | ||
| 57 | * S0: initial state 0 0 0 | ||
| 58 | * S1: context created 1 0 0 | ||
| 59 | * S2: context is currently running 2 1 X | ||
| 60 | * S3: GPU referenced, but not current 2 0 1 | ||
| 61 | * S4: context is current, but destroyed 1 1 0 | ||
| 62 | * S5: like S3, but destroyed 1 0 1 | ||
| 63 | * | ||
| 64 | * The most common (but not all) transitions: | ||
| 65 | * S0->S1: client creates a context | ||
| 66 | * S1->S2: client submits execbuf with context | ||
| 67 | * S2->S3: other clients submits execbuf with context | ||
| 68 | * S3->S1: context object was retired | ||
| 69 | * S3->S2: clients submits another execbuf | ||
| 70 | * S2->S4: context destroy called with current context | ||
| 71 | * S3->S5->S0: destroy path | ||
| 72 | * S4->S5->S0: destroy path on current context | ||
| 73 | * | ||
| 74 | * There are two confusing terms used above: | ||
| 75 | * The "current context" means the context which is currently running on the | ||
| 76 | * GPU. The GPU has loaded it's state already and has stored away the gtt | ||
| 77 | * offset of the BO. The GPU is not actively referencing the data at this | ||
| 78 | * offset, but it will on the next context switch. The only way to avoid this | ||
| 79 | * is to do a GPU reset. | ||
| 80 | * | ||
| 81 | * An "active context' is one which was previously the "current context" and is | ||
| 82 | * on the active list waiting for the next context switch to occur. Until this | ||
| 83 | * happens, the object must remain at the same gtt offset. It is therefore | ||
| 84 | * possible to destroy a context, but it is still active. | ||
| 85 | * | ||
| 86 | */ | ||
| 87 | |||
| 88 | #include "drmP.h" | ||
| 89 | #include "i915_drm.h" | ||
| 90 | #include "i915_drv.h" | ||
| 91 | |||
| 92 | /* This is a HW constraint. The value below is the largest known requirement | ||
| 93 | * I've seen in a spec to date, and that was a workaround for a non-shipping | ||
| 94 | * part. It should be safe to decrease this, but it's more future proof as is. | ||
| 95 | */ | ||
| 96 | #define CONTEXT_ALIGN (64<<10) | ||
| 97 | |||
| 98 | static struct i915_hw_context * | ||
| 99 | i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id); | ||
| 100 | static int do_switch(struct drm_i915_gem_object *from_obj, | ||
| 101 | struct i915_hw_context *to, u32 seqno); | ||
| 102 | |||
| 103 | static int get_context_size(struct drm_device *dev) | ||
| 104 | { | ||
| 105 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 106 | int ret; | ||
| 107 | u32 reg; | ||
| 108 | |||
| 109 | switch (INTEL_INFO(dev)->gen) { | ||
| 110 | case 6: | ||
| 111 | reg = I915_READ(CXT_SIZE); | ||
| 112 | ret = GEN6_CXT_TOTAL_SIZE(reg) * 64; | ||
| 113 | break; | ||
| 114 | case 7: | ||
| 115 | reg = I915_READ(GEN7_CTX_SIZE); | ||
| 116 | ret = GEN7_CTX_TOTAL_SIZE(reg) * 64; | ||
| 117 | break; | ||
| 118 | default: | ||
| 119 | BUG(); | ||
| 120 | } | ||
| 121 | |||
| 122 | return ret; | ||
| 123 | } | ||
| 124 | |||
| 125 | static void do_destroy(struct i915_hw_context *ctx) | ||
| 126 | { | ||
| 127 | struct drm_device *dev = ctx->obj->base.dev; | ||
| 128 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 129 | |||
| 130 | if (ctx->file_priv) | ||
| 131 | idr_remove(&ctx->file_priv->context_idr, ctx->id); | ||
| 132 | else | ||
| 133 | BUG_ON(ctx != dev_priv->ring[RCS].default_context); | ||
| 134 | |||
| 135 | drm_gem_object_unreference(&ctx->obj->base); | ||
| 136 | kfree(ctx); | ||
| 137 | } | ||
| 138 | |||
| 139 | static struct i915_hw_context * | ||
| 140 | create_hw_context(struct drm_device *dev, | ||
| 141 | struct drm_i915_file_private *file_priv) | ||
| 142 | { | ||
| 143 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 144 | struct i915_hw_context *ctx; | ||
| 145 | int ret, id; | ||
| 146 | |||
| 147 | ctx = kzalloc(sizeof(struct drm_i915_file_private), GFP_KERNEL); | ||
| 148 | if (ctx == NULL) | ||
| 149 | return ERR_PTR(-ENOMEM); | ||
| 150 | |||
| 151 | ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size); | ||
| 152 | if (ctx->obj == NULL) { | ||
| 153 | kfree(ctx); | ||
| 154 | DRM_DEBUG_DRIVER("Context object allocated failed\n"); | ||
| 155 | return ERR_PTR(-ENOMEM); | ||
| 156 | } | ||
| 157 | |||
| 158 | /* The ring associated with the context object is handled by the normal | ||
| 159 | * object tracking code. We give an initial ring value simple to pass an | ||
| 160 | * assertion in the context switch code. | ||
| 161 | */ | ||
| 162 | ctx->ring = &dev_priv->ring[RCS]; | ||
| 163 | |||
| 164 | /* Default context will never have a file_priv */ | ||
| 165 | if (file_priv == NULL) | ||
| 166 | return ctx; | ||
| 167 | |||
| 168 | ctx->file_priv = file_priv; | ||
| 169 | |||
| 170 | again: | ||
| 171 | if (idr_pre_get(&file_priv->context_idr, GFP_KERNEL) == 0) { | ||
| 172 | ret = -ENOMEM; | ||
| 173 | DRM_DEBUG_DRIVER("idr allocation failed\n"); | ||
| 174 | goto err_out; | ||
| 175 | } | ||
| 176 | |||
| 177 | ret = idr_get_new_above(&file_priv->context_idr, ctx, | ||
| 178 | DEFAULT_CONTEXT_ID + 1, &id); | ||
| 179 | if (ret == 0) | ||
| 180 | ctx->id = id; | ||
| 181 | |||
| 182 | if (ret == -EAGAIN) | ||
| 183 | goto again; | ||
| 184 | else if (ret) | ||
| 185 | goto err_out; | ||
| 186 | |||
| 187 | return ctx; | ||
| 188 | |||
| 189 | err_out: | ||
| 190 | do_destroy(ctx); | ||
| 191 | return ERR_PTR(ret); | ||
| 192 | } | ||
| 193 | |||
| 194 | static inline bool is_default_context(struct i915_hw_context *ctx) | ||
| 195 | { | ||
| 196 | return (ctx == ctx->ring->default_context); | ||
| 197 | } | ||
| 198 | |||
| 199 | /** | ||
| 200 | * The default context needs to exist per ring that uses contexts. It stores the | ||
| 201 | * context state of the GPU for applications that don't utilize HW contexts, as | ||
| 202 | * well as an idle case. | ||
| 203 | */ | ||
| 204 | static int create_default_context(struct drm_i915_private *dev_priv) | ||
| 205 | { | ||
| 206 | struct i915_hw_context *ctx; | ||
| 207 | int ret; | ||
| 208 | |||
| 209 | BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); | ||
| 210 | |||
| 211 | ctx = create_hw_context(dev_priv->dev, NULL); | ||
| 212 | if (IS_ERR(ctx)) | ||
| 213 | return PTR_ERR(ctx); | ||
| 214 | |||
| 215 | /* We may need to do things with the shrinker which require us to | ||
| 216 | * immediately switch back to the default context. This can cause a | ||
| 217 | * problem as pinning the default context also requires GTT space which | ||
| 218 | * may not be available. To avoid this we always pin the | ||
| 219 | * default context. | ||
| 220 | */ | ||
| 221 | dev_priv->ring[RCS].default_context = ctx; | ||
| 222 | ret = i915_gem_object_pin(ctx->obj, CONTEXT_ALIGN, false); | ||
| 223 | if (ret) { | ||
| 224 | do_destroy(ctx); | ||
| 225 | return ret; | ||
| 226 | } | ||
| 227 | |||
| 228 | ret = do_switch(NULL, ctx, 0); | ||
| 229 | if (ret) { | ||
| 230 | i915_gem_object_unpin(ctx->obj); | ||
| 231 | do_destroy(ctx); | ||
| 232 | } else { | ||
| 233 | DRM_DEBUG_DRIVER("Default HW context loaded\n"); | ||
| 234 | } | ||
| 235 | |||
| 236 | return ret; | ||
| 237 | } | ||
| 238 | |||
| 239 | void i915_gem_context_init(struct drm_device *dev) | ||
| 240 | { | ||
| 241 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 242 | uint32_t ctx_size; | ||
| 243 | |||
| 244 | if (!HAS_HW_CONTEXTS(dev)) { | ||
| 245 | dev_priv->hw_contexts_disabled = true; | ||
| 246 | return; | ||
| 247 | } | ||
| 248 | |||
| 249 | /* If called from reset, or thaw... we've been here already */ | ||
| 250 | if (dev_priv->hw_contexts_disabled || | ||
| 251 | dev_priv->ring[RCS].default_context) | ||
| 252 | return; | ||
| 253 | |||
| 254 | ctx_size = get_context_size(dev); | ||
| 255 | dev_priv->hw_context_size = get_context_size(dev); | ||
| 256 | dev_priv->hw_context_size = round_up(dev_priv->hw_context_size, 4096); | ||
| 257 | |||
| 258 | if (ctx_size <= 0 || ctx_size > (1<<20)) { | ||
| 259 | dev_priv->hw_contexts_disabled = true; | ||
| 260 | return; | ||
| 261 | } | ||
| 262 | |||
| 263 | if (create_default_context(dev_priv)) { | ||
| 264 | dev_priv->hw_contexts_disabled = true; | ||
| 265 | return; | ||
| 266 | } | ||
| 267 | |||
| 268 | DRM_DEBUG_DRIVER("HW context support initialized\n"); | ||
| 269 | } | ||
| 270 | |||
| 271 | void i915_gem_context_fini(struct drm_device *dev) | ||
| 272 | { | ||
| 273 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 274 | |||
| 275 | if (dev_priv->hw_contexts_disabled) | ||
| 276 | return; | ||
| 277 | |||
| 278 | /* The only known way to stop the gpu from accessing the hw context is | ||
| 279 | * to reset it. Do this as the very last operation to avoid confusing | ||
| 280 | * other code, leading to spurious errors. */ | ||
| 281 | intel_gpu_reset(dev); | ||
| 282 | |||
| 283 | i915_gem_object_unpin(dev_priv->ring[RCS].default_context->obj); | ||
| 284 | |||
| 285 | do_destroy(dev_priv->ring[RCS].default_context); | ||
| 286 | } | ||
| 287 | |||
| 288 | static int context_idr_cleanup(int id, void *p, void *data) | ||
| 289 | { | ||
| 290 | struct i915_hw_context *ctx = p; | ||
| 291 | |||
| 292 | BUG_ON(id == DEFAULT_CONTEXT_ID); | ||
| 293 | |||
| 294 | do_destroy(ctx); | ||
| 295 | |||
| 296 | return 0; | ||
| 297 | } | ||
| 298 | |||
| 299 | void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) | ||
| 300 | { | ||
| 301 | struct drm_i915_file_private *file_priv = file->driver_priv; | ||
| 302 | |||
| 303 | mutex_lock(&dev->struct_mutex); | ||
| 304 | idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL); | ||
| 305 | idr_destroy(&file_priv->context_idr); | ||
| 306 | mutex_unlock(&dev->struct_mutex); | ||
| 307 | } | ||
| 308 | |||
| 309 | static struct i915_hw_context * | ||
| 310 | i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id) | ||
| 311 | { | ||
| 312 | return (struct i915_hw_context *)idr_find(&file_priv->context_idr, id); | ||
| 313 | } | ||
| 314 | |||
| 315 | static inline int | ||
| 316 | mi_set_context(struct intel_ring_buffer *ring, | ||
| 317 | struct i915_hw_context *new_context, | ||
| 318 | u32 hw_flags) | ||
| 319 | { | ||
| 320 | int ret; | ||
| 321 | |||
| 322 | /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB | ||
| 323 | * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value | ||
| 324 | * explicitly, so we rely on the value at ring init, stored in | ||
| 325 | * itlb_before_ctx_switch. | ||
| 326 | */ | ||
| 327 | if (IS_GEN6(ring->dev) && ring->itlb_before_ctx_switch) { | ||
| 328 | ret = ring->flush(ring, 0, 0); | ||
| 329 | if (ret) | ||
| 330 | return ret; | ||
| 331 | } | ||
| 332 | |||
| 333 | ret = intel_ring_begin(ring, 6); | ||
| 334 | if (ret) | ||
| 335 | return ret; | ||
| 336 | |||
| 337 | if (IS_GEN7(ring->dev)) | ||
| 338 | intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE); | ||
| 339 | else | ||
| 340 | intel_ring_emit(ring, MI_NOOP); | ||
| 341 | |||
| 342 | intel_ring_emit(ring, MI_NOOP); | ||
| 343 | intel_ring_emit(ring, MI_SET_CONTEXT); | ||
| 344 | intel_ring_emit(ring, new_context->obj->gtt_offset | | ||
| 345 | MI_MM_SPACE_GTT | | ||
| 346 | MI_SAVE_EXT_STATE_EN | | ||
| 347 | MI_RESTORE_EXT_STATE_EN | | ||
| 348 | hw_flags); | ||
| 349 | /* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP */ | ||
| 350 | intel_ring_emit(ring, MI_NOOP); | ||
| 351 | |||
| 352 | if (IS_GEN7(ring->dev)) | ||
| 353 | intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE); | ||
| 354 | else | ||
| 355 | intel_ring_emit(ring, MI_NOOP); | ||
| 356 | |||
| 357 | intel_ring_advance(ring); | ||
| 358 | |||
| 359 | return ret; | ||
| 360 | } | ||
| 361 | |||
| 362 | static int do_switch(struct drm_i915_gem_object *from_obj, | ||
| 363 | struct i915_hw_context *to, | ||
| 364 | u32 seqno) | ||
| 365 | { | ||
| 366 | struct intel_ring_buffer *ring = NULL; | ||
| 367 | u32 hw_flags = 0; | ||
| 368 | int ret; | ||
| 369 | |||
| 370 | BUG_ON(to == NULL); | ||
| 371 | BUG_ON(from_obj != NULL && from_obj->pin_count == 0); | ||
| 372 | |||
| 373 | ret = i915_gem_object_pin(to->obj, CONTEXT_ALIGN, false); | ||
| 374 | if (ret) | ||
| 375 | return ret; | ||
| 376 | |||
| 377 | if (!to->obj->has_global_gtt_mapping) | ||
| 378 | i915_gem_gtt_bind_object(to->obj, to->obj->cache_level); | ||
| 379 | |||
| 380 | if (!to->is_initialized || is_default_context(to)) | ||
| 381 | hw_flags |= MI_RESTORE_INHIBIT; | ||
| 382 | else if (WARN_ON_ONCE(from_obj == to->obj)) /* not yet expected */ | ||
| 383 | hw_flags |= MI_FORCE_RESTORE; | ||
| 384 | |||
| 385 | ring = to->ring; | ||
| 386 | ret = mi_set_context(ring, to, hw_flags); | ||
| 387 | if (ret) { | ||
| 388 | i915_gem_object_unpin(to->obj); | ||
| 389 | return ret; | ||
| 390 | } | ||
| 391 | |||
| 392 | /* The backing object for the context is done after switching to the | ||
| 393 | * *next* context. Therefore we cannot retire the previous context until | ||
| 394 | * the next context has already started running. In fact, the below code | ||
| 395 | * is a bit suboptimal because the retiring can occur simply after the | ||
| 396 | * MI_SET_CONTEXT instead of when the next seqno has completed. | ||
| 397 | */ | ||
| 398 | if (from_obj != NULL) { | ||
| 399 | from_obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION; | ||
| 400 | i915_gem_object_move_to_active(from_obj, ring, seqno); | ||
| 401 | /* As long as MI_SET_CONTEXT is serializing, ie. it flushes the | ||
| 402 | * whole damn pipeline, we don't need to explicitly mark the | ||
| 403 | * object dirty. The only exception is that the context must be | ||
| 404 | * correct in case the object gets swapped out. Ideally we'd be | ||
| 405 | * able to defer doing this until we know the object would be | ||
| 406 | * swapped, but there is no way to do that yet. | ||
| 407 | */ | ||
| 408 | from_obj->dirty = 1; | ||
| 409 | BUG_ON(from_obj->ring != to->ring); | ||
| 410 | i915_gem_object_unpin(from_obj); | ||
| 411 | } | ||
| 412 | |||
| 413 | ring->last_context_obj = to->obj; | ||
| 414 | to->is_initialized = true; | ||
| 415 | |||
| 416 | return 0; | ||
| 417 | } | ||
| 418 | |||
| 419 | /** | ||
| 420 | * i915_switch_context() - perform a GPU context switch. | ||
| 421 | * @ring: ring for which we'll execute the context switch | ||
| 422 | * @file_priv: file_priv associated with the context, may be NULL | ||
| 423 | * @id: context id number | ||
| 424 | * @seqno: sequence number by which the new context will be switched to | ||
| 425 | * @flags: | ||
| 426 | * | ||
| 427 | * The context life cycle is simple. The context refcount is incremented and | ||
| 428 | * decremented by 1 and create and destroy. If the context is in use by the GPU, | ||
| 429 | * it will have a refoucnt > 1. This allows us to destroy the context abstract | ||
| 430 | * object while letting the normal object tracking destroy the backing BO. | ||
| 431 | */ | ||
| 432 | int i915_switch_context(struct intel_ring_buffer *ring, | ||
| 433 | struct drm_file *file, | ||
| 434 | int to_id) | ||
| 435 | { | ||
| 436 | struct drm_i915_private *dev_priv = ring->dev->dev_private; | ||
| 437 | struct drm_i915_file_private *file_priv = NULL; | ||
| 438 | struct i915_hw_context *to; | ||
| 439 | struct drm_i915_gem_object *from_obj = ring->last_context_obj; | ||
| 440 | int ret; | ||
| 441 | |||
| 442 | if (dev_priv->hw_contexts_disabled) | ||
| 443 | return 0; | ||
| 444 | |||
| 445 | if (ring != &dev_priv->ring[RCS]) | ||
| 446 | return 0; | ||
| 447 | |||
| 448 | if (file) | ||
| 449 | file_priv = file->driver_priv; | ||
| 450 | |||
| 451 | if (to_id == DEFAULT_CONTEXT_ID) { | ||
| 452 | to = ring->default_context; | ||
| 453 | } else { | ||
| 454 | to = i915_gem_context_get(file_priv, to_id); | ||
| 455 | if (to == NULL) | ||
| 456 | return -ENOENT; | ||
| 457 | } | ||
| 458 | |||
| 459 | if (from_obj == to->obj) | ||
| 460 | return 0; | ||
| 461 | |||
| 462 | ret = do_switch(from_obj, to, i915_gem_next_request_seqno(to->ring)); | ||
| 463 | if (ret) | ||
| 464 | return ret; | ||
| 465 | |||
| 466 | /* Just to make the code a little cleaner we take the object reference | ||
| 467 | * after the switch was successful. It would be more intuitive to ref | ||
| 468 | * the 'to' object before the switch but we know the refcount must be >0 | ||
| 469 | * if context_get() succeeded, and we hold struct mutex. So it's safe to | ||
| 470 | * do this here/now | ||
| 471 | */ | ||
| 472 | drm_gem_object_reference(&to->obj->base); | ||
| 473 | if (from_obj != NULL) | ||
| 474 | drm_gem_object_unreference(&from_obj->base); | ||
| 475 | return ret; | ||
| 476 | } | ||
| 477 | |||
| 478 | int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, | ||
| 479 | struct drm_file *file) | ||
| 480 | { | ||
| 481 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 482 | struct drm_i915_gem_context_create *args = data; | ||
| 483 | struct drm_i915_file_private *file_priv = file->driver_priv; | ||
| 484 | struct i915_hw_context *ctx; | ||
| 485 | int ret; | ||
| 486 | |||
| 487 | if (!(dev->driver->driver_features & DRIVER_GEM)) | ||
| 488 | return -ENODEV; | ||
| 489 | |||
| 490 | if (dev_priv->hw_contexts_disabled) | ||
| 491 | return -ENODEV; | ||
| 492 | |||
| 493 | ret = i915_mutex_lock_interruptible(dev); | ||
| 494 | if (ret) | ||
| 495 | return ret; | ||
| 496 | |||
| 497 | ctx = create_hw_context(dev, file_priv); | ||
| 498 | mutex_unlock(&dev->struct_mutex); | ||
| 499 | |||
| 500 | args->ctx_id = ctx->id; | ||
| 501 | DRM_DEBUG_DRIVER("HW context %d created\n", args->ctx_id); | ||
| 502 | |||
| 503 | return PTR_RET(ctx); | ||
| 504 | } | ||
| 505 | |||
| 506 | int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, | ||
| 507 | struct drm_file *file) | ||
| 508 | { | ||
| 509 | struct drm_i915_gem_context_destroy *args = data; | ||
| 510 | struct drm_i915_file_private *file_priv = file->driver_priv; | ||
| 511 | struct i915_hw_context *ctx; | ||
| 512 | int ret; | ||
| 513 | |||
| 514 | if (!(dev->driver->driver_features & DRIVER_GEM)) | ||
| 515 | return -ENODEV; | ||
| 516 | |||
| 517 | ret = i915_mutex_lock_interruptible(dev); | ||
| 518 | if (ret) | ||
| 519 | return ret; | ||
| 520 | |||
| 521 | ctx = i915_gem_context_get(file_priv, args->ctx_id); | ||
| 522 | if (!ctx) { | ||
| 523 | mutex_unlock(&dev->struct_mutex); | ||
| 524 | return -ENOENT; | ||
| 525 | } | ||
| 526 | |||
| 527 | do_destroy(ctx); | ||
| 528 | |||
| 529 | mutex_unlock(&dev->struct_mutex); | ||
| 530 | |||
| 531 | DRM_DEBUG_DRIVER("HW context %d destroyed\n", args->ctx_id); | ||
| 532 | return 0; | ||
| 533 | } | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c index a4f6aaabca99..bddf7bed183f 100644 --- a/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/drivers/gpu/drm/i915/i915_gem_debug.c | |||
| @@ -132,7 +132,8 @@ i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, int handle) | |||
| 132 | __func__, obj, obj->gtt_offset, handle, | 132 | __func__, obj, obj->gtt_offset, handle, |
| 133 | obj->size / 1024); | 133 | obj->size / 1024); |
| 134 | 134 | ||
| 135 | gtt_mapping = ioremap(dev->agp->base + obj->gtt_offset, obj->base.size); | 135 | gtt_mapping = ioremap(dev_priv->mm.gtt_base_addr + obj->gtt_offset, |
| 136 | obj->base.size); | ||
| 136 | if (gtt_mapping == NULL) { | 137 | if (gtt_mapping == NULL) { |
| 137 | DRM_ERROR("failed to map GTT space\n"); | 138 | DRM_ERROR("failed to map GTT space\n"); |
| 138 | return; | 139 | return; |
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index ae7c24e12e52..eba0308f10e3 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c | |||
| @@ -78,11 +78,12 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, | |||
| 78 | 78 | ||
| 79 | INIT_LIST_HEAD(&unwind_list); | 79 | INIT_LIST_HEAD(&unwind_list); |
| 80 | if (mappable) | 80 | if (mappable) |
| 81 | drm_mm_init_scan_with_range(&dev_priv->mm.gtt_space, min_size, | 81 | drm_mm_init_scan_with_range(&dev_priv->mm.gtt_space, |
| 82 | alignment, 0, | 82 | min_size, alignment, 0, |
| 83 | dev_priv->mm.gtt_mappable_end); | 83 | 0, dev_priv->mm.gtt_mappable_end); |
| 84 | else | 84 | else |
| 85 | drm_mm_init_scan(&dev_priv->mm.gtt_space, min_size, alignment); | 85 | drm_mm_init_scan(&dev_priv->mm.gtt_space, |
| 86 | min_size, alignment, 0); | ||
| 86 | 87 | ||
| 87 | /* First see if there is a large enough contiguous idle region... */ | 88 | /* First see if there is a large enough contiguous idle region... */ |
| 88 | list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list) { | 89 | list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list) { |
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 974a9f1068a3..88e2e114189c 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
| @@ -810,33 +810,16 @@ err: | |||
| 810 | return ret; | 810 | return ret; |
| 811 | } | 811 | } |
| 812 | 812 | ||
| 813 | static int | 813 | static void |
| 814 | i915_gem_execbuffer_flush(struct drm_device *dev, | 814 | i915_gem_execbuffer_flush(struct drm_device *dev, |
| 815 | uint32_t invalidate_domains, | 815 | uint32_t invalidate_domains, |
| 816 | uint32_t flush_domains, | 816 | uint32_t flush_domains) |
| 817 | uint32_t flush_rings) | ||
| 818 | { | 817 | { |
| 819 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 820 | int i, ret; | ||
| 821 | |||
| 822 | if (flush_domains & I915_GEM_DOMAIN_CPU) | 818 | if (flush_domains & I915_GEM_DOMAIN_CPU) |
| 823 | intel_gtt_chipset_flush(); | 819 | intel_gtt_chipset_flush(); |
| 824 | 820 | ||
| 825 | if (flush_domains & I915_GEM_DOMAIN_GTT) | 821 | if (flush_domains & I915_GEM_DOMAIN_GTT) |
| 826 | wmb(); | 822 | wmb(); |
| 827 | |||
| 828 | if ((flush_domains | invalidate_domains) & I915_GEM_GPU_DOMAINS) { | ||
| 829 | for (i = 0; i < I915_NUM_RINGS; i++) | ||
| 830 | if (flush_rings & (1 << i)) { | ||
| 831 | ret = i915_gem_flush_ring(&dev_priv->ring[i], | ||
| 832 | invalidate_domains, | ||
| 833 | flush_domains); | ||
| 834 | if (ret) | ||
| 835 | return ret; | ||
| 836 | } | ||
| 837 | } | ||
| 838 | |||
| 839 | return 0; | ||
| 840 | } | 823 | } |
| 841 | 824 | ||
| 842 | static int | 825 | static int |
| @@ -885,12 +868,9 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring, | |||
| 885 | i915_gem_object_set_to_gpu_domain(obj, ring, &cd); | 868 | i915_gem_object_set_to_gpu_domain(obj, ring, &cd); |
| 886 | 869 | ||
| 887 | if (cd.invalidate_domains | cd.flush_domains) { | 870 | if (cd.invalidate_domains | cd.flush_domains) { |
| 888 | ret = i915_gem_execbuffer_flush(ring->dev, | 871 | i915_gem_execbuffer_flush(ring->dev, |
| 889 | cd.invalidate_domains, | 872 | cd.invalidate_domains, |
| 890 | cd.flush_domains, | 873 | cd.flush_domains); |
| 891 | cd.flush_rings); | ||
| 892 | if (ret) | ||
| 893 | return ret; | ||
| 894 | } | 874 | } |
| 895 | 875 | ||
| 896 | if (cd.flips) { | 876 | if (cd.flips) { |
| @@ -905,6 +885,11 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring, | |||
| 905 | return ret; | 885 | return ret; |
| 906 | } | 886 | } |
| 907 | 887 | ||
| 888 | /* Unconditionally invalidate gpu caches. */ | ||
| 889 | ret = i915_gem_flush_ring(ring, I915_GEM_GPU_DOMAINS, 0); | ||
| 890 | if (ret) | ||
| 891 | return ret; | ||
| 892 | |||
| 908 | return 0; | 893 | return 0; |
| 909 | } | 894 | } |
| 910 | 895 | ||
| @@ -983,26 +968,13 @@ i915_gem_execbuffer_retire_commands(struct drm_device *dev, | |||
| 983 | struct intel_ring_buffer *ring) | 968 | struct intel_ring_buffer *ring) |
| 984 | { | 969 | { |
| 985 | struct drm_i915_gem_request *request; | 970 | struct drm_i915_gem_request *request; |
| 986 | u32 invalidate; | ||
| 987 | 971 | ||
| 988 | /* | 972 | /* Unconditionally force add_request to emit a full flush. */ |
| 989 | * Ensure that the commands in the batch buffer are | 973 | ring->gpu_caches_dirty = true; |
| 990 | * finished before the interrupt fires. | ||
| 991 | * | ||
| 992 | * The sampler always gets flushed on i965 (sigh). | ||
| 993 | */ | ||
| 994 | invalidate = I915_GEM_DOMAIN_COMMAND; | ||
| 995 | if (INTEL_INFO(dev)->gen >= 4) | ||
| 996 | invalidate |= I915_GEM_DOMAIN_SAMPLER; | ||
| 997 | if (ring->flush(ring, invalidate, 0)) { | ||
| 998 | i915_gem_next_request_seqno(ring); | ||
| 999 | return; | ||
| 1000 | } | ||
| 1001 | 974 | ||
| 1002 | /* Add a breadcrumb for the completion of the batch buffer */ | 975 | /* Add a breadcrumb for the completion of the batch buffer */ |
| 1003 | request = kzalloc(sizeof(*request), GFP_KERNEL); | 976 | request = kzalloc(sizeof(*request), GFP_KERNEL); |
| 1004 | if (request == NULL || i915_add_request(ring, file, request)) { | 977 | if (request == NULL || i915_add_request(ring, file, request)) { |
| 1005 | i915_gem_next_request_seqno(ring); | ||
| 1006 | kfree(request); | 978 | kfree(request); |
| 1007 | } | 979 | } |
| 1008 | } | 980 | } |
| @@ -1044,6 +1016,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
| 1044 | struct drm_i915_gem_object *batch_obj; | 1016 | struct drm_i915_gem_object *batch_obj; |
| 1045 | struct drm_clip_rect *cliprects = NULL; | 1017 | struct drm_clip_rect *cliprects = NULL; |
| 1046 | struct intel_ring_buffer *ring; | 1018 | struct intel_ring_buffer *ring; |
| 1019 | u32 ctx_id = i915_execbuffer2_get_context_id(*args); | ||
| 1047 | u32 exec_start, exec_len; | 1020 | u32 exec_start, exec_len; |
| 1048 | u32 seqno; | 1021 | u32 seqno; |
| 1049 | u32 mask; | 1022 | u32 mask; |
| @@ -1065,9 +1038,19 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
| 1065 | break; | 1038 | break; |
| 1066 | case I915_EXEC_BSD: | 1039 | case I915_EXEC_BSD: |
| 1067 | ring = &dev_priv->ring[VCS]; | 1040 | ring = &dev_priv->ring[VCS]; |
| 1041 | if (ctx_id != 0) { | ||
| 1042 | DRM_DEBUG("Ring %s doesn't support contexts\n", | ||
| 1043 | ring->name); | ||
| 1044 | return -EPERM; | ||
| 1045 | } | ||
| 1068 | break; | 1046 | break; |
| 1069 | case I915_EXEC_BLT: | 1047 | case I915_EXEC_BLT: |
| 1070 | ring = &dev_priv->ring[BCS]; | 1048 | ring = &dev_priv->ring[BCS]; |
| 1049 | if (ctx_id != 0) { | ||
| 1050 | DRM_DEBUG("Ring %s doesn't support contexts\n", | ||
| 1051 | ring->name); | ||
| 1052 | return -EPERM; | ||
| 1053 | } | ||
| 1071 | break; | 1054 | break; |
| 1072 | default: | 1055 | default: |
| 1073 | DRM_DEBUG("execbuf with unknown ring: %d\n", | 1056 | DRM_DEBUG("execbuf with unknown ring: %d\n", |
| @@ -1261,6 +1244,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
| 1261 | goto err; | 1244 | goto err; |
| 1262 | } | 1245 | } |
| 1263 | 1246 | ||
| 1247 | ret = i915_switch_context(ring, file, ctx_id); | ||
| 1248 | if (ret) | ||
| 1249 | goto err; | ||
| 1250 | |||
| 1264 | trace_i915_gem_ring_dispatch(ring, seqno); | 1251 | trace_i915_gem_ring_dispatch(ring, seqno); |
| 1265 | 1252 | ||
| 1266 | exec_start = batch_obj->gtt_offset + args->batch_start_offset; | 1253 | exec_start = batch_obj->gtt_offset + args->batch_start_offset; |
| @@ -1367,6 +1354,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
| 1367 | exec2.num_cliprects = args->num_cliprects; | 1354 | exec2.num_cliprects = args->num_cliprects; |
| 1368 | exec2.cliprects_ptr = args->cliprects_ptr; | 1355 | exec2.cliprects_ptr = args->cliprects_ptr; |
| 1369 | exec2.flags = I915_EXEC_RENDER; | 1356 | exec2.flags = I915_EXEC_RENDER; |
| 1357 | i915_execbuffer2_set_context_id(exec2, 0); | ||
| 1370 | 1358 | ||
| 1371 | ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list); | 1359 | ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list); |
| 1372 | if (!ret) { | 1360 | if (!ret) { |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ed3224c37423..05014bc20ee8 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -375,6 +375,86 @@ static void gen6_pm_rps_work(struct work_struct *work) | |||
| 375 | mutex_unlock(&dev_priv->dev->struct_mutex); | 375 | mutex_unlock(&dev_priv->dev->struct_mutex); |
| 376 | } | 376 | } |
| 377 | 377 | ||
| 378 | |||
| 379 | /** | ||
| 380 | * ivybridge_parity_work - Workqueue called when a parity error interrupt | ||
| 381 | * occurred. | ||
| 382 | * @work: workqueue struct | ||
| 383 | * | ||
| 384 | * Doesn't actually do anything except notify userspace. As a consequence of | ||
| 385 | * this event, userspace should try to remap the bad rows since statistically | ||
| 386 | * it is likely the same row is more likely to go bad again. | ||
| 387 | */ | ||
| 388 | static void ivybridge_parity_work(struct work_struct *work) | ||
| 389 | { | ||
| 390 | drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, | ||
| 391 | parity_error_work); | ||
| 392 | u32 error_status, row, bank, subbank; | ||
| 393 | char *parity_event[5]; | ||
| 394 | uint32_t misccpctl; | ||
| 395 | unsigned long flags; | ||
| 396 | |||
| 397 | /* We must turn off DOP level clock gating to access the L3 registers. | ||
| 398 | * In order to prevent a get/put style interface, acquire struct mutex | ||
| 399 | * any time we access those registers. | ||
| 400 | */ | ||
| 401 | mutex_lock(&dev_priv->dev->struct_mutex); | ||
| 402 | |||
| 403 | misccpctl = I915_READ(GEN7_MISCCPCTL); | ||
| 404 | I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); | ||
| 405 | POSTING_READ(GEN7_MISCCPCTL); | ||
| 406 | |||
| 407 | error_status = I915_READ(GEN7_L3CDERRST1); | ||
| 408 | row = GEN7_PARITY_ERROR_ROW(error_status); | ||
| 409 | bank = GEN7_PARITY_ERROR_BANK(error_status); | ||
| 410 | subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); | ||
| 411 | |||
| 412 | I915_WRITE(GEN7_L3CDERRST1, GEN7_PARITY_ERROR_VALID | | ||
| 413 | GEN7_L3CDERRST1_ENABLE); | ||
| 414 | POSTING_READ(GEN7_L3CDERRST1); | ||
| 415 | |||
| 416 | I915_WRITE(GEN7_MISCCPCTL, misccpctl); | ||
| 417 | |||
| 418 | spin_lock_irqsave(&dev_priv->irq_lock, flags); | ||
| 419 | dev_priv->gt_irq_mask &= ~GT_GEN7_L3_PARITY_ERROR_INTERRUPT; | ||
| 420 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); | ||
| 421 | spin_unlock_irqrestore(&dev_priv->irq_lock, flags); | ||
| 422 | |||
| 423 | mutex_unlock(&dev_priv->dev->struct_mutex); | ||
| 424 | |||
| 425 | parity_event[0] = "L3_PARITY_ERROR=1"; | ||
| 426 | parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); | ||
| 427 | parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); | ||
| 428 | parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); | ||
| 429 | parity_event[4] = NULL; | ||
| 430 | |||
| 431 | kobject_uevent_env(&dev_priv->dev->primary->kdev.kobj, | ||
| 432 | KOBJ_CHANGE, parity_event); | ||
| 433 | |||
| 434 | DRM_DEBUG("Parity error: Row = %d, Bank = %d, Sub bank = %d.\n", | ||
| 435 | row, bank, subbank); | ||
| 436 | |||
| 437 | kfree(parity_event[3]); | ||
| 438 | kfree(parity_event[2]); | ||
| 439 | kfree(parity_event[1]); | ||
| 440 | } | ||
| 441 | |||
| 442 | static void ivybridge_handle_parity_error(struct drm_device *dev) | ||
| 443 | { | ||
| 444 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
| 445 | unsigned long flags; | ||
| 446 | |||
| 447 | if (!IS_IVYBRIDGE(dev)) | ||
| 448 | return; | ||
| 449 | |||
| 450 | spin_lock_irqsave(&dev_priv->irq_lock, flags); | ||
| 451 | dev_priv->gt_irq_mask |= GT_GEN7_L3_PARITY_ERROR_INTERRUPT; | ||
| 452 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); | ||
| 453 | spin_unlock_irqrestore(&dev_priv->irq_lock, flags); | ||
| 454 | |||
| 455 | queue_work(dev_priv->wq, &dev_priv->parity_error_work); | ||
| 456 | } | ||
| 457 | |||
| 378 | static void snb_gt_irq_handler(struct drm_device *dev, | 458 | static void snb_gt_irq_handler(struct drm_device *dev, |
| 379 | struct drm_i915_private *dev_priv, | 459 | struct drm_i915_private *dev_priv, |
| 380 | u32 gt_iir) | 460 | u32 gt_iir) |
| @@ -394,6 +474,9 @@ static void snb_gt_irq_handler(struct drm_device *dev, | |||
| 394 | DRM_ERROR("GT error interrupt 0x%08x\n", gt_iir); | 474 | DRM_ERROR("GT error interrupt 0x%08x\n", gt_iir); |
| 395 | i915_handle_error(dev, false); | 475 | i915_handle_error(dev, false); |
| 396 | } | 476 | } |
| 477 | |||
| 478 | if (gt_iir & GT_GEN7_L3_PARITY_ERROR_INTERRUPT) | ||
| 479 | ivybridge_handle_parity_error(dev); | ||
| 397 | } | 480 | } |
| 398 | 481 | ||
| 399 | static void gen6_queue_rps_work(struct drm_i915_private *dev_priv, | 482 | static void gen6_queue_rps_work(struct drm_i915_private *dev_priv, |
| @@ -429,15 +512,10 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS) | |||
| 429 | unsigned long irqflags; | 512 | unsigned long irqflags; |
| 430 | int pipe; | 513 | int pipe; |
| 431 | u32 pipe_stats[I915_MAX_PIPES]; | 514 | u32 pipe_stats[I915_MAX_PIPES]; |
| 432 | u32 vblank_status; | ||
| 433 | int vblank = 0; | ||
| 434 | bool blc_event; | 515 | bool blc_event; |
| 435 | 516 | ||
| 436 | atomic_inc(&dev_priv->irq_received); | 517 | atomic_inc(&dev_priv->irq_received); |
| 437 | 518 | ||
| 438 | vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS | | ||
| 439 | PIPE_VBLANK_INTERRUPT_STATUS; | ||
| 440 | |||
| 441 | while (true) { | 519 | while (true) { |
| 442 | iir = I915_READ(VLV_IIR); | 520 | iir = I915_READ(VLV_IIR); |
| 443 | gt_iir = I915_READ(GTIIR); | 521 | gt_iir = I915_READ(GTIIR); |
| @@ -467,6 +545,16 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS) | |||
| 467 | } | 545 | } |
| 468 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 546 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
| 469 | 547 | ||
| 548 | for_each_pipe(pipe) { | ||
| 549 | if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) | ||
| 550 | drm_handle_vblank(dev, pipe); | ||
| 551 | |||
| 552 | if (pipe_stats[pipe] & PLANE_FLIPDONE_INT_STATUS_VLV) { | ||
| 553 | intel_prepare_page_flip(dev, pipe); | ||
| 554 | intel_finish_page_flip(dev, pipe); | ||
| 555 | } | ||
| 556 | } | ||
| 557 | |||
| 470 | /* Consume port. Then clear IIR or we'll miss events */ | 558 | /* Consume port. Then clear IIR or we'll miss events */ |
| 471 | if (iir & I915_DISPLAY_PORT_INTERRUPT) { | 559 | if (iir & I915_DISPLAY_PORT_INTERRUPT) { |
| 472 | u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); | 560 | u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); |
| @@ -481,19 +569,6 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS) | |||
| 481 | I915_READ(PORT_HOTPLUG_STAT); | 569 | I915_READ(PORT_HOTPLUG_STAT); |
| 482 | } | 570 | } |
| 483 | 571 | ||
| 484 | |||
| 485 | if (iir & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT) { | ||
| 486 | drm_handle_vblank(dev, 0); | ||
| 487 | vblank++; | ||
| 488 | intel_finish_page_flip(dev, 0); | ||
| 489 | } | ||
| 490 | |||
| 491 | if (iir & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT) { | ||
| 492 | drm_handle_vblank(dev, 1); | ||
| 493 | vblank++; | ||
| 494 | intel_finish_page_flip(dev, 0); | ||
| 495 | } | ||
| 496 | |||
| 497 | if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) | 572 | if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) |
| 498 | blc_event = true; | 573 | blc_event = true; |
| 499 | 574 | ||
| @@ -1104,6 +1179,7 @@ static void i915_capture_error_state(struct drm_device *dev) | |||
| 1104 | kref_init(&error->ref); | 1179 | kref_init(&error->ref); |
| 1105 | error->eir = I915_READ(EIR); | 1180 | error->eir = I915_READ(EIR); |
| 1106 | error->pgtbl_er = I915_READ(PGTBL_ER); | 1181 | error->pgtbl_er = I915_READ(PGTBL_ER); |
| 1182 | error->ccid = I915_READ(CCID); | ||
| 1107 | 1183 | ||
| 1108 | if (HAS_PCH_SPLIT(dev)) | 1184 | if (HAS_PCH_SPLIT(dev)) |
| 1109 | error->ier = I915_READ(DEIER) | I915_READ(GTIER); | 1185 | error->ier = I915_READ(DEIER) | I915_READ(GTIER); |
| @@ -1426,23 +1502,20 @@ static int valleyview_enable_vblank(struct drm_device *dev, int pipe) | |||
| 1426 | { | 1502 | { |
| 1427 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1503 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 1428 | unsigned long irqflags; | 1504 | unsigned long irqflags; |
| 1429 | u32 dpfl, imr; | 1505 | u32 imr; |
| 1430 | 1506 | ||
| 1431 | if (!i915_pipe_enabled(dev, pipe)) | 1507 | if (!i915_pipe_enabled(dev, pipe)) |
| 1432 | return -EINVAL; | 1508 | return -EINVAL; |
| 1433 | 1509 | ||
| 1434 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | 1510 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
| 1435 | dpfl = I915_READ(VLV_DPFLIPSTAT); | ||
| 1436 | imr = I915_READ(VLV_IMR); | 1511 | imr = I915_READ(VLV_IMR); |
| 1437 | if (pipe == 0) { | 1512 | if (pipe == 0) |
| 1438 | dpfl |= PIPEA_VBLANK_INT_EN; | ||
| 1439 | imr &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; | 1513 | imr &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; |
| 1440 | } else { | 1514 | else |
| 1441 | dpfl |= PIPEA_VBLANK_INT_EN; | ||
| 1442 | imr &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; | 1515 | imr &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; |
| 1443 | } | ||
| 1444 | I915_WRITE(VLV_DPFLIPSTAT, dpfl); | ||
| 1445 | I915_WRITE(VLV_IMR, imr); | 1516 | I915_WRITE(VLV_IMR, imr); |
| 1517 | i915_enable_pipestat(dev_priv, pipe, | ||
| 1518 | PIPE_START_VBLANK_INTERRUPT_ENABLE); | ||
| 1446 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 1519 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
| 1447 | 1520 | ||
| 1448 | return 0; | 1521 | return 0; |
| @@ -1492,20 +1565,17 @@ static void valleyview_disable_vblank(struct drm_device *dev, int pipe) | |||
| 1492 | { | 1565 | { |
| 1493 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1566 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 1494 | unsigned long irqflags; | 1567 | unsigned long irqflags; |
| 1495 | u32 dpfl, imr; | 1568 | u32 imr; |
| 1496 | 1569 | ||
| 1497 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | 1570 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
| 1498 | dpfl = I915_READ(VLV_DPFLIPSTAT); | 1571 | i915_disable_pipestat(dev_priv, pipe, |
| 1572 | PIPE_START_VBLANK_INTERRUPT_ENABLE); | ||
| 1499 | imr = I915_READ(VLV_IMR); | 1573 | imr = I915_READ(VLV_IMR); |
| 1500 | if (pipe == 0) { | 1574 | if (pipe == 0) |
| 1501 | dpfl &= ~PIPEA_VBLANK_INT_EN; | ||
| 1502 | imr |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; | 1575 | imr |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; |
| 1503 | } else { | 1576 | else |
| 1504 | dpfl &= ~PIPEB_VBLANK_INT_EN; | ||
| 1505 | imr |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; | 1577 | imr |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; |
| 1506 | } | ||
| 1507 | I915_WRITE(VLV_IMR, imr); | 1578 | I915_WRITE(VLV_IMR, imr); |
| 1508 | I915_WRITE(VLV_DPFLIPSTAT, dpfl); | ||
| 1509 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 1579 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
| 1510 | } | 1580 | } |
| 1511 | 1581 | ||
| @@ -1648,7 +1718,6 @@ static void ironlake_irq_preinstall(struct drm_device *dev) | |||
| 1648 | 1718 | ||
| 1649 | atomic_set(&dev_priv->irq_received, 0); | 1719 | atomic_set(&dev_priv->irq_received, 0); |
| 1650 | 1720 | ||
| 1651 | |||
| 1652 | I915_WRITE(HWSTAM, 0xeffe); | 1721 | I915_WRITE(HWSTAM, 0xeffe); |
| 1653 | 1722 | ||
| 1654 | /* XXX hotplug from PCH */ | 1723 | /* XXX hotplug from PCH */ |
| @@ -1811,13 +1880,13 @@ static int ivybridge_irq_postinstall(struct drm_device *dev) | |||
| 1811 | DE_PIPEA_VBLANK_IVB); | 1880 | DE_PIPEA_VBLANK_IVB); |
| 1812 | POSTING_READ(DEIER); | 1881 | POSTING_READ(DEIER); |
| 1813 | 1882 | ||
| 1814 | dev_priv->gt_irq_mask = ~0; | 1883 | dev_priv->gt_irq_mask = ~GT_GEN7_L3_PARITY_ERROR_INTERRUPT; |
| 1815 | 1884 | ||
| 1816 | I915_WRITE(GTIIR, I915_READ(GTIIR)); | 1885 | I915_WRITE(GTIIR, I915_READ(GTIIR)); |
| 1817 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); | 1886 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); |
| 1818 | 1887 | ||
| 1819 | render_irqs = GT_USER_INTERRUPT | GEN6_BSD_USER_INTERRUPT | | 1888 | render_irqs = GT_USER_INTERRUPT | GEN6_BSD_USER_INTERRUPT | |
| 1820 | GEN6_BLITTER_USER_INTERRUPT; | 1889 | GEN6_BLITTER_USER_INTERRUPT | GT_GEN7_L3_PARITY_ERROR_INTERRUPT; |
| 1821 | I915_WRITE(GTIER, render_irqs); | 1890 | I915_WRITE(GTIER, render_irqs); |
| 1822 | POSTING_READ(GTIER); | 1891 | POSTING_READ(GTIER); |
| 1823 | 1892 | ||
| @@ -1840,16 +1909,24 @@ static int ivybridge_irq_postinstall(struct drm_device *dev) | |||
| 1840 | static int valleyview_irq_postinstall(struct drm_device *dev) | 1909 | static int valleyview_irq_postinstall(struct drm_device *dev) |
| 1841 | { | 1910 | { |
| 1842 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1911 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 1843 | u32 render_irqs; | ||
| 1844 | u32 enable_mask; | 1912 | u32 enable_mask; |
| 1845 | u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); | 1913 | u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); |
| 1914 | u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV; | ||
| 1846 | u16 msid; | 1915 | u16 msid; |
| 1847 | 1916 | ||
| 1848 | enable_mask = I915_DISPLAY_PORT_INTERRUPT; | 1917 | enable_mask = I915_DISPLAY_PORT_INTERRUPT; |
| 1849 | enable_mask |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | | 1918 | enable_mask |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | |
| 1919 | I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | | ||
| 1920 | I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | | ||
| 1850 | I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; | 1921 | I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; |
| 1851 | 1922 | ||
| 1852 | dev_priv->irq_mask = ~enable_mask; | 1923 | /* |
| 1924 | *Leave vblank interrupts masked initially. enable/disable will | ||
| 1925 | * toggle them based on usage. | ||
| 1926 | */ | ||
| 1927 | dev_priv->irq_mask = (~enable_mask) | | ||
| 1928 | I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | | ||
| 1929 | I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; | ||
| 1853 | 1930 | ||
| 1854 | dev_priv->pipestat[0] = 0; | 1931 | dev_priv->pipestat[0] = 0; |
| 1855 | dev_priv->pipestat[1] = 0; | 1932 | dev_priv->pipestat[1] = 0; |
| @@ -1868,26 +1945,27 @@ static int valleyview_irq_postinstall(struct drm_device *dev) | |||
| 1868 | I915_WRITE(PIPESTAT(1), 0xffff); | 1945 | I915_WRITE(PIPESTAT(1), 0xffff); |
| 1869 | POSTING_READ(VLV_IER); | 1946 | POSTING_READ(VLV_IER); |
| 1870 | 1947 | ||
| 1948 | i915_enable_pipestat(dev_priv, 0, pipestat_enable); | ||
| 1949 | i915_enable_pipestat(dev_priv, 1, pipestat_enable); | ||
| 1950 | |||
| 1871 | I915_WRITE(VLV_IIR, 0xffffffff); | 1951 | I915_WRITE(VLV_IIR, 0xffffffff); |
| 1872 | I915_WRITE(VLV_IIR, 0xffffffff); | 1952 | I915_WRITE(VLV_IIR, 0xffffffff); |
| 1873 | 1953 | ||
| 1874 | render_irqs = GT_GEN6_BLT_FLUSHDW_NOTIFY_INTERRUPT | | 1954 | dev_priv->gt_irq_mask = ~0; |
| 1875 | GT_GEN6_BLT_CS_ERROR_INTERRUPT | | ||
| 1876 | GT_GEN6_BLT_USER_INTERRUPT | | ||
| 1877 | GT_GEN6_BSD_USER_INTERRUPT | | ||
| 1878 | GT_GEN6_BSD_CS_ERROR_INTERRUPT | | ||
| 1879 | GT_GEN7_L3_PARITY_ERROR_INTERRUPT | | ||
| 1880 | GT_PIPE_NOTIFY | | ||
| 1881 | GT_RENDER_CS_ERROR_INTERRUPT | | ||
| 1882 | GT_SYNC_STATUS | | ||
| 1883 | GT_USER_INTERRUPT; | ||
| 1884 | |||
| 1885 | dev_priv->gt_irq_mask = ~render_irqs; | ||
| 1886 | 1955 | ||
| 1887 | I915_WRITE(GTIIR, I915_READ(GTIIR)); | 1956 | I915_WRITE(GTIIR, I915_READ(GTIIR)); |
| 1888 | I915_WRITE(GTIIR, I915_READ(GTIIR)); | 1957 | I915_WRITE(GTIIR, I915_READ(GTIIR)); |
| 1889 | I915_WRITE(GTIMR, 0); | 1958 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); |
| 1890 | I915_WRITE(GTIER, render_irqs); | 1959 | I915_WRITE(GTIER, GT_GEN6_BLT_FLUSHDW_NOTIFY_INTERRUPT | |
| 1960 | GT_GEN6_BLT_CS_ERROR_INTERRUPT | | ||
| 1961 | GT_GEN6_BLT_USER_INTERRUPT | | ||
| 1962 | GT_GEN6_BSD_USER_INTERRUPT | | ||
| 1963 | GT_GEN6_BSD_CS_ERROR_INTERRUPT | | ||
| 1964 | GT_GEN7_L3_PARITY_ERROR_INTERRUPT | | ||
| 1965 | GT_PIPE_NOTIFY | | ||
| 1966 | GT_RENDER_CS_ERROR_INTERRUPT | | ||
| 1967 | GT_SYNC_STATUS | | ||
| 1968 | GT_USER_INTERRUPT); | ||
| 1891 | POSTING_READ(GTIER); | 1969 | POSTING_READ(GTIER); |
| 1892 | 1970 | ||
| 1893 | /* ack & enable invalid PTE error interrupts */ | 1971 | /* ack & enable invalid PTE error interrupts */ |
| @@ -2166,9 +2244,9 @@ static int i915_irq_postinstall(struct drm_device *dev) | |||
| 2166 | hotplug_en |= HDMIC_HOTPLUG_INT_EN; | 2244 | hotplug_en |= HDMIC_HOTPLUG_INT_EN; |
| 2167 | if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) | 2245 | if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) |
| 2168 | hotplug_en |= HDMID_HOTPLUG_INT_EN; | 2246 | hotplug_en |= HDMID_HOTPLUG_INT_EN; |
| 2169 | if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) | 2247 | if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I915) |
| 2170 | hotplug_en |= SDVOC_HOTPLUG_INT_EN; | 2248 | hotplug_en |= SDVOC_HOTPLUG_INT_EN; |
| 2171 | if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) | 2249 | if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I915) |
| 2172 | hotplug_en |= SDVOB_HOTPLUG_INT_EN; | 2250 | hotplug_en |= SDVOB_HOTPLUG_INT_EN; |
| 2173 | if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { | 2251 | if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { |
| 2174 | hotplug_en |= CRT_HOTPLUG_INT_EN; | 2252 | hotplug_en |= CRT_HOTPLUG_INT_EN; |
| @@ -2328,10 +2406,8 @@ static void i965_irq_preinstall(struct drm_device * dev) | |||
| 2328 | 2406 | ||
| 2329 | atomic_set(&dev_priv->irq_received, 0); | 2407 | atomic_set(&dev_priv->irq_received, 0); |
| 2330 | 2408 | ||
| 2331 | if (I915_HAS_HOTPLUG(dev)) { | 2409 | I915_WRITE(PORT_HOTPLUG_EN, 0); |
| 2332 | I915_WRITE(PORT_HOTPLUG_EN, 0); | 2410 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); |
| 2333 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); | ||
| 2334 | } | ||
| 2335 | 2411 | ||
| 2336 | I915_WRITE(HWSTAM, 0xeffe); | 2412 | I915_WRITE(HWSTAM, 0xeffe); |
| 2337 | for_each_pipe(pipe) | 2413 | for_each_pipe(pipe) |
| @@ -2344,11 +2420,13 @@ static void i965_irq_preinstall(struct drm_device * dev) | |||
| 2344 | static int i965_irq_postinstall(struct drm_device *dev) | 2420 | static int i965_irq_postinstall(struct drm_device *dev) |
| 2345 | { | 2421 | { |
| 2346 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 2422 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 2423 | u32 hotplug_en; | ||
| 2347 | u32 enable_mask; | 2424 | u32 enable_mask; |
| 2348 | u32 error_mask; | 2425 | u32 error_mask; |
| 2349 | 2426 | ||
| 2350 | /* Unmask the interrupts that we always want on. */ | 2427 | /* Unmask the interrupts that we always want on. */ |
| 2351 | dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT | | 2428 | dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT | |
| 2429 | I915_DISPLAY_PORT_INTERRUPT | | ||
| 2352 | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | | 2430 | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | |
| 2353 | I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | | 2431 | I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | |
| 2354 | I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | | 2432 | I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | |
| @@ -2364,13 +2442,6 @@ static int i965_irq_postinstall(struct drm_device *dev) | |||
| 2364 | dev_priv->pipestat[0] = 0; | 2442 | dev_priv->pipestat[0] = 0; |
| 2365 | dev_priv->pipestat[1] = 0; | 2443 | dev_priv->pipestat[1] = 0; |
| 2366 | 2444 | ||
| 2367 | if (I915_HAS_HOTPLUG(dev)) { | ||
| 2368 | /* Enable in IER... */ | ||
| 2369 | enable_mask |= I915_DISPLAY_PORT_INTERRUPT; | ||
| 2370 | /* and unmask in IMR */ | ||
| 2371 | dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT; | ||
| 2372 | } | ||
| 2373 | |||
| 2374 | /* | 2445 | /* |
| 2375 | * Enable some error detection, note the instruction error mask | 2446 | * Enable some error detection, note the instruction error mask |
| 2376 | * bit is reserved, so we leave it masked. | 2447 | * bit is reserved, so we leave it masked. |
| @@ -2390,36 +2461,40 @@ static int i965_irq_postinstall(struct drm_device *dev) | |||
| 2390 | I915_WRITE(IER, enable_mask); | 2461 | I915_WRITE(IER, enable_mask); |
| 2391 | POSTING_READ(IER); | 2462 | POSTING_READ(IER); |
| 2392 | 2463 | ||
| 2393 | if (I915_HAS_HOTPLUG(dev)) { | 2464 | /* Note HDMI and DP share hotplug bits */ |
| 2394 | u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); | 2465 | hotplug_en = 0; |
| 2395 | 2466 | if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) | |
| 2396 | /* Note HDMI and DP share bits */ | 2467 | hotplug_en |= HDMIB_HOTPLUG_INT_EN; |
| 2397 | if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) | 2468 | if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) |
| 2398 | hotplug_en |= HDMIB_HOTPLUG_INT_EN; | 2469 | hotplug_en |= HDMIC_HOTPLUG_INT_EN; |
| 2399 | if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) | 2470 | if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) |
| 2400 | hotplug_en |= HDMIC_HOTPLUG_INT_EN; | 2471 | hotplug_en |= HDMID_HOTPLUG_INT_EN; |
| 2401 | if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) | 2472 | if (IS_G4X(dev)) { |
| 2402 | hotplug_en |= HDMID_HOTPLUG_INT_EN; | 2473 | if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_G4X) |
| 2403 | if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) | ||
| 2404 | hotplug_en |= SDVOC_HOTPLUG_INT_EN; | 2474 | hotplug_en |= SDVOC_HOTPLUG_INT_EN; |
| 2405 | if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) | 2475 | if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_G4X) |
| 2406 | hotplug_en |= SDVOB_HOTPLUG_INT_EN; | 2476 | hotplug_en |= SDVOB_HOTPLUG_INT_EN; |
| 2407 | if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { | 2477 | } else { |
| 2408 | hotplug_en |= CRT_HOTPLUG_INT_EN; | 2478 | if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I965) |
| 2479 | hotplug_en |= SDVOC_HOTPLUG_INT_EN; | ||
| 2480 | if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I965) | ||
| 2481 | hotplug_en |= SDVOB_HOTPLUG_INT_EN; | ||
| 2482 | } | ||
| 2483 | if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { | ||
| 2484 | hotplug_en |= CRT_HOTPLUG_INT_EN; | ||
| 2409 | 2485 | ||
| 2410 | /* Programming the CRT detection parameters tends | 2486 | /* Programming the CRT detection parameters tends |
| 2411 | to generate a spurious hotplug event about three | 2487 | to generate a spurious hotplug event about three |
| 2412 | seconds later. So just do it once. | 2488 | seconds later. So just do it once. |
| 2413 | */ | 2489 | */ |
| 2414 | if (IS_G4X(dev)) | 2490 | if (IS_G4X(dev)) |
| 2415 | hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; | 2491 | hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; |
| 2416 | hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; | 2492 | hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; |
| 2417 | } | 2493 | } |
| 2418 | 2494 | ||
| 2419 | /* Ignore TV since it's buggy */ | 2495 | /* Ignore TV since it's buggy */ |
| 2420 | 2496 | ||
| 2421 | I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); | 2497 | I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); |
| 2422 | } | ||
| 2423 | 2498 | ||
| 2424 | intel_opregion_enable_asle(dev); | 2499 | intel_opregion_enable_asle(dev); |
| 2425 | 2500 | ||
| @@ -2477,8 +2552,7 @@ static irqreturn_t i965_irq_handler(DRM_IRQ_ARGS) | |||
| 2477 | ret = IRQ_HANDLED; | 2552 | ret = IRQ_HANDLED; |
| 2478 | 2553 | ||
| 2479 | /* Consume port. Then clear IIR or we'll miss events */ | 2554 | /* Consume port. Then clear IIR or we'll miss events */ |
| 2480 | if ((I915_HAS_HOTPLUG(dev)) && | 2555 | if (iir & I915_DISPLAY_PORT_INTERRUPT) { |
| 2481 | (iir & I915_DISPLAY_PORT_INTERRUPT)) { | ||
| 2482 | u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); | 2556 | u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); |
| 2483 | 2557 | ||
| 2484 | DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n", | 2558 | DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n", |
| @@ -2551,10 +2625,8 @@ static void i965_irq_uninstall(struct drm_device * dev) | |||
| 2551 | if (!dev_priv) | 2625 | if (!dev_priv) |
| 2552 | return; | 2626 | return; |
| 2553 | 2627 | ||
| 2554 | if (I915_HAS_HOTPLUG(dev)) { | 2628 | I915_WRITE(PORT_HOTPLUG_EN, 0); |
| 2555 | I915_WRITE(PORT_HOTPLUG_EN, 0); | 2629 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); |
| 2556 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); | ||
| 2557 | } | ||
| 2558 | 2630 | ||
| 2559 | I915_WRITE(HWSTAM, 0xffffffff); | 2631 | I915_WRITE(HWSTAM, 0xffffffff); |
| 2560 | for_each_pipe(pipe) | 2632 | for_each_pipe(pipe) |
| @@ -2575,6 +2647,7 @@ void intel_irq_init(struct drm_device *dev) | |||
| 2575 | INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); | 2647 | INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); |
| 2576 | INIT_WORK(&dev_priv->error_work, i915_error_work_func); | 2648 | INIT_WORK(&dev_priv->error_work, i915_error_work_func); |
| 2577 | INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); | 2649 | INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); |
| 2650 | INIT_WORK(&dev_priv->parity_error_work, ivybridge_parity_work); | ||
| 2578 | 2651 | ||
| 2579 | dev->driver->get_vblank_counter = i915_get_vblank_counter; | 2652 | dev->driver->get_vblank_counter = i915_get_vblank_counter; |
| 2580 | dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ | 2653 | dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 48d5e8e051cf..1218069c7f66 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -217,6 +217,9 @@ | |||
| 217 | #define MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19) | 217 | #define MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19) |
| 218 | #define MI_DISPLAY_FLIP_IVB_PLANE_C (4 << 19) | 218 | #define MI_DISPLAY_FLIP_IVB_PLANE_C (4 << 19) |
| 219 | #define MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19) | 219 | #define MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19) |
| 220 | #define MI_ARB_ON_OFF MI_INSTR(0x08, 0) | ||
| 221 | #define MI_ARB_ENABLE (1<<0) | ||
| 222 | #define MI_ARB_DISABLE (0<<0) | ||
| 220 | 223 | ||
| 221 | #define MI_SET_CONTEXT MI_INSTR(0x18, 0) | 224 | #define MI_SET_CONTEXT MI_INSTR(0x18, 0) |
| 222 | #define MI_MM_SPACE_GTT (1<<8) | 225 | #define MI_MM_SPACE_GTT (1<<8) |
| @@ -299,6 +302,7 @@ | |||
| 299 | #define DISPLAY_PLANE_B (1<<20) | 302 | #define DISPLAY_PLANE_B (1<<20) |
| 300 | #define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2)) | 303 | #define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2)) |
| 301 | #define PIPE_CONTROL_CS_STALL (1<<20) | 304 | #define PIPE_CONTROL_CS_STALL (1<<20) |
| 305 | #define PIPE_CONTROL_TLB_INVALIDATE (1<<18) | ||
| 302 | #define PIPE_CONTROL_QW_WRITE (1<<14) | 306 | #define PIPE_CONTROL_QW_WRITE (1<<14) |
| 303 | #define PIPE_CONTROL_DEPTH_STALL (1<<13) | 307 | #define PIPE_CONTROL_DEPTH_STALL (1<<13) |
| 304 | #define PIPE_CONTROL_WRITE_FLUSH (1<<12) | 308 | #define PIPE_CONTROL_WRITE_FLUSH (1<<12) |
| @@ -908,6 +912,7 @@ | |||
| 908 | #define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ | 912 | #define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ |
| 909 | #define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ | 913 | #define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ |
| 910 | #define DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */ | 914 | #define DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */ |
| 915 | #define DPLL_LOCK_VLV (1<<15) | ||
| 911 | #define DPLL_INTEGRATED_CLOCK_VLV (1<<13) | 916 | #define DPLL_INTEGRATED_CLOCK_VLV (1<<13) |
| 912 | 917 | ||
| 913 | #define SRX_INDEX 0x3c4 | 918 | #define SRX_INDEX 0x3c4 |
| @@ -1453,6 +1458,10 @@ | |||
| 1453 | #define DDRMPLL1 0X12c20 | 1458 | #define DDRMPLL1 0X12c20 |
| 1454 | #define PEG_BAND_GAP_DATA 0x14d68 | 1459 | #define PEG_BAND_GAP_DATA 0x14d68 |
| 1455 | 1460 | ||
| 1461 | #define GEN6_GT_THREAD_STATUS_REG 0x13805c | ||
| 1462 | #define GEN6_GT_THREAD_STATUS_CORE_MASK 0x7 | ||
| 1463 | #define GEN6_GT_THREAD_STATUS_CORE_MASK_HSW (0x7 | (0x07 << 16)) | ||
| 1464 | |||
| 1456 | #define GEN6_GT_PERF_STATUS 0x145948 | 1465 | #define GEN6_GT_PERF_STATUS 0x145948 |
| 1457 | #define GEN6_RP_STATE_LIMITS 0x145994 | 1466 | #define GEN6_RP_STATE_LIMITS 0x145994 |
| 1458 | #define GEN6_RP_STATE_CAP 0x145998 | 1467 | #define GEN6_RP_STATE_CAP 0x145998 |
| @@ -1462,6 +1471,27 @@ | |||
| 1462 | */ | 1471 | */ |
| 1463 | #define CCID 0x2180 | 1472 | #define CCID 0x2180 |
| 1464 | #define CCID_EN (1<<0) | 1473 | #define CCID_EN (1<<0) |
| 1474 | #define CXT_SIZE 0x21a0 | ||
| 1475 | #define GEN6_CXT_POWER_SIZE(cxt_reg) ((cxt_reg >> 24) & 0x3f) | ||
| 1476 | #define GEN6_CXT_RING_SIZE(cxt_reg) ((cxt_reg >> 18) & 0x3f) | ||
| 1477 | #define GEN6_CXT_RENDER_SIZE(cxt_reg) ((cxt_reg >> 12) & 0x3f) | ||
| 1478 | #define GEN6_CXT_EXTENDED_SIZE(cxt_reg) ((cxt_reg >> 6) & 0x3f) | ||
| 1479 | #define GEN6_CXT_PIPELINE_SIZE(cxt_reg) ((cxt_reg >> 0) & 0x3f) | ||
| 1480 | #define GEN6_CXT_TOTAL_SIZE(cxt_reg) (GEN6_CXT_POWER_SIZE(cxt_reg) + \ | ||
| 1481 | GEN6_CXT_RING_SIZE(cxt_reg) + \ | ||
| 1482 | GEN6_CXT_RENDER_SIZE(cxt_reg) + \ | ||
| 1483 | GEN6_CXT_EXTENDED_SIZE(cxt_reg) + \ | ||
| 1484 | GEN6_CXT_PIPELINE_SIZE(cxt_reg)) | ||
| 1485 | #define GEN7_CTX_SIZE 0x21a8 | ||
| 1486 | #define GEN7_CTX_RENDER_SIZE(ctx_reg) ((ctx_reg >> 16) & 0x3f) | ||
| 1487 | #define GEN7_CTX_EXTENDED_SIZE(ctx_reg) ((ctx_reg >> 9) & 0x7f) | ||
| 1488 | #define GEN7_CTX_GT1_SIZE(ctx_reg) ((ctx_reg >> 6) & 0x7) | ||
| 1489 | #define GEN7_CTX_VFSTATE_SIZE(ctx_reg) ((ctx_reg >> 0) & 0x3f) | ||
| 1490 | #define GEN7_CTX_TOTAL_SIZE(ctx_reg) (GEN7_CTX_RENDER_SIZE(ctx_reg) + \ | ||
| 1491 | GEN7_CTX_EXTENDED_SIZE(ctx_reg) + \ | ||
| 1492 | GEN7_CTX_GT1_SIZE(ctx_reg) + \ | ||
| 1493 | GEN7_CTX_VFSTATE_SIZE(ctx_reg)) | ||
| 1494 | |||
| 1465 | /* | 1495 | /* |
| 1466 | * Overlay regs | 1496 | * Overlay regs |
| 1467 | */ | 1497 | */ |
| @@ -1566,20 +1596,34 @@ | |||
| 1566 | #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) | 1596 | #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) |
| 1567 | 1597 | ||
| 1568 | #define PORT_HOTPLUG_STAT 0x61114 | 1598 | #define PORT_HOTPLUG_STAT 0x61114 |
| 1569 | #define HDMIB_HOTPLUG_INT_STATUS (1 << 29) | 1599 | /* HDMI/DP bits are gen4+ */ |
| 1570 | #define DPB_HOTPLUG_INT_STATUS (1 << 29) | 1600 | #define DPB_HOTPLUG_LIVE_STATUS (1 << 29) |
| 1571 | #define HDMIC_HOTPLUG_INT_STATUS (1 << 28) | 1601 | #define DPC_HOTPLUG_LIVE_STATUS (1 << 28) |
| 1572 | #define DPC_HOTPLUG_INT_STATUS (1 << 28) | 1602 | #define DPD_HOTPLUG_LIVE_STATUS (1 << 27) |
| 1573 | #define HDMID_HOTPLUG_INT_STATUS (1 << 27) | 1603 | #define DPD_HOTPLUG_INT_STATUS (3 << 21) |
| 1574 | #define DPD_HOTPLUG_INT_STATUS (1 << 27) | 1604 | #define DPC_HOTPLUG_INT_STATUS (3 << 19) |
| 1605 | #define DPB_HOTPLUG_INT_STATUS (3 << 17) | ||
| 1606 | /* HDMI bits are shared with the DP bits */ | ||
| 1607 | #define HDMIB_HOTPLUG_LIVE_STATUS (1 << 29) | ||
| 1608 | #define HDMIC_HOTPLUG_LIVE_STATUS (1 << 28) | ||
| 1609 | #define HDMID_HOTPLUG_LIVE_STATUS (1 << 27) | ||
| 1610 | #define HDMID_HOTPLUG_INT_STATUS (3 << 21) | ||
| 1611 | #define HDMIC_HOTPLUG_INT_STATUS (3 << 19) | ||
| 1612 | #define HDMIB_HOTPLUG_INT_STATUS (3 << 17) | ||
| 1613 | /* CRT/TV common between gen3+ */ | ||
| 1575 | #define CRT_HOTPLUG_INT_STATUS (1 << 11) | 1614 | #define CRT_HOTPLUG_INT_STATUS (1 << 11) |
| 1576 | #define TV_HOTPLUG_INT_STATUS (1 << 10) | 1615 | #define TV_HOTPLUG_INT_STATUS (1 << 10) |
| 1577 | #define CRT_HOTPLUG_MONITOR_MASK (3 << 8) | 1616 | #define CRT_HOTPLUG_MONITOR_MASK (3 << 8) |
| 1578 | #define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) | 1617 | #define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) |
| 1579 | #define CRT_HOTPLUG_MONITOR_MONO (2 << 8) | 1618 | #define CRT_HOTPLUG_MONITOR_MONO (2 << 8) |
| 1580 | #define CRT_HOTPLUG_MONITOR_NONE (0 << 8) | 1619 | #define CRT_HOTPLUG_MONITOR_NONE (0 << 8) |
| 1581 | #define SDVOC_HOTPLUG_INT_STATUS (1 << 7) | 1620 | /* SDVO is different across gen3/4 */ |
| 1582 | #define SDVOB_HOTPLUG_INT_STATUS (1 << 6) | 1621 | #define SDVOC_HOTPLUG_INT_STATUS_G4X (1 << 3) |
| 1622 | #define SDVOB_HOTPLUG_INT_STATUS_G4X (1 << 2) | ||
| 1623 | #define SDVOC_HOTPLUG_INT_STATUS_I965 (3 << 4) | ||
| 1624 | #define SDVOB_HOTPLUG_INT_STATUS_I965 (3 << 2) | ||
| 1625 | #define SDVOC_HOTPLUG_INT_STATUS_I915 (1 << 7) | ||
| 1626 | #define SDVOB_HOTPLUG_INT_STATUS_I915 (1 << 6) | ||
| 1583 | 1627 | ||
| 1584 | /* SDVO port control */ | 1628 | /* SDVO port control */ |
| 1585 | #define SDVOB 0x61140 | 1629 | #define SDVOB 0x61140 |
| @@ -1711,8 +1755,10 @@ | |||
| 1711 | #define VIDEO_DIP_PORT_C (2 << 29) | 1755 | #define VIDEO_DIP_PORT_C (2 << 29) |
| 1712 | #define VIDEO_DIP_PORT_D (3 << 29) | 1756 | #define VIDEO_DIP_PORT_D (3 << 29) |
| 1713 | #define VIDEO_DIP_PORT_MASK (3 << 29) | 1757 | #define VIDEO_DIP_PORT_MASK (3 << 29) |
| 1758 | #define VIDEO_DIP_ENABLE_GCP (1 << 25) | ||
| 1714 | #define VIDEO_DIP_ENABLE_AVI (1 << 21) | 1759 | #define VIDEO_DIP_ENABLE_AVI (1 << 21) |
| 1715 | #define VIDEO_DIP_ENABLE_VENDOR (2 << 21) | 1760 | #define VIDEO_DIP_ENABLE_VENDOR (2 << 21) |
| 1761 | #define VIDEO_DIP_ENABLE_GAMUT (4 << 21) | ||
| 1716 | #define VIDEO_DIP_ENABLE_SPD (8 << 21) | 1762 | #define VIDEO_DIP_ENABLE_SPD (8 << 21) |
| 1717 | #define VIDEO_DIP_SELECT_AVI (0 << 19) | 1763 | #define VIDEO_DIP_SELECT_AVI (0 << 19) |
| 1718 | #define VIDEO_DIP_SELECT_VENDOR (1 << 19) | 1764 | #define VIDEO_DIP_SELECT_VENDOR (1 << 19) |
| @@ -1723,7 +1769,11 @@ | |||
| 1723 | #define VIDEO_DIP_FREQ_2VSYNC (2 << 16) | 1769 | #define VIDEO_DIP_FREQ_2VSYNC (2 << 16) |
| 1724 | #define VIDEO_DIP_FREQ_MASK (3 << 16) | 1770 | #define VIDEO_DIP_FREQ_MASK (3 << 16) |
| 1725 | /* HSW and later: */ | 1771 | /* HSW and later: */ |
| 1772 | #define VIDEO_DIP_ENABLE_VSC_HSW (1 << 20) | ||
| 1773 | #define VIDEO_DIP_ENABLE_GCP_HSW (1 << 16) | ||
| 1726 | #define VIDEO_DIP_ENABLE_AVI_HSW (1 << 12) | 1774 | #define VIDEO_DIP_ENABLE_AVI_HSW (1 << 12) |
| 1775 | #define VIDEO_DIP_ENABLE_VS_HSW (1 << 8) | ||
| 1776 | #define VIDEO_DIP_ENABLE_GMP_HSW (1 << 4) | ||
| 1727 | #define VIDEO_DIP_ENABLE_SPD_HSW (1 << 0) | 1777 | #define VIDEO_DIP_ENABLE_SPD_HSW (1 << 0) |
| 1728 | 1778 | ||
| 1729 | /* Panel power sequencing */ | 1779 | /* Panel power sequencing */ |
| @@ -1795,18 +1845,35 @@ | |||
| 1795 | #define PFIT_AUTO_RATIOS 0x61238 | 1845 | #define PFIT_AUTO_RATIOS 0x61238 |
| 1796 | 1846 | ||
| 1797 | /* Backlight control */ | 1847 | /* Backlight control */ |
| 1798 | #define BLC_PWM_CTL 0x61254 | ||
| 1799 | #define BACKLIGHT_MODULATION_FREQ_SHIFT (17) | ||
| 1800 | #define BLC_PWM_CTL2 0x61250 /* 965+ only */ | 1848 | #define BLC_PWM_CTL2 0x61250 /* 965+ only */ |
| 1801 | #define BLM_COMBINATION_MODE (1 << 30) | 1849 | #define BLM_PWM_ENABLE (1 << 31) |
| 1850 | #define BLM_COMBINATION_MODE (1 << 30) /* gen4 only */ | ||
| 1851 | #define BLM_PIPE_SELECT (1 << 29) | ||
| 1852 | #define BLM_PIPE_SELECT_IVB (3 << 29) | ||
| 1853 | #define BLM_PIPE_A (0 << 29) | ||
| 1854 | #define BLM_PIPE_B (1 << 29) | ||
| 1855 | #define BLM_PIPE_C (2 << 29) /* ivb + */ | ||
| 1856 | #define BLM_PIPE(pipe) ((pipe) << 29) | ||
| 1857 | #define BLM_POLARITY_I965 (1 << 28) /* gen4 only */ | ||
| 1858 | #define BLM_PHASE_IN_INTERUPT_STATUS (1 << 26) | ||
| 1859 | #define BLM_PHASE_IN_ENABLE (1 << 25) | ||
| 1860 | #define BLM_PHASE_IN_INTERUPT_ENABL (1 << 24) | ||
| 1861 | #define BLM_PHASE_IN_TIME_BASE_SHIFT (16) | ||
| 1862 | #define BLM_PHASE_IN_TIME_BASE_MASK (0xff << 16) | ||
| 1863 | #define BLM_PHASE_IN_COUNT_SHIFT (8) | ||
| 1864 | #define BLM_PHASE_IN_COUNT_MASK (0xff << 8) | ||
| 1865 | #define BLM_PHASE_IN_INCR_SHIFT (0) | ||
| 1866 | #define BLM_PHASE_IN_INCR_MASK (0xff << 0) | ||
| 1867 | #define BLC_PWM_CTL 0x61254 | ||
| 1802 | /* | 1868 | /* |
| 1803 | * This is the most significant 15 bits of the number of backlight cycles in a | 1869 | * This is the most significant 15 bits of the number of backlight cycles in a |
| 1804 | * complete cycle of the modulated backlight control. | 1870 | * complete cycle of the modulated backlight control. |
| 1805 | * | 1871 | * |
| 1806 | * The actual value is this field multiplied by two. | 1872 | * The actual value is this field multiplied by two. |
| 1807 | */ | 1873 | */ |
| 1808 | #define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) | 1874 | #define BACKLIGHT_MODULATION_FREQ_SHIFT (17) |
| 1809 | #define BLM_LEGACY_MODE (1 << 16) | 1875 | #define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) |
| 1876 | #define BLM_LEGACY_MODE (1 << 16) /* gen2 only */ | ||
| 1810 | /* | 1877 | /* |
| 1811 | * This is the number of cycles out of the backlight modulation cycle for which | 1878 | * This is the number of cycles out of the backlight modulation cycle for which |
| 1812 | * the backlight is on. | 1879 | * the backlight is on. |
| @@ -1816,9 +1883,24 @@ | |||
| 1816 | */ | 1883 | */ |
| 1817 | #define BACKLIGHT_DUTY_CYCLE_SHIFT (0) | 1884 | #define BACKLIGHT_DUTY_CYCLE_SHIFT (0) |
| 1818 | #define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) | 1885 | #define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) |
| 1886 | #define BACKLIGHT_DUTY_CYCLE_MASK_PNV (0xfffe) | ||
| 1887 | #define BLM_POLARITY_PNV (1 << 0) /* pnv only */ | ||
| 1819 | 1888 | ||
| 1820 | #define BLC_HIST_CTL 0x61260 | 1889 | #define BLC_HIST_CTL 0x61260 |
| 1821 | 1890 | ||
| 1891 | /* New registers for PCH-split platforms. Safe where new bits show up, the | ||
| 1892 | * register layout machtes with gen4 BLC_PWM_CTL[12]. */ | ||
| 1893 | #define BLC_PWM_CPU_CTL2 0x48250 | ||
| 1894 | #define BLC_PWM_CPU_CTL 0x48254 | ||
| 1895 | |||
| 1896 | /* PCH CTL1 is totally different, all but the below bits are reserved. CTL2 is | ||
| 1897 | * like the normal CTL from gen4 and earlier. Hooray for confusing naming. */ | ||
| 1898 | #define BLC_PWM_PCH_CTL1 0xc8250 | ||
| 1899 | #define BLM_PCH_PWM_ENABLE (1 << 30) | ||
| 1900 | #define BLM_PCH_OVERRIDE_ENABLE (1 << 30) | ||
| 1901 | #define BLM_PCH_POLARITY (1 << 29) | ||
| 1902 | #define BLC_PWM_PCH_CTL2 0xc8254 | ||
| 1903 | |||
| 1822 | /* TV port control */ | 1904 | /* TV port control */ |
| 1823 | #define TV_CTL 0x68000 | 1905 | #define TV_CTL 0x68000 |
| 1824 | /** Enables the TV encoder */ | 1906 | /** Enables the TV encoder */ |
| @@ -2583,13 +2665,13 @@ | |||
| 2583 | #define PIPESTAT(pipe) _PIPE(pipe, _PIPEASTAT, _PIPEBSTAT) | 2665 | #define PIPESTAT(pipe) _PIPE(pipe, _PIPEASTAT, _PIPEBSTAT) |
| 2584 | 2666 | ||
| 2585 | #define VLV_DPFLIPSTAT 0x70028 | 2667 | #define VLV_DPFLIPSTAT 0x70028 |
| 2586 | #define PIPEB_LINE_COMPARE_STATUS (1<<29) | 2668 | #define PIPEB_LINE_COMPARE_INT_EN (1<<29) |
| 2587 | #define PIPEB_HLINE_INT_EN (1<<28) | 2669 | #define PIPEB_HLINE_INT_EN (1<<28) |
| 2588 | #define PIPEB_VBLANK_INT_EN (1<<27) | 2670 | #define PIPEB_VBLANK_INT_EN (1<<27) |
| 2589 | #define SPRITED_FLIPDONE_INT_EN (1<<26) | 2671 | #define SPRITED_FLIPDONE_INT_EN (1<<26) |
| 2590 | #define SPRITEC_FLIPDONE_INT_EN (1<<25) | 2672 | #define SPRITEC_FLIPDONE_INT_EN (1<<25) |
| 2591 | #define PLANEB_FLIPDONE_INT_EN (1<<24) | 2673 | #define PLANEB_FLIPDONE_INT_EN (1<<24) |
| 2592 | #define PIPEA_LINE_COMPARE_STATUS (1<<21) | 2674 | #define PIPEA_LINE_COMPARE_INT_EN (1<<21) |
| 2593 | #define PIPEA_HLINE_INT_EN (1<<20) | 2675 | #define PIPEA_HLINE_INT_EN (1<<20) |
| 2594 | #define PIPEA_VBLANK_INT_EN (1<<19) | 2676 | #define PIPEA_VBLANK_INT_EN (1<<19) |
| 2595 | #define SPRITEB_FLIPDONE_INT_EN (1<<18) | 2677 | #define SPRITEB_FLIPDONE_INT_EN (1<<18) |
| @@ -2897,13 +2979,14 @@ | |||
| 2897 | #define DSPSIZE(plane) _PIPE(plane, _DSPASIZE, _DSPBSIZE) | 2979 | #define DSPSIZE(plane) _PIPE(plane, _DSPASIZE, _DSPBSIZE) |
| 2898 | #define DSPSURF(plane) _PIPE(plane, _DSPASURF, _DSPBSURF) | 2980 | #define DSPSURF(plane) _PIPE(plane, _DSPASURF, _DSPBSURF) |
| 2899 | #define DSPTILEOFF(plane) _PIPE(plane, _DSPATILEOFF, _DSPBTILEOFF) | 2981 | #define DSPTILEOFF(plane) _PIPE(plane, _DSPATILEOFF, _DSPBTILEOFF) |
| 2982 | #define DSPLINOFF(plane) DSPADDR(plane) | ||
| 2900 | 2983 | ||
| 2901 | /* Display/Sprite base address macros */ | 2984 | /* Display/Sprite base address macros */ |
| 2902 | #define DISP_BASEADDR_MASK (0xfffff000) | 2985 | #define DISP_BASEADDR_MASK (0xfffff000) |
| 2903 | #define I915_LO_DISPBASE(val) (val & ~DISP_BASEADDR_MASK) | 2986 | #define I915_LO_DISPBASE(val) (val & ~DISP_BASEADDR_MASK) |
| 2904 | #define I915_HI_DISPBASE(val) (val & DISP_BASEADDR_MASK) | 2987 | #define I915_HI_DISPBASE(val) (val & DISP_BASEADDR_MASK) |
| 2905 | #define I915_MODIFY_DISPBASE(reg, gfx_addr) \ | 2988 | #define I915_MODIFY_DISPBASE(reg, gfx_addr) \ |
| 2906 | (I915_WRITE(reg, gfx_addr | I915_LO_DISPBASE(I915_READ(reg)))) | 2989 | (I915_WRITE((reg), (gfx_addr) | I915_LO_DISPBASE(I915_READ(reg)))) |
| 2907 | 2990 | ||
| 2908 | /* VBIOS flags */ | 2991 | /* VBIOS flags */ |
| 2909 | #define SWF00 0x71410 | 2992 | #define SWF00 0x71410 |
| @@ -3771,6 +3854,9 @@ | |||
| 3771 | #define _FDI_RXA_TUSIZE2 0xf0038 | 3854 | #define _FDI_RXA_TUSIZE2 0xf0038 |
| 3772 | #define _FDI_RXB_TUSIZE1 0xf1030 | 3855 | #define _FDI_RXB_TUSIZE1 0xf1030 |
| 3773 | #define _FDI_RXB_TUSIZE2 0xf1038 | 3856 | #define _FDI_RXB_TUSIZE2 0xf1038 |
| 3857 | #define FDI_RX_TP1_TO_TP2_48 (2<<20) | ||
| 3858 | #define FDI_RX_TP1_TO_TP2_64 (3<<20) | ||
| 3859 | #define FDI_RX_FDI_DELAY_90 (0x90<<0) | ||
| 3774 | #define FDI_RX_MISC(pipe) _PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC) | 3860 | #define FDI_RX_MISC(pipe) _PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC) |
| 3775 | #define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE1, _FDI_RXB_TUSIZE1) | 3861 | #define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE1, _FDI_RXB_TUSIZE1) |
| 3776 | #define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE2, _FDI_RXB_TUSIZE2) | 3862 | #define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE2, _FDI_RXB_TUSIZE2) |
| @@ -3824,7 +3910,6 @@ | |||
| 3824 | #define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16) | 3910 | #define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16) |
| 3825 | 3911 | ||
| 3826 | /* or SDVOB */ | 3912 | /* or SDVOB */ |
| 3827 | #define VLV_HDMIB 0x61140 | ||
| 3828 | #define HDMIB 0xe1140 | 3913 | #define HDMIB 0xe1140 |
| 3829 | #define PORT_ENABLE (1 << 31) | 3914 | #define PORT_ENABLE (1 << 31) |
| 3830 | #define TRANSCODER(pipe) ((pipe) << 30) | 3915 | #define TRANSCODER(pipe) ((pipe) << 30) |
| @@ -3855,20 +3940,18 @@ | |||
| 3855 | #define PCH_LVDS 0xe1180 | 3940 | #define PCH_LVDS 0xe1180 |
| 3856 | #define LVDS_DETECTED (1 << 1) | 3941 | #define LVDS_DETECTED (1 << 1) |
| 3857 | 3942 | ||
| 3858 | #define BLC_PWM_CPU_CTL2 0x48250 | 3943 | /* vlv has 2 sets of panel control regs. */ |
| 3859 | #define PWM_ENABLE (1 << 31) | 3944 | #define PIPEA_PP_STATUS 0x61200 |
| 3860 | #define PWM_PIPE_A (0 << 29) | 3945 | #define PIPEA_PP_CONTROL 0x61204 |
| 3861 | #define PWM_PIPE_B (1 << 29) | 3946 | #define PIPEA_PP_ON_DELAYS 0x61208 |
| 3862 | #define BLC_PWM_CPU_CTL 0x48254 | 3947 | #define PIPEA_PP_OFF_DELAYS 0x6120c |
| 3948 | #define PIPEA_PP_DIVISOR 0x61210 | ||
| 3863 | 3949 | ||
| 3864 | #define BLC_PWM_PCH_CTL1 0xc8250 | 3950 | #define PIPEB_PP_STATUS 0x61300 |
| 3865 | #define PWM_PCH_ENABLE (1 << 31) | 3951 | #define PIPEB_PP_CONTROL 0x61304 |
| 3866 | #define PWM_POLARITY_ACTIVE_LOW (1 << 29) | 3952 | #define PIPEB_PP_ON_DELAYS 0x61308 |
| 3867 | #define PWM_POLARITY_ACTIVE_HIGH (0 << 29) | 3953 | #define PIPEB_PP_OFF_DELAYS 0x6130c |
| 3868 | #define PWM_POLARITY_ACTIVE_LOW2 (1 << 28) | 3954 | #define PIPEB_PP_DIVISOR 0x61310 |
| 3869 | #define PWM_POLARITY_ACTIVE_HIGH2 (0 << 28) | ||
| 3870 | |||
| 3871 | #define BLC_PWM_PCH_CTL2 0xc8254 | ||
| 3872 | 3955 | ||
| 3873 | #define PCH_PP_STATUS 0xc7200 | 3956 | #define PCH_PP_STATUS 0xc7200 |
| 3874 | #define PCH_PP_CONTROL 0xc7204 | 3957 | #define PCH_PP_CONTROL 0xc7204 |
| @@ -3992,6 +4075,7 @@ | |||
| 3992 | #define FORCEWAKE 0xA18C | 4075 | #define FORCEWAKE 0xA18C |
| 3993 | #define FORCEWAKE_VLV 0x1300b0 | 4076 | #define FORCEWAKE_VLV 0x1300b0 |
| 3994 | #define FORCEWAKE_ACK_VLV 0x1300b4 | 4077 | #define FORCEWAKE_ACK_VLV 0x1300b4 |
| 4078 | #define FORCEWAKE_ACK_HSW 0x130044 | ||
| 3995 | #define FORCEWAKE_ACK 0x130090 | 4079 | #define FORCEWAKE_ACK 0x130090 |
| 3996 | #define FORCEWAKE_MT 0xa188 /* multi-threaded */ | 4080 | #define FORCEWAKE_MT 0xa188 /* multi-threaded */ |
| 3997 | #define FORCEWAKE_MT_ACK 0x130040 | 4081 | #define FORCEWAKE_MT_ACK 0x130040 |
| @@ -4012,10 +4096,15 @@ | |||
| 4012 | # define GEN6_CSUNIT_CLOCK_GATE_DISABLE (1 << 7) | 4096 | # define GEN6_CSUNIT_CLOCK_GATE_DISABLE (1 << 7) |
| 4013 | 4097 | ||
| 4014 | #define GEN6_UCGCTL2 0x9404 | 4098 | #define GEN6_UCGCTL2 0x9404 |
| 4099 | # define GEN7_VDSUNIT_CLOCK_GATE_DISABLE (1 << 30) | ||
| 4100 | # define GEN7_TDLUNIT_CLOCK_GATE_DISABLE (1 << 22) | ||
| 4015 | # define GEN6_RCZUNIT_CLOCK_GATE_DISABLE (1 << 13) | 4101 | # define GEN6_RCZUNIT_CLOCK_GATE_DISABLE (1 << 13) |
| 4016 | # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) | 4102 | # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) |
| 4017 | # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11) | 4103 | # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11) |
| 4018 | 4104 | ||
| 4105 | #define GEN7_UCGCTL4 0x940c | ||
| 4106 | #define GEN7_L3BANK2X_CLOCK_GATE_DISABLE (1<<25) | ||
| 4107 | |||
| 4019 | #define GEN6_RPNSWREQ 0xA008 | 4108 | #define GEN6_RPNSWREQ 0xA008 |
| 4020 | #define GEN6_TURBO_DISABLE (1<<31) | 4109 | #define GEN6_TURBO_DISABLE (1<<31) |
| 4021 | #define GEN6_FREQUENCY(x) ((x)<<25) | 4110 | #define GEN6_FREQUENCY(x) ((x)<<25) |
| @@ -4047,6 +4136,7 @@ | |||
| 4047 | #define GEN6_RP_UP_IDLE_MIN (0x1<<3) | 4136 | #define GEN6_RP_UP_IDLE_MIN (0x1<<3) |
| 4048 | #define GEN6_RP_UP_BUSY_AVG (0x2<<3) | 4137 | #define GEN6_RP_UP_BUSY_AVG (0x2<<3) |
| 4049 | #define GEN6_RP_UP_BUSY_CONT (0x4<<3) | 4138 | #define GEN6_RP_UP_BUSY_CONT (0x4<<3) |
| 4139 | #define GEN7_RP_DOWN_IDLE_AVG (0x2<<0) | ||
| 4050 | #define GEN6_RP_DOWN_IDLE_CONT (0x1<<0) | 4140 | #define GEN6_RP_DOWN_IDLE_CONT (0x1<<0) |
| 4051 | #define GEN6_RP_UP_THRESHOLD 0xA02C | 4141 | #define GEN6_RP_UP_THRESHOLD 0xA02C |
| 4052 | #define GEN6_RP_DOWN_THRESHOLD 0xA030 | 4142 | #define GEN6_RP_DOWN_THRESHOLD 0xA030 |
| @@ -4111,6 +4201,26 @@ | |||
| 4111 | #define GEN6_RC6 3 | 4201 | #define GEN6_RC6 3 |
| 4112 | #define GEN6_RC7 4 | 4202 | #define GEN6_RC7 4 |
| 4113 | 4203 | ||
| 4204 | #define GEN7_MISCCPCTL (0x9424) | ||
| 4205 | #define GEN7_DOP_CLOCK_GATE_ENABLE (1<<0) | ||
| 4206 | |||
| 4207 | /* IVYBRIDGE DPF */ | ||
| 4208 | #define GEN7_L3CDERRST1 0xB008 /* L3CD Error Status 1 */ | ||
| 4209 | #define GEN7_L3CDERRST1_ROW_MASK (0x7ff<<14) | ||
| 4210 | #define GEN7_PARITY_ERROR_VALID (1<<13) | ||
| 4211 | #define GEN7_L3CDERRST1_BANK_MASK (3<<11) | ||
| 4212 | #define GEN7_L3CDERRST1_SUBBANK_MASK (7<<8) | ||
| 4213 | #define GEN7_PARITY_ERROR_ROW(reg) \ | ||
| 4214 | ((reg & GEN7_L3CDERRST1_ROW_MASK) >> 14) | ||
| 4215 | #define GEN7_PARITY_ERROR_BANK(reg) \ | ||
| 4216 | ((reg & GEN7_L3CDERRST1_BANK_MASK) >> 11) | ||
| 4217 | #define GEN7_PARITY_ERROR_SUBBANK(reg) \ | ||
| 4218 | ((reg & GEN7_L3CDERRST1_SUBBANK_MASK) >> 8) | ||
| 4219 | #define GEN7_L3CDERRST1_ENABLE (1<<7) | ||
| 4220 | |||
| 4221 | #define GEN7_L3LOG_BASE 0xB070 | ||
| 4222 | #define GEN7_L3LOG_SIZE 0x80 | ||
| 4223 | |||
| 4114 | #define G4X_AUD_VID_DID 0x62020 | 4224 | #define G4X_AUD_VID_DID 0x62020 |
| 4115 | #define INTEL_AUDIO_DEVCL 0x808629FB | 4225 | #define INTEL_AUDIO_DEVCL 0x808629FB |
| 4116 | #define INTEL_AUDIO_DEVBLC 0x80862801 | 4226 | #define INTEL_AUDIO_DEVBLC 0x80862801 |
| @@ -4177,7 +4287,7 @@ | |||
| 4177 | PIPE_DDI_FUNC_CTL_B) | 4287 | PIPE_DDI_FUNC_CTL_B) |
| 4178 | #define PIPE_DDI_FUNC_ENABLE (1<<31) | 4288 | #define PIPE_DDI_FUNC_ENABLE (1<<31) |
| 4179 | /* Those bits are ignored by pipe EDP since it can only connect to DDI A */ | 4289 | /* Those bits are ignored by pipe EDP since it can only connect to DDI A */ |
| 4180 | #define PIPE_DDI_PORT_MASK (0xf<<28) | 4290 | #define PIPE_DDI_PORT_MASK (7<<28) |
| 4181 | #define PIPE_DDI_SELECT_PORT(x) ((x)<<28) | 4291 | #define PIPE_DDI_SELECT_PORT(x) ((x)<<28) |
| 4182 | #define PIPE_DDI_MODE_SELECT_HDMI (0<<24) | 4292 | #define PIPE_DDI_MODE_SELECT_HDMI (0<<24) |
| 4183 | #define PIPE_DDI_MODE_SELECT_DVI (1<<24) | 4293 | #define PIPE_DDI_MODE_SELECT_DVI (1<<24) |
| @@ -4335,7 +4445,7 @@ | |||
| 4335 | #define PIPE_WM_LINETIME_B 0x45274 | 4445 | #define PIPE_WM_LINETIME_B 0x45274 |
| 4336 | #define PIPE_WM_LINETIME(pipe) _PIPE(pipe, \ | 4446 | #define PIPE_WM_LINETIME(pipe) _PIPE(pipe, \ |
| 4337 | PIPE_WM_LINETIME_A, \ | 4447 | PIPE_WM_LINETIME_A, \ |
| 4338 | PIPE_WM_LINETIME_A) | 4448 | PIPE_WM_LINETIME_B) |
| 4339 | #define PIPE_WM_LINETIME_MASK (0x1ff) | 4449 | #define PIPE_WM_LINETIME_MASK (0x1ff) |
| 4340 | #define PIPE_WM_LINETIME_TIME(x) ((x)) | 4450 | #define PIPE_WM_LINETIME_TIME(x) ((x)) |
| 4341 | #define PIPE_WM_LINETIME_IPS_LINETIME_MASK (0x1ff<<16) | 4451 | #define PIPE_WM_LINETIME_IPS_LINETIME_MASK (0x1ff<<16) |
| @@ -4347,4 +4457,9 @@ | |||
| 4347 | #define SFUSE_STRAP_DDIC_DETECTED (1<<1) | 4457 | #define SFUSE_STRAP_DDIC_DETECTED (1<<1) |
| 4348 | #define SFUSE_STRAP_DDID_DETECTED (1<<0) | 4458 | #define SFUSE_STRAP_DDID_DETECTED (1<<0) |
| 4349 | 4459 | ||
| 4460 | #define WM_DBG 0x45280 | ||
| 4461 | #define WM_DBG_DISALLOW_MULTIPLE_LP (1<<0) | ||
| 4462 | #define WM_DBG_DISALLOW_MAXFIFO (1<<1) | ||
| 4463 | #define WM_DBG_DISALLOW_SPRITE (1<<2) | ||
| 4464 | |||
| 4350 | #endif /* _I915_REG_H_ */ | 4465 | #endif /* _I915_REG_H_ */ |
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index a748e5cabe14..4776ccf1b3cd 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c | |||
| @@ -828,10 +828,7 @@ int i915_save_state(struct drm_device *dev) | |||
| 828 | dev_priv->saveIMR = I915_READ(IMR); | 828 | dev_priv->saveIMR = I915_READ(IMR); |
| 829 | } | 829 | } |
| 830 | 830 | ||
| 831 | if (IS_IRONLAKE_M(dev)) | 831 | intel_disable_gt_powersave(dev); |
| 832 | ironlake_disable_drps(dev); | ||
| 833 | if (INTEL_INFO(dev)->gen >= 6) | ||
| 834 | gen6_disable_rps(dev); | ||
| 835 | 832 | ||
| 836 | /* Cache mode state */ | 833 | /* Cache mode state */ |
| 837 | dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); | 834 | dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); |
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 79f83445afa0..2f5388af8df9 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
| 30 | #include <linux/stat.h> | 30 | #include <linux/stat.h> |
| 31 | #include <linux/sysfs.h> | 31 | #include <linux/sysfs.h> |
| 32 | #include "intel_drv.h" | ||
| 32 | #include "i915_drv.h" | 33 | #include "i915_drv.h" |
| 33 | 34 | ||
| 34 | static u32 calc_residency(struct drm_device *dev, const u32 reg) | 35 | static u32 calc_residency(struct drm_device *dev, const u32 reg) |
| @@ -92,20 +93,134 @@ static struct attribute_group rc6_attr_group = { | |||
| 92 | .attrs = rc6_attrs | 93 | .attrs = rc6_attrs |
| 93 | }; | 94 | }; |
| 94 | 95 | ||
| 95 | void i915_setup_sysfs(struct drm_device *dev) | 96 | static int l3_access_valid(struct drm_device *dev, loff_t offset) |
| 97 | { | ||
| 98 | if (!IS_IVYBRIDGE(dev)) | ||
| 99 | return -EPERM; | ||
| 100 | |||
| 101 | if (offset % 4 != 0) | ||
| 102 | return -EINVAL; | ||
| 103 | |||
| 104 | if (offset >= GEN7_L3LOG_SIZE) | ||
| 105 | return -ENXIO; | ||
| 106 | |||
| 107 | return 0; | ||
| 108 | } | ||
| 109 | |||
| 110 | static ssize_t | ||
| 111 | i915_l3_read(struct file *filp, struct kobject *kobj, | ||
| 112 | struct bin_attribute *attr, char *buf, | ||
| 113 | loff_t offset, size_t count) | ||
| 114 | { | ||
| 115 | struct device *dev = container_of(kobj, struct device, kobj); | ||
| 116 | struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); | ||
| 117 | struct drm_device *drm_dev = dminor->dev; | ||
| 118 | struct drm_i915_private *dev_priv = drm_dev->dev_private; | ||
| 119 | uint32_t misccpctl; | ||
| 120 | int i, ret; | ||
| 121 | |||
| 122 | ret = l3_access_valid(drm_dev, offset); | ||
| 123 | if (ret) | ||
| 124 | return ret; | ||
| 125 | |||
| 126 | ret = i915_mutex_lock_interruptible(drm_dev); | ||
| 127 | if (ret) | ||
| 128 | return ret; | ||
| 129 | |||
| 130 | misccpctl = I915_READ(GEN7_MISCCPCTL); | ||
| 131 | I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); | ||
| 132 | |||
| 133 | for (i = offset; count >= 4 && i < GEN7_L3LOG_SIZE; i += 4, count -= 4) | ||
| 134 | *((uint32_t *)(&buf[i])) = I915_READ(GEN7_L3LOG_BASE + i); | ||
| 135 | |||
| 136 | I915_WRITE(GEN7_MISCCPCTL, misccpctl); | ||
| 137 | |||
| 138 | mutex_unlock(&drm_dev->struct_mutex); | ||
| 139 | |||
| 140 | return i - offset; | ||
| 141 | } | ||
| 142 | |||
| 143 | static ssize_t | ||
| 144 | i915_l3_write(struct file *filp, struct kobject *kobj, | ||
| 145 | struct bin_attribute *attr, char *buf, | ||
| 146 | loff_t offset, size_t count) | ||
| 96 | { | 147 | { |
| 148 | struct device *dev = container_of(kobj, struct device, kobj); | ||
| 149 | struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); | ||
| 150 | struct drm_device *drm_dev = dminor->dev; | ||
| 151 | struct drm_i915_private *dev_priv = drm_dev->dev_private; | ||
| 152 | u32 *temp = NULL; /* Just here to make handling failures easy */ | ||
| 97 | int ret; | 153 | int ret; |
| 98 | 154 | ||
| 99 | /* ILK doesn't have any residency information */ | 155 | ret = l3_access_valid(drm_dev, offset); |
| 100 | if (INTEL_INFO(dev)->gen < 6) | 156 | if (ret) |
| 101 | return; | 157 | return ret; |
| 102 | 158 | ||
| 103 | ret = sysfs_merge_group(&dev->primary->kdev.kobj, &rc6_attr_group); | 159 | ret = i915_mutex_lock_interruptible(drm_dev); |
| 104 | if (ret) | 160 | if (ret) |
| 105 | DRM_ERROR("sysfs setup failed\n"); | 161 | return ret; |
| 162 | |||
| 163 | if (!dev_priv->mm.l3_remap_info) { | ||
| 164 | temp = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL); | ||
| 165 | if (!temp) { | ||
| 166 | mutex_unlock(&drm_dev->struct_mutex); | ||
| 167 | return -ENOMEM; | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | ret = i915_gpu_idle(drm_dev); | ||
| 172 | if (ret) { | ||
| 173 | kfree(temp); | ||
| 174 | mutex_unlock(&drm_dev->struct_mutex); | ||
| 175 | return ret; | ||
| 176 | } | ||
| 177 | |||
| 178 | /* TODO: Ideally we really want a GPU reset here to make sure errors | ||
| 179 | * aren't propagated. Since I cannot find a stable way to reset the GPU | ||
| 180 | * at this point it is left as a TODO. | ||
| 181 | */ | ||
| 182 | if (temp) | ||
| 183 | dev_priv->mm.l3_remap_info = temp; | ||
| 184 | |||
| 185 | memcpy(dev_priv->mm.l3_remap_info + (offset/4), | ||
| 186 | buf + (offset/4), | ||
| 187 | count); | ||
| 188 | |||
| 189 | i915_gem_l3_remap(drm_dev); | ||
| 190 | |||
| 191 | mutex_unlock(&drm_dev->struct_mutex); | ||
| 192 | |||
| 193 | return count; | ||
| 194 | } | ||
| 195 | |||
| 196 | static struct bin_attribute dpf_attrs = { | ||
| 197 | .attr = {.name = "l3_parity", .mode = (S_IRUSR | S_IWUSR)}, | ||
| 198 | .size = GEN7_L3LOG_SIZE, | ||
| 199 | .read = i915_l3_read, | ||
| 200 | .write = i915_l3_write, | ||
| 201 | .mmap = NULL | ||
| 202 | }; | ||
| 203 | |||
| 204 | void i915_setup_sysfs(struct drm_device *dev) | ||
| 205 | { | ||
| 206 | int ret; | ||
| 207 | |||
| 208 | if (INTEL_INFO(dev)->gen >= 6) { | ||
| 209 | ret = sysfs_merge_group(&dev->primary->kdev.kobj, | ||
| 210 | &rc6_attr_group); | ||
| 211 | if (ret) | ||
| 212 | DRM_ERROR("RC6 residency sysfs setup failed\n"); | ||
| 213 | } | ||
| 214 | |||
| 215 | if (IS_IVYBRIDGE(dev)) { | ||
| 216 | ret = device_create_bin_file(&dev->primary->kdev, &dpf_attrs); | ||
| 217 | if (ret) | ||
| 218 | DRM_ERROR("l3 parity sysfs setup failed\n"); | ||
| 219 | } | ||
| 106 | } | 220 | } |
| 107 | 221 | ||
| 108 | void i915_teardown_sysfs(struct drm_device *dev) | 222 | void i915_teardown_sysfs(struct drm_device *dev) |
| 109 | { | 223 | { |
| 224 | device_remove_bin_file(&dev->primary->kdev, &dpf_attrs); | ||
| 110 | sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group); | 225 | sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group); |
| 111 | } | 226 | } |
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index dac7bba4d9da..fe90b3a84a6d 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h | |||
| @@ -311,9 +311,33 @@ DEFINE_EVENT(i915_gem_request, i915_gem_request_retire, | |||
| 311 | TP_ARGS(ring, seqno) | 311 | TP_ARGS(ring, seqno) |
| 312 | ); | 312 | ); |
| 313 | 313 | ||
| 314 | DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_begin, | 314 | TRACE_EVENT(i915_gem_request_wait_begin, |
| 315 | TP_PROTO(struct intel_ring_buffer *ring, u32 seqno), | 315 | TP_PROTO(struct intel_ring_buffer *ring, u32 seqno), |
| 316 | TP_ARGS(ring, seqno) | 316 | TP_ARGS(ring, seqno), |
| 317 | |||
| 318 | TP_STRUCT__entry( | ||
| 319 | __field(u32, dev) | ||
| 320 | __field(u32, ring) | ||
| 321 | __field(u32, seqno) | ||
| 322 | __field(bool, blocking) | ||
| 323 | ), | ||
| 324 | |||
| 325 | /* NB: the blocking information is racy since mutex_is_locked | ||
| 326 | * doesn't check that the current thread holds the lock. The only | ||
| 327 | * other option would be to pass the boolean information of whether | ||
| 328 | * or not the class was blocking down through the stack which is | ||
| 329 | * less desirable. | ||
| 330 | */ | ||
| 331 | TP_fast_assign( | ||
| 332 | __entry->dev = ring->dev->primary->index; | ||
| 333 | __entry->ring = ring->id; | ||
| 334 | __entry->seqno = seqno; | ||
| 335 | __entry->blocking = mutex_is_locked(&ring->dev->struct_mutex); | ||
| 336 | ), | ||
| 337 | |||
| 338 | TP_printk("dev=%u, ring=%u, seqno=%u, blocking=%s", | ||
| 339 | __entry->dev, __entry->ring, __entry->seqno, | ||
| 340 | __entry->blocking ? "yes (NB)" : "no") | ||
| 317 | ); | 341 | ); |
| 318 | 342 | ||
| 319 | DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_end, | 343 | DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_end, |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 353459362f6f..8c6074154bf6 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
| @@ -692,7 +692,7 @@ static const struct dmi_system_id intel_no_opregion_vbt[] = { | |||
| 692 | * | 692 | * |
| 693 | * Returns 0 on success, nonzero on failure. | 693 | * Returns 0 on success, nonzero on failure. |
| 694 | */ | 694 | */ |
| 695 | bool | 695 | int |
| 696 | intel_parse_bios(struct drm_device *dev) | 696 | intel_parse_bios(struct drm_device *dev) |
| 697 | { | 697 | { |
| 698 | struct drm_i915_private *dev_priv = dev->dev_private; | 698 | struct drm_i915_private *dev_priv = dev->dev_private; |
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index dbda6e3bdf07..31c2107e7825 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h | |||
| @@ -476,7 +476,7 @@ struct bdb_edp { | |||
| 476 | } __attribute__ ((packed)); | 476 | } __attribute__ ((packed)); |
| 477 | 477 | ||
| 478 | void intel_setup_bios(struct drm_device *dev); | 478 | void intel_setup_bios(struct drm_device *dev); |
| 479 | bool intel_parse_bios(struct drm_device *dev); | 479 | int intel_parse_bios(struct drm_device *dev); |
| 480 | 480 | ||
| 481 | /* | 481 | /* |
| 482 | * Driver<->VBIOS interaction occurs through scratch bits in | 482 | * Driver<->VBIOS interaction occurs through scratch bits in |
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 75a70c46ef1b..48e3b76e0ab2 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
| @@ -88,6 +88,9 @@ static void gmch_crt_dpms(struct drm_encoder *encoder, int mode) | |||
| 88 | temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); | 88 | temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); |
| 89 | temp &= ~ADPA_DAC_ENABLE; | 89 | temp &= ~ADPA_DAC_ENABLE; |
| 90 | 90 | ||
| 91 | if (IS_VALLEYVIEW(dev) && mode != DRM_MODE_DPMS_ON) | ||
| 92 | mode = DRM_MODE_DPMS_OFF; | ||
| 93 | |||
| 91 | switch (mode) { | 94 | switch (mode) { |
| 92 | case DRM_MODE_DPMS_ON: | 95 | case DRM_MODE_DPMS_ON: |
| 93 | temp |= ADPA_DAC_ENABLE; | 96 | temp |= ADPA_DAC_ENABLE; |
| @@ -129,7 +132,7 @@ static int intel_crt_mode_valid(struct drm_connector *connector, | |||
| 129 | } | 132 | } |
| 130 | 133 | ||
| 131 | static bool intel_crt_mode_fixup(struct drm_encoder *encoder, | 134 | static bool intel_crt_mode_fixup(struct drm_encoder *encoder, |
| 132 | struct drm_display_mode *mode, | 135 | const struct drm_display_mode *mode, |
| 133 | struct drm_display_mode *adjusted_mode) | 136 | struct drm_display_mode *adjusted_mode) |
| 134 | { | 137 | { |
| 135 | return true; | 138 | return true; |
| @@ -230,6 +233,42 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) | |||
| 230 | return ret; | 233 | return ret; |
| 231 | } | 234 | } |
| 232 | 235 | ||
| 236 | static bool valleyview_crt_detect_hotplug(struct drm_connector *connector) | ||
| 237 | { | ||
| 238 | struct drm_device *dev = connector->dev; | ||
| 239 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 240 | u32 adpa; | ||
| 241 | bool ret; | ||
| 242 | u32 save_adpa; | ||
| 243 | |||
| 244 | save_adpa = adpa = I915_READ(ADPA); | ||
| 245 | DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa); | ||
| 246 | |||
| 247 | adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER; | ||
| 248 | |||
| 249 | I915_WRITE(ADPA, adpa); | ||
| 250 | |||
| 251 | if (wait_for((I915_READ(ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0, | ||
| 252 | 1000)) { | ||
| 253 | DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); | ||
| 254 | I915_WRITE(ADPA, save_adpa); | ||
| 255 | } | ||
| 256 | |||
| 257 | /* Check the status to see if both blue and green are on now */ | ||
| 258 | adpa = I915_READ(ADPA); | ||
| 259 | if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0) | ||
| 260 | ret = true; | ||
| 261 | else | ||
| 262 | ret = false; | ||
| 263 | |||
| 264 | DRM_DEBUG_KMS("valleyview hotplug adpa=0x%x, result %d\n", adpa, ret); | ||
| 265 | |||
| 266 | /* FIXME: debug force function and remove */ | ||
| 267 | ret = true; | ||
| 268 | |||
| 269 | return ret; | ||
| 270 | } | ||
| 271 | |||
| 233 | /** | 272 | /** |
| 234 | * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence. | 273 | * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence. |
| 235 | * | 274 | * |
| @@ -249,6 +288,9 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) | |||
| 249 | if (HAS_PCH_SPLIT(dev)) | 288 | if (HAS_PCH_SPLIT(dev)) |
| 250 | return intel_ironlake_crt_detect_hotplug(connector); | 289 | return intel_ironlake_crt_detect_hotplug(connector); |
| 251 | 290 | ||
| 291 | if (IS_VALLEYVIEW(dev)) | ||
| 292 | return valleyview_crt_detect_hotplug(connector); | ||
| 293 | |||
| 252 | /* | 294 | /* |
| 253 | * On 4 series desktop, CRT detect sequence need to be done twice | 295 | * On 4 series desktop, CRT detect sequence need to be done twice |
| 254 | * to get a reliable result. | 296 | * to get a reliable result. |
| @@ -453,18 +495,27 @@ intel_crt_detect(struct drm_connector *connector, bool force) | |||
| 453 | struct intel_load_detect_pipe tmp; | 495 | struct intel_load_detect_pipe tmp; |
| 454 | 496 | ||
| 455 | if (I915_HAS_HOTPLUG(dev)) { | 497 | if (I915_HAS_HOTPLUG(dev)) { |
| 498 | /* We can not rely on the HPD pin always being correctly wired | ||
| 499 | * up, for example many KVM do not pass it through, and so | ||
| 500 | * only trust an assertion that the monitor is connected. | ||
| 501 | */ | ||
| 456 | if (intel_crt_detect_hotplug(connector)) { | 502 | if (intel_crt_detect_hotplug(connector)) { |
| 457 | DRM_DEBUG_KMS("CRT detected via hotplug\n"); | 503 | DRM_DEBUG_KMS("CRT detected via hotplug\n"); |
| 458 | return connector_status_connected; | 504 | return connector_status_connected; |
| 459 | } else { | 505 | } else |
| 460 | DRM_DEBUG_KMS("CRT not detected via hotplug\n"); | 506 | DRM_DEBUG_KMS("CRT not detected via hotplug\n"); |
| 461 | return connector_status_disconnected; | ||
| 462 | } | ||
| 463 | } | 507 | } |
| 464 | 508 | ||
| 465 | if (intel_crt_detect_ddc(connector)) | 509 | if (intel_crt_detect_ddc(connector)) |
| 466 | return connector_status_connected; | 510 | return connector_status_connected; |
| 467 | 511 | ||
| 512 | /* Load detection is broken on HPD capable machines. Whoever wants a | ||
| 513 | * broken monitor (without edid) to work behind a broken kvm (that fails | ||
| 514 | * to have the right resistors for HP detection) needs to fix this up. | ||
| 515 | * For now just bail out. */ | ||
| 516 | if (I915_HAS_HOTPLUG(dev)) | ||
| 517 | return connector_status_disconnected; | ||
| 518 | |||
| 468 | if (!force) | 519 | if (!force) |
| 469 | return connector->status; | 520 | return connector->status; |
| 470 | 521 | ||
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 46d1e886c692..933c74859172 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
| @@ -170,6 +170,15 @@ void hsw_fdi_link_train(struct drm_crtc *crtc) | |||
| 170 | 170 | ||
| 171 | udelay(600); | 171 | udelay(600); |
| 172 | 172 | ||
| 173 | /* We need to program FDI_RX_MISC with the default TP1 to TP2 | ||
| 174 | * values before enabling the receiver, and configure the delay | ||
| 175 | * for the FDI timing generator to 90h. Luckily, all the other | ||
| 176 | * bits are supposed to be zeroed, so we can write those values | ||
| 177 | * directly. | ||
| 178 | */ | ||
| 179 | I915_WRITE(FDI_RX_MISC(pipe), FDI_RX_TP1_TO_TP2_48 | | ||
| 180 | FDI_RX_FDI_DELAY_90); | ||
| 181 | |||
| 173 | /* Enable CPU FDI Receiver with auto-training */ | 182 | /* Enable CPU FDI Receiver with auto-training */ |
| 174 | reg = FDI_RX_CTL(pipe); | 183 | reg = FDI_RX_CTL(pipe); |
| 175 | I915_WRITE(reg, | 184 | I915_WRITE(reg, |
| @@ -726,8 +735,7 @@ void intel_ddi_mode_set(struct drm_encoder *encoder, | |||
| 726 | 735 | ||
| 727 | I915_WRITE(DDI_FUNC_CTL(pipe), temp); | 736 | I915_WRITE(DDI_FUNC_CTL(pipe), temp); |
| 728 | 737 | ||
| 729 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); | 738 | intel_hdmi->set_infoframes(encoder, adjusted_mode); |
| 730 | intel_hdmi_set_spd_infoframe(encoder); | ||
| 731 | } | 739 | } |
| 732 | 740 | ||
| 733 | void intel_ddi_dpms(struct drm_encoder *encoder, int mode) | 741 | void intel_ddi_dpms(struct drm_encoder *encoder, int mode) |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a8538ac0299d..bc25a24a08c5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -98,6 +98,11 @@ intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc, | |||
| 98 | int target, int refclk, intel_clock_t *match_clock, | 98 | int target, int refclk, intel_clock_t *match_clock, |
| 99 | intel_clock_t *best_clock); | 99 | intel_clock_t *best_clock); |
| 100 | 100 | ||
| 101 | static bool | ||
| 102 | intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
| 103 | int target, int refclk, intel_clock_t *match_clock, | ||
| 104 | intel_clock_t *best_clock); | ||
| 105 | |||
| 101 | static inline u32 /* units of 100MHz */ | 106 | static inline u32 /* units of 100MHz */ |
| 102 | intel_fdi_link_freq(struct drm_device *dev) | 107 | intel_fdi_link_freq(struct drm_device *dev) |
| 103 | { | 108 | { |
| @@ -359,6 +364,48 @@ static const intel_limit_t intel_limits_ironlake_display_port = { | |||
| 359 | .find_pll = intel_find_pll_ironlake_dp, | 364 | .find_pll = intel_find_pll_ironlake_dp, |
| 360 | }; | 365 | }; |
| 361 | 366 | ||
| 367 | static const intel_limit_t intel_limits_vlv_dac = { | ||
| 368 | .dot = { .min = 25000, .max = 270000 }, | ||
| 369 | .vco = { .min = 4000000, .max = 6000000 }, | ||
| 370 | .n = { .min = 1, .max = 7 }, | ||
| 371 | .m = { .min = 22, .max = 450 }, /* guess */ | ||
| 372 | .m1 = { .min = 2, .max = 3 }, | ||
| 373 | .m2 = { .min = 11, .max = 156 }, | ||
| 374 | .p = { .min = 10, .max = 30 }, | ||
| 375 | .p1 = { .min = 2, .max = 3 }, | ||
| 376 | .p2 = { .dot_limit = 270000, | ||
| 377 | .p2_slow = 2, .p2_fast = 20 }, | ||
| 378 | .find_pll = intel_vlv_find_best_pll, | ||
| 379 | }; | ||
| 380 | |||
| 381 | static const intel_limit_t intel_limits_vlv_hdmi = { | ||
| 382 | .dot = { .min = 20000, .max = 165000 }, | ||
| 383 | .vco = { .min = 5994000, .max = 4000000 }, | ||
| 384 | .n = { .min = 1, .max = 7 }, | ||
| 385 | .m = { .min = 60, .max = 300 }, /* guess */ | ||
| 386 | .m1 = { .min = 2, .max = 3 }, | ||
| 387 | .m2 = { .min = 11, .max = 156 }, | ||
| 388 | .p = { .min = 10, .max = 30 }, | ||
| 389 | .p1 = { .min = 2, .max = 3 }, | ||
| 390 | .p2 = { .dot_limit = 270000, | ||
| 391 | .p2_slow = 2, .p2_fast = 20 }, | ||
| 392 | .find_pll = intel_vlv_find_best_pll, | ||
| 393 | }; | ||
| 394 | |||
| 395 | static const intel_limit_t intel_limits_vlv_dp = { | ||
| 396 | .dot = { .min = 162000, .max = 270000 }, | ||
| 397 | .vco = { .min = 5994000, .max = 4000000 }, | ||
| 398 | .n = { .min = 1, .max = 7 }, | ||
| 399 | .m = { .min = 60, .max = 300 }, /* guess */ | ||
| 400 | .m1 = { .min = 2, .max = 3 }, | ||
| 401 | .m2 = { .min = 11, .max = 156 }, | ||
| 402 | .p = { .min = 10, .max = 30 }, | ||
| 403 | .p1 = { .min = 2, .max = 3 }, | ||
| 404 | .p2 = { .dot_limit = 270000, | ||
| 405 | .p2_slow = 2, .p2_fast = 20 }, | ||
| 406 | .find_pll = intel_vlv_find_best_pll, | ||
| 407 | }; | ||
| 408 | |||
| 362 | u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg) | 409 | u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg) |
| 363 | { | 410 | { |
| 364 | unsigned long flags; | 411 | unsigned long flags; |
| @@ -384,6 +431,28 @@ out_unlock: | |||
| 384 | return val; | 431 | return val; |
| 385 | } | 432 | } |
| 386 | 433 | ||
| 434 | static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg, | ||
| 435 | u32 val) | ||
| 436 | { | ||
| 437 | unsigned long flags; | ||
| 438 | |||
| 439 | spin_lock_irqsave(&dev_priv->dpio_lock, flags); | ||
| 440 | if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) { | ||
| 441 | DRM_ERROR("DPIO idle wait timed out\n"); | ||
| 442 | goto out_unlock; | ||
| 443 | } | ||
| 444 | |||
| 445 | I915_WRITE(DPIO_DATA, val); | ||
| 446 | I915_WRITE(DPIO_REG, reg); | ||
| 447 | I915_WRITE(DPIO_PKT, DPIO_RID | DPIO_OP_WRITE | DPIO_PORTID | | ||
| 448 | DPIO_BYTE); | ||
| 449 | if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) | ||
| 450 | DRM_ERROR("DPIO write wait timed out\n"); | ||
| 451 | |||
| 452 | out_unlock: | ||
| 453 | spin_unlock_irqrestore(&dev_priv->dpio_lock, flags); | ||
| 454 | } | ||
| 455 | |||
| 387 | static void vlv_init_dpio(struct drm_device *dev) | 456 | static void vlv_init_dpio(struct drm_device *dev) |
| 388 | { | 457 | { |
| 389 | struct drm_i915_private *dev_priv = dev->dev_private; | 458 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -434,7 +503,7 @@ static bool is_dual_link_lvds(struct drm_i915_private *dev_priv, | |||
| 434 | * register is uninitialized. | 503 | * register is uninitialized. |
| 435 | */ | 504 | */ |
| 436 | val = I915_READ(reg); | 505 | val = I915_READ(reg); |
| 437 | if (!(val & ~LVDS_DETECTED)) | 506 | if (!(val & ~(LVDS_PIPE_MASK | LVDS_DETECTED))) |
| 438 | val = dev_priv->bios_lvds_val; | 507 | val = dev_priv->bios_lvds_val; |
| 439 | dev_priv->lvds_val = val; | 508 | dev_priv->lvds_val = val; |
| 440 | } | 509 | } |
| @@ -510,6 +579,13 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc, int refclk) | |||
| 510 | limit = &intel_limits_pineview_lvds; | 579 | limit = &intel_limits_pineview_lvds; |
| 511 | else | 580 | else |
| 512 | limit = &intel_limits_pineview_sdvo; | 581 | limit = &intel_limits_pineview_sdvo; |
| 582 | } else if (IS_VALLEYVIEW(dev)) { | ||
| 583 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) | ||
| 584 | limit = &intel_limits_vlv_dac; | ||
| 585 | else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) | ||
| 586 | limit = &intel_limits_vlv_hdmi; | ||
| 587 | else | ||
| 588 | limit = &intel_limits_vlv_dp; | ||
| 513 | } else if (!IS_GEN2(dev)) { | 589 | } else if (!IS_GEN2(dev)) { |
| 514 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 590 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
| 515 | limit = &intel_limits_i9xx_lvds; | 591 | limit = &intel_limits_i9xx_lvds; |
| @@ -551,11 +627,10 @@ static void intel_clock(struct drm_device *dev, int refclk, intel_clock_t *clock | |||
| 551 | bool intel_pipe_has_type(struct drm_crtc *crtc, int type) | 627 | bool intel_pipe_has_type(struct drm_crtc *crtc, int type) |
| 552 | { | 628 | { |
| 553 | struct drm_device *dev = crtc->dev; | 629 | struct drm_device *dev = crtc->dev; |
| 554 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 555 | struct intel_encoder *encoder; | 630 | struct intel_encoder *encoder; |
| 556 | 631 | ||
| 557 | list_for_each_entry(encoder, &mode_config->encoder_list, base.head) | 632 | for_each_encoder_on_crtc(dev, crtc, encoder) |
| 558 | if (encoder->base.crtc == crtc && encoder->type == type) | 633 | if (encoder->type == type) |
| 559 | return true; | 634 | return true; |
| 560 | 635 | ||
| 561 | return false; | 636 | return false; |
| @@ -783,6 +858,73 @@ intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, | |||
| 783 | memcpy(best_clock, &clock, sizeof(intel_clock_t)); | 858 | memcpy(best_clock, &clock, sizeof(intel_clock_t)); |
| 784 | return true; | 859 | return true; |
| 785 | } | 860 | } |
| 861 | static bool | ||
| 862 | intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
| 863 | int target, int refclk, intel_clock_t *match_clock, | ||
| 864 | intel_clock_t *best_clock) | ||
| 865 | { | ||
| 866 | u32 p1, p2, m1, m2, vco, bestn, bestm1, bestm2, bestp1, bestp2; | ||
| 867 | u32 m, n, fastclk; | ||
| 868 | u32 updrate, minupdate, fracbits, p; | ||
| 869 | unsigned long bestppm, ppm, absppm; | ||
| 870 | int dotclk, flag; | ||
| 871 | |||
| 872 | dotclk = target * 1000; | ||
| 873 | bestppm = 1000000; | ||
| 874 | ppm = absppm = 0; | ||
| 875 | fastclk = dotclk / (2*100); | ||
| 876 | updrate = 0; | ||
| 877 | minupdate = 19200; | ||
| 878 | fracbits = 1; | ||
| 879 | n = p = p1 = p2 = m = m1 = m2 = vco = bestn = 0; | ||
| 880 | bestm1 = bestm2 = bestp1 = bestp2 = 0; | ||
| 881 | |||
| 882 | /* based on hardware requirement, prefer smaller n to precision */ | ||
| 883 | for (n = limit->n.min; n <= ((refclk) / minupdate); n++) { | ||
| 884 | updrate = refclk / n; | ||
| 885 | for (p1 = limit->p1.max; p1 > limit->p1.min; p1--) { | ||
| 886 | for (p2 = limit->p2.p2_fast+1; p2 > 0; p2--) { | ||
| 887 | if (p2 > 10) | ||
| 888 | p2 = p2 - 1; | ||
| 889 | p = p1 * p2; | ||
| 890 | /* based on hardware requirement, prefer bigger m1,m2 values */ | ||
| 891 | for (m1 = limit->m1.min; m1 <= limit->m1.max; m1++) { | ||
| 892 | m2 = (((2*(fastclk * p * n / m1 )) + | ||
| 893 | refclk) / (2*refclk)); | ||
| 894 | m = m1 * m2; | ||
| 895 | vco = updrate * m; | ||
| 896 | if (vco >= limit->vco.min && vco < limit->vco.max) { | ||
| 897 | ppm = 1000000 * ((vco / p) - fastclk) / fastclk; | ||
| 898 | absppm = (ppm > 0) ? ppm : (-ppm); | ||
| 899 | if (absppm < 100 && ((p1 * p2) > (bestp1 * bestp2))) { | ||
| 900 | bestppm = 0; | ||
| 901 | flag = 1; | ||
| 902 | } | ||
| 903 | if (absppm < bestppm - 10) { | ||
| 904 | bestppm = absppm; | ||
| 905 | flag = 1; | ||
| 906 | } | ||
| 907 | if (flag) { | ||
| 908 | bestn = n; | ||
| 909 | bestm1 = m1; | ||
| 910 | bestm2 = m2; | ||
| 911 | bestp1 = p1; | ||
| 912 | bestp2 = p2; | ||
| 913 | flag = 0; | ||
| 914 | } | ||
| 915 | } | ||
| 916 | } | ||
| 917 | } | ||
| 918 | } | ||
| 919 | } | ||
| 920 | best_clock->n = bestn; | ||
| 921 | best_clock->m1 = bestm1; | ||
| 922 | best_clock->m2 = bestm2; | ||
| 923 | best_clock->p1 = bestp1; | ||
| 924 | best_clock->p2 = bestp2; | ||
| 925 | |||
| 926 | return true; | ||
| 927 | } | ||
| 786 | 928 | ||
| 787 | static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe) | 929 | static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe) |
| 788 | { | 930 | { |
| @@ -1232,6 +1374,9 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, | |||
| 1232 | WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val), | 1374 | WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val), |
| 1233 | "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", | 1375 | "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", |
| 1234 | reg, pipe_name(pipe)); | 1376 | reg, pipe_name(pipe)); |
| 1377 | |||
| 1378 | WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), | ||
| 1379 | "IBX PCH dp port still using transcoder B\n"); | ||
| 1235 | } | 1380 | } |
| 1236 | 1381 | ||
| 1237 | static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, | 1382 | static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, |
| @@ -1241,6 +1386,9 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, | |||
| 1241 | WARN(hdmi_pipe_enabled(dev_priv, val, pipe), | 1386 | WARN(hdmi_pipe_enabled(dev_priv, val, pipe), |
| 1242 | "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", | 1387 | "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", |
| 1243 | reg, pipe_name(pipe)); | 1388 | reg, pipe_name(pipe)); |
| 1389 | |||
| 1390 | WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), | ||
| 1391 | "IBX PCH hdmi port still using transcoder B\n"); | ||
| 1244 | } | 1392 | } |
| 1245 | 1393 | ||
| 1246 | static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, | 1394 | static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, |
| @@ -1287,7 +1435,7 @@ static void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) | |||
| 1287 | u32 val; | 1435 | u32 val; |
| 1288 | 1436 | ||
| 1289 | /* No really, not for ILK+ */ | 1437 | /* No really, not for ILK+ */ |
| 1290 | BUG_ON(dev_priv->info->gen >= 5); | 1438 | BUG_ON(!IS_VALLEYVIEW(dev_priv->dev) && dev_priv->info->gen >= 5); |
| 1291 | 1439 | ||
| 1292 | /* PLL is protected by panel, make sure we can write it */ | 1440 | /* PLL is protected by panel, make sure we can write it */ |
| 1293 | if (IS_MOBILE(dev_priv->dev) && !IS_I830(dev_priv->dev)) | 1441 | if (IS_MOBILE(dev_priv->dev) && !IS_I830(dev_priv->dev)) |
| @@ -1344,7 +1492,7 @@ intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value) | |||
| 1344 | unsigned long flags; | 1492 | unsigned long flags; |
| 1345 | 1493 | ||
| 1346 | spin_lock_irqsave(&dev_priv->dpio_lock, flags); | 1494 | spin_lock_irqsave(&dev_priv->dpio_lock, flags); |
| 1347 | if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_READY) == 0, | 1495 | if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0, |
| 1348 | 100)) { | 1496 | 100)) { |
| 1349 | DRM_ERROR("timeout waiting for SBI to become ready\n"); | 1497 | DRM_ERROR("timeout waiting for SBI to become ready\n"); |
| 1350 | goto out_unlock; | 1498 | goto out_unlock; |
| @@ -1358,7 +1506,7 @@ intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value) | |||
| 1358 | SBI_BUSY | | 1506 | SBI_BUSY | |
| 1359 | SBI_CTL_OP_CRWR); | 1507 | SBI_CTL_OP_CRWR); |
| 1360 | 1508 | ||
| 1361 | if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_READY | SBI_RESPONSE_SUCCESS)) == 0, | 1509 | if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0, |
| 1362 | 100)) { | 1510 | 100)) { |
| 1363 | DRM_ERROR("timeout waiting for SBI to complete write transaction\n"); | 1511 | DRM_ERROR("timeout waiting for SBI to complete write transaction\n"); |
| 1364 | goto out_unlock; | 1512 | goto out_unlock; |
| @@ -1372,10 +1520,10 @@ static u32 | |||
| 1372 | intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg) | 1520 | intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg) |
| 1373 | { | 1521 | { |
| 1374 | unsigned long flags; | 1522 | unsigned long flags; |
| 1375 | u32 value; | 1523 | u32 value = 0; |
| 1376 | 1524 | ||
| 1377 | spin_lock_irqsave(&dev_priv->dpio_lock, flags); | 1525 | spin_lock_irqsave(&dev_priv->dpio_lock, flags); |
| 1378 | if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_READY) == 0, | 1526 | if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0, |
| 1379 | 100)) { | 1527 | 100)) { |
| 1380 | DRM_ERROR("timeout waiting for SBI to become ready\n"); | 1528 | DRM_ERROR("timeout waiting for SBI to become ready\n"); |
| 1381 | goto out_unlock; | 1529 | goto out_unlock; |
| @@ -1387,7 +1535,7 @@ intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg) | |||
| 1387 | SBI_BUSY | | 1535 | SBI_BUSY | |
| 1388 | SBI_CTL_OP_CRRD); | 1536 | SBI_CTL_OP_CRRD); |
| 1389 | 1537 | ||
| 1390 | if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_READY | SBI_RESPONSE_SUCCESS)) == 0, | 1538 | if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0, |
| 1391 | 100)) { | 1539 | 100)) { |
| 1392 | DRM_ERROR("timeout waiting for SBI to complete read transaction\n"); | 1540 | DRM_ERROR("timeout waiting for SBI to complete read transaction\n"); |
| 1393 | goto out_unlock; | 1541 | goto out_unlock; |
| @@ -1824,6 +1972,22 @@ void intel_unpin_fb_obj(struct drm_i915_gem_object *obj) | |||
| 1824 | i915_gem_object_unpin(obj); | 1972 | i915_gem_object_unpin(obj); |
| 1825 | } | 1973 | } |
| 1826 | 1974 | ||
| 1975 | /* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel | ||
| 1976 | * is assumed to be a power-of-two. */ | ||
| 1977 | static unsigned long gen4_compute_dspaddr_offset_xtiled(int *x, int *y, | ||
| 1978 | unsigned int bpp, | ||
| 1979 | unsigned int pitch) | ||
| 1980 | { | ||
| 1981 | int tile_rows, tiles; | ||
| 1982 | |||
| 1983 | tile_rows = *y / 8; | ||
| 1984 | *y %= 8; | ||
| 1985 | tiles = *x / (512/bpp); | ||
| 1986 | *x %= 512/bpp; | ||
| 1987 | |||
| 1988 | return tile_rows * pitch * 8 + tiles * 4096; | ||
| 1989 | } | ||
| 1990 | |||
| 1827 | static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, | 1991 | static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, |
| 1828 | int x, int y) | 1992 | int x, int y) |
| 1829 | { | 1993 | { |
| @@ -1833,7 +1997,7 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
| 1833 | struct intel_framebuffer *intel_fb; | 1997 | struct intel_framebuffer *intel_fb; |
| 1834 | struct drm_i915_gem_object *obj; | 1998 | struct drm_i915_gem_object *obj; |
| 1835 | int plane = intel_crtc->plane; | 1999 | int plane = intel_crtc->plane; |
| 1836 | unsigned long Start, Offset; | 2000 | unsigned long linear_offset; |
| 1837 | u32 dspcntr; | 2001 | u32 dspcntr; |
| 1838 | u32 reg; | 2002 | u32 reg; |
| 1839 | 2003 | ||
| @@ -1880,18 +2044,28 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
| 1880 | 2044 | ||
| 1881 | I915_WRITE(reg, dspcntr); | 2045 | I915_WRITE(reg, dspcntr); |
| 1882 | 2046 | ||
| 1883 | Start = obj->gtt_offset; | 2047 | linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); |
| 1884 | Offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); | 2048 | |
| 2049 | if (INTEL_INFO(dev)->gen >= 4) { | ||
| 2050 | intel_crtc->dspaddr_offset = | ||
| 2051 | gen4_compute_dspaddr_offset_xtiled(&x, &y, | ||
| 2052 | fb->bits_per_pixel / 8, | ||
| 2053 | fb->pitches[0]); | ||
| 2054 | linear_offset -= intel_crtc->dspaddr_offset; | ||
| 2055 | } else { | ||
| 2056 | intel_crtc->dspaddr_offset = linear_offset; | ||
| 2057 | } | ||
| 1885 | 2058 | ||
| 1886 | DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", | 2059 | DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n", |
| 1887 | Start, Offset, x, y, fb->pitches[0]); | 2060 | obj->gtt_offset, linear_offset, x, y, fb->pitches[0]); |
| 1888 | I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); | 2061 | I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); |
| 1889 | if (INTEL_INFO(dev)->gen >= 4) { | 2062 | if (INTEL_INFO(dev)->gen >= 4) { |
| 1890 | I915_MODIFY_DISPBASE(DSPSURF(plane), Start); | 2063 | I915_MODIFY_DISPBASE(DSPSURF(plane), |
| 2064 | obj->gtt_offset + intel_crtc->dspaddr_offset); | ||
| 1891 | I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); | 2065 | I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); |
| 1892 | I915_WRITE(DSPADDR(plane), Offset); | 2066 | I915_WRITE(DSPLINOFF(plane), linear_offset); |
| 1893 | } else | 2067 | } else |
| 1894 | I915_WRITE(DSPADDR(plane), Start + Offset); | 2068 | I915_WRITE(DSPADDR(plane), obj->gtt_offset + linear_offset); |
| 1895 | POSTING_READ(reg); | 2069 | POSTING_READ(reg); |
| 1896 | 2070 | ||
| 1897 | return 0; | 2071 | return 0; |
| @@ -1906,7 +2080,7 @@ static int ironlake_update_plane(struct drm_crtc *crtc, | |||
| 1906 | struct intel_framebuffer *intel_fb; | 2080 | struct intel_framebuffer *intel_fb; |
| 1907 | struct drm_i915_gem_object *obj; | 2081 | struct drm_i915_gem_object *obj; |
| 1908 | int plane = intel_crtc->plane; | 2082 | int plane = intel_crtc->plane; |
| 1909 | unsigned long Start, Offset; | 2083 | unsigned long linear_offset; |
| 1910 | u32 dspcntr; | 2084 | u32 dspcntr; |
| 1911 | u32 reg; | 2085 | u32 reg; |
| 1912 | 2086 | ||
| @@ -1961,15 +2135,20 @@ static int ironlake_update_plane(struct drm_crtc *crtc, | |||
| 1961 | 2135 | ||
| 1962 | I915_WRITE(reg, dspcntr); | 2136 | I915_WRITE(reg, dspcntr); |
| 1963 | 2137 | ||
| 1964 | Start = obj->gtt_offset; | 2138 | linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); |
| 1965 | Offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); | 2139 | intel_crtc->dspaddr_offset = |
| 2140 | gen4_compute_dspaddr_offset_xtiled(&x, &y, | ||
| 2141 | fb->bits_per_pixel / 8, | ||
| 2142 | fb->pitches[0]); | ||
| 2143 | linear_offset -= intel_crtc->dspaddr_offset; | ||
| 1966 | 2144 | ||
| 1967 | DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", | 2145 | DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n", |
| 1968 | Start, Offset, x, y, fb->pitches[0]); | 2146 | obj->gtt_offset, linear_offset, x, y, fb->pitches[0]); |
| 1969 | I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); | 2147 | I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); |
| 1970 | I915_MODIFY_DISPBASE(DSPSURF(plane), Start); | 2148 | I915_MODIFY_DISPBASE(DSPSURF(plane), |
| 2149 | obj->gtt_offset + intel_crtc->dspaddr_offset); | ||
| 1971 | I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); | 2150 | I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); |
| 1972 | I915_WRITE(DSPADDR(plane), Offset); | 2151 | I915_WRITE(DSPLINOFF(plane), linear_offset); |
| 1973 | POSTING_READ(reg); | 2152 | POSTING_READ(reg); |
| 1974 | 2153 | ||
| 1975 | return 0; | 2154 | return 0; |
| @@ -2656,16 +2835,13 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) | |||
| 2656 | static bool intel_crtc_driving_pch(struct drm_crtc *crtc) | 2835 | static bool intel_crtc_driving_pch(struct drm_crtc *crtc) |
| 2657 | { | 2836 | { |
| 2658 | struct drm_device *dev = crtc->dev; | 2837 | struct drm_device *dev = crtc->dev; |
| 2659 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 2660 | struct intel_encoder *encoder; | 2838 | struct intel_encoder *encoder; |
| 2661 | 2839 | ||
| 2662 | /* | 2840 | /* |
| 2663 | * If there's a non-PCH eDP on this crtc, it must be DP_A, and that | 2841 | * If there's a non-PCH eDP on this crtc, it must be DP_A, and that |
| 2664 | * must be driven by its own crtc; no sharing is possible. | 2842 | * must be driven by its own crtc; no sharing is possible. |
| 2665 | */ | 2843 | */ |
| 2666 | list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { | 2844 | for_each_encoder_on_crtc(dev, crtc, encoder) { |
| 2667 | if (encoder->base.crtc != crtc) | ||
| 2668 | continue; | ||
| 2669 | 2845 | ||
| 2670 | /* On Haswell, LPT PCH handles the VGA connection via FDI, and Haswell | 2846 | /* On Haswell, LPT PCH handles the VGA connection via FDI, and Haswell |
| 2671 | * CPU handles all others */ | 2847 | * CPU handles all others */ |
| @@ -3554,16 +3730,12 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, | |||
| 3554 | { | 3730 | { |
| 3555 | struct drm_device *dev = crtc->dev; | 3731 | struct drm_device *dev = crtc->dev; |
| 3556 | struct drm_i915_private *dev_priv = dev->dev_private; | 3732 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 3557 | struct drm_encoder *encoder; | ||
| 3558 | struct drm_connector *connector; | 3733 | struct drm_connector *connector; |
| 3734 | struct intel_encoder *intel_encoder; | ||
| 3559 | unsigned int display_bpc = UINT_MAX, bpc; | 3735 | unsigned int display_bpc = UINT_MAX, bpc; |
| 3560 | 3736 | ||
| 3561 | /* Walk the encoders & connectors on this crtc, get min bpc */ | 3737 | /* Walk the encoders & connectors on this crtc, get min bpc */ |
| 3562 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 3738 | for_each_encoder_on_crtc(dev, crtc, intel_encoder) { |
| 3563 | struct intel_encoder *intel_encoder = to_intel_encoder(encoder); | ||
| 3564 | |||
| 3565 | if (encoder->crtc != crtc) | ||
| 3566 | continue; | ||
| 3567 | 3739 | ||
| 3568 | if (intel_encoder->type == INTEL_OUTPUT_LVDS) { | 3740 | if (intel_encoder->type == INTEL_OUTPUT_LVDS) { |
| 3569 | unsigned int lvds_bpc; | 3741 | unsigned int lvds_bpc; |
| @@ -3595,7 +3767,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, | |||
| 3595 | /* Not one of the known troublemakers, check the EDID */ | 3767 | /* Not one of the known troublemakers, check the EDID */ |
| 3596 | list_for_each_entry(connector, &dev->mode_config.connector_list, | 3768 | list_for_each_entry(connector, &dev->mode_config.connector_list, |
| 3597 | head) { | 3769 | head) { |
| 3598 | if (connector->encoder != encoder) | 3770 | if (connector->encoder != &intel_encoder->base) |
| 3599 | continue; | 3771 | continue; |
| 3600 | 3772 | ||
| 3601 | /* Don't use an invalid EDID bpc value */ | 3773 | /* Don't use an invalid EDID bpc value */ |
| @@ -3666,13 +3838,37 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, | |||
| 3666 | return display_bpc != bpc; | 3838 | return display_bpc != bpc; |
| 3667 | } | 3839 | } |
| 3668 | 3840 | ||
| 3841 | static int vlv_get_refclk(struct drm_crtc *crtc) | ||
| 3842 | { | ||
| 3843 | struct drm_device *dev = crtc->dev; | ||
| 3844 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 3845 | int refclk = 27000; /* for DP & HDMI */ | ||
| 3846 | |||
| 3847 | return 100000; /* only one validated so far */ | ||
| 3848 | |||
| 3849 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { | ||
| 3850 | refclk = 96000; | ||
| 3851 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { | ||
| 3852 | if (intel_panel_use_ssc(dev_priv)) | ||
| 3853 | refclk = 100000; | ||
| 3854 | else | ||
| 3855 | refclk = 96000; | ||
| 3856 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) { | ||
| 3857 | refclk = 100000; | ||
| 3858 | } | ||
| 3859 | |||
| 3860 | return refclk; | ||
| 3861 | } | ||
| 3862 | |||
| 3669 | static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) | 3863 | static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) |
| 3670 | { | 3864 | { |
| 3671 | struct drm_device *dev = crtc->dev; | 3865 | struct drm_device *dev = crtc->dev; |
| 3672 | struct drm_i915_private *dev_priv = dev->dev_private; | 3866 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 3673 | int refclk; | 3867 | int refclk; |
| 3674 | 3868 | ||
| 3675 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && | 3869 | if (IS_VALLEYVIEW(dev)) { |
| 3870 | refclk = vlv_get_refclk(crtc); | ||
| 3871 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && | ||
| 3676 | intel_panel_use_ssc(dev_priv) && num_connectors < 2) { | 3872 | intel_panel_use_ssc(dev_priv) && num_connectors < 2) { |
| 3677 | refclk = dev_priv->lvds_ssc_freq * 1000; | 3873 | refclk = dev_priv->lvds_ssc_freq * 1000; |
| 3678 | DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", | 3874 | DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", |
| @@ -3787,6 +3983,72 @@ static void intel_update_lvds(struct drm_crtc *crtc, intel_clock_t *clock, | |||
| 3787 | I915_WRITE(LVDS, temp); | 3983 | I915_WRITE(LVDS, temp); |
| 3788 | } | 3984 | } |
| 3789 | 3985 | ||
| 3986 | static void vlv_update_pll(struct drm_crtc *crtc, | ||
| 3987 | struct drm_display_mode *mode, | ||
| 3988 | struct drm_display_mode *adjusted_mode, | ||
| 3989 | intel_clock_t *clock, intel_clock_t *reduced_clock, | ||
| 3990 | int refclk, int num_connectors) | ||
| 3991 | { | ||
| 3992 | struct drm_device *dev = crtc->dev; | ||
| 3993 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 3994 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 3995 | int pipe = intel_crtc->pipe; | ||
| 3996 | u32 dpll, mdiv, pdiv; | ||
| 3997 | u32 bestn, bestm1, bestm2, bestp1, bestp2; | ||
| 3998 | bool is_hdmi; | ||
| 3999 | |||
| 4000 | is_hdmi = intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI); | ||
| 4001 | |||
| 4002 | bestn = clock->n; | ||
| 4003 | bestm1 = clock->m1; | ||
| 4004 | bestm2 = clock->m2; | ||
| 4005 | bestp1 = clock->p1; | ||
| 4006 | bestp2 = clock->p2; | ||
| 4007 | |||
| 4008 | /* Enable DPIO clock input */ | ||
| 4009 | dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV | | ||
| 4010 | DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV; | ||
| 4011 | I915_WRITE(DPLL(pipe), dpll); | ||
| 4012 | POSTING_READ(DPLL(pipe)); | ||
| 4013 | |||
| 4014 | mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK)); | ||
| 4015 | mdiv |= ((bestp1 << DPIO_P1_SHIFT) | (bestp2 << DPIO_P2_SHIFT)); | ||
| 4016 | mdiv |= ((bestn << DPIO_N_SHIFT)); | ||
| 4017 | mdiv |= (1 << DPIO_POST_DIV_SHIFT); | ||
| 4018 | mdiv |= (1 << DPIO_K_SHIFT); | ||
| 4019 | mdiv |= DPIO_ENABLE_CALIBRATION; | ||
| 4020 | intel_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv); | ||
| 4021 | |||
| 4022 | intel_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), 0x01000000); | ||
| 4023 | |||
| 4024 | pdiv = DPIO_REFSEL_OVERRIDE | (5 << DPIO_PLL_MODESEL_SHIFT) | | ||
| 4025 | (3 << DPIO_BIAS_CURRENT_CTL_SHIFT) | (1<<20) | | ||
| 4026 | (8 << DPIO_DRIVER_CTL_SHIFT) | (5 << DPIO_CLK_BIAS_CTL_SHIFT); | ||
| 4027 | intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), pdiv); | ||
| 4028 | |||
| 4029 | intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe), 0x009f0051); | ||
| 4030 | |||
| 4031 | dpll |= DPLL_VCO_ENABLE; | ||
| 4032 | I915_WRITE(DPLL(pipe), dpll); | ||
| 4033 | POSTING_READ(DPLL(pipe)); | ||
| 4034 | if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1)) | ||
| 4035 | DRM_ERROR("DPLL %d failed to lock\n", pipe); | ||
| 4036 | |||
| 4037 | if (is_hdmi) { | ||
| 4038 | u32 temp = intel_mode_get_pixel_multiplier(adjusted_mode); | ||
| 4039 | |||
| 4040 | if (temp > 1) | ||
| 4041 | temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; | ||
| 4042 | else | ||
| 4043 | temp = 0; | ||
| 4044 | |||
| 4045 | I915_WRITE(DPLL_MD(pipe), temp); | ||
| 4046 | POSTING_READ(DPLL_MD(pipe)); | ||
| 4047 | } | ||
| 4048 | |||
| 4049 | intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x641); /* ??? */ | ||
| 4050 | } | ||
| 4051 | |||
| 3790 | static void i9xx_update_pll(struct drm_crtc *crtc, | 4052 | static void i9xx_update_pll(struct drm_crtc *crtc, |
| 3791 | struct drm_display_mode *mode, | 4053 | struct drm_display_mode *mode, |
| 3792 | struct drm_display_mode *adjusted_mode, | 4054 | struct drm_display_mode *adjusted_mode, |
| @@ -3974,15 +4236,11 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, | |||
| 3974 | u32 dspcntr, pipeconf, vsyncshift; | 4236 | u32 dspcntr, pipeconf, vsyncshift; |
| 3975 | bool ok, has_reduced_clock = false, is_sdvo = false; | 4237 | bool ok, has_reduced_clock = false, is_sdvo = false; |
| 3976 | bool is_lvds = false, is_tv = false, is_dp = false; | 4238 | bool is_lvds = false, is_tv = false, is_dp = false; |
| 3977 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 3978 | struct intel_encoder *encoder; | 4239 | struct intel_encoder *encoder; |
| 3979 | const intel_limit_t *limit; | 4240 | const intel_limit_t *limit; |
| 3980 | int ret; | 4241 | int ret; |
| 3981 | 4242 | ||
| 3982 | list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { | 4243 | for_each_encoder_on_crtc(dev, crtc, encoder) { |
| 3983 | if (encoder->base.crtc != crtc) | ||
| 3984 | continue; | ||
| 3985 | |||
| 3986 | switch (encoder->type) { | 4244 | switch (encoder->type) { |
| 3987 | case INTEL_OUTPUT_LVDS: | 4245 | case INTEL_OUTPUT_LVDS: |
| 3988 | is_lvds = true; | 4246 | is_lvds = true; |
| @@ -4044,6 +4302,9 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, | |||
| 4044 | 4302 | ||
| 4045 | if (IS_GEN2(dev)) | 4303 | if (IS_GEN2(dev)) |
| 4046 | i8xx_update_pll(crtc, adjusted_mode, &clock, num_connectors); | 4304 | i8xx_update_pll(crtc, adjusted_mode, &clock, num_connectors); |
| 4305 | else if (IS_VALLEYVIEW(dev)) | ||
| 4306 | vlv_update_pll(crtc, mode,adjusted_mode, &clock, NULL, | ||
| 4307 | refclk, num_connectors); | ||
| 4047 | else | 4308 | else |
| 4048 | i9xx_update_pll(crtc, mode, adjusted_mode, &clock, | 4309 | i9xx_update_pll(crtc, mode, adjusted_mode, &clock, |
| 4049 | has_reduced_clock ? &reduced_clock : NULL, | 4310 | has_reduced_clock ? &reduced_clock : NULL, |
| @@ -4282,15 +4543,11 @@ static int ironlake_get_refclk(struct drm_crtc *crtc) | |||
| 4282 | struct drm_device *dev = crtc->dev; | 4543 | struct drm_device *dev = crtc->dev; |
| 4283 | struct drm_i915_private *dev_priv = dev->dev_private; | 4544 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 4284 | struct intel_encoder *encoder; | 4545 | struct intel_encoder *encoder; |
| 4285 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 4286 | struct intel_encoder *edp_encoder = NULL; | 4546 | struct intel_encoder *edp_encoder = NULL; |
| 4287 | int num_connectors = 0; | 4547 | int num_connectors = 0; |
| 4288 | bool is_lvds = false; | 4548 | bool is_lvds = false; |
| 4289 | 4549 | ||
| 4290 | list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { | 4550 | for_each_encoder_on_crtc(dev, crtc, encoder) { |
| 4291 | if (encoder->base.crtc != crtc) | ||
| 4292 | continue; | ||
| 4293 | |||
| 4294 | switch (encoder->type) { | 4551 | switch (encoder->type) { |
| 4295 | case INTEL_OUTPUT_LVDS: | 4552 | case INTEL_OUTPUT_LVDS: |
| 4296 | is_lvds = true; | 4553 | is_lvds = true; |
| @@ -4327,7 +4584,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
| 4327 | u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf; | 4584 | u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf; |
| 4328 | bool ok, has_reduced_clock = false, is_sdvo = false; | 4585 | bool ok, has_reduced_clock = false, is_sdvo = false; |
| 4329 | bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; | 4586 | bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; |
| 4330 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 4331 | struct intel_encoder *encoder, *edp_encoder = NULL; | 4587 | struct intel_encoder *encoder, *edp_encoder = NULL; |
| 4332 | const intel_limit_t *limit; | 4588 | const intel_limit_t *limit; |
| 4333 | int ret; | 4589 | int ret; |
| @@ -4338,10 +4594,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
| 4338 | bool dither; | 4594 | bool dither; |
| 4339 | bool is_cpu_edp = false, is_pch_edp = false; | 4595 | bool is_cpu_edp = false, is_pch_edp = false; |
| 4340 | 4596 | ||
| 4341 | list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { | 4597 | for_each_encoder_on_crtc(dev, crtc, encoder) { |
| 4342 | if (encoder->base.crtc != crtc) | ||
| 4343 | continue; | ||
| 4344 | |||
| 4345 | switch (encoder->type) { | 4598 | switch (encoder->type) { |
| 4346 | case INTEL_OUTPUT_LVDS: | 4599 | case INTEL_OUTPUT_LVDS: |
| 4347 | is_lvds = true; | 4600 | is_lvds = true; |
| @@ -4405,25 +4658,10 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
| 4405 | &clock, | 4658 | &clock, |
| 4406 | &reduced_clock); | 4659 | &reduced_clock); |
| 4407 | } | 4660 | } |
| 4408 | /* SDVO TV has fixed PLL values depend on its clock range, | 4661 | |
| 4409 | this mirrors vbios setting. */ | 4662 | if (is_sdvo && is_tv) |
| 4410 | if (is_sdvo && is_tv) { | 4663 | i9xx_adjust_sdvo_tv_clock(adjusted_mode, &clock); |
| 4411 | if (adjusted_mode->clock >= 100000 | 4664 | |
| 4412 | && adjusted_mode->clock < 140500) { | ||
| 4413 | clock.p1 = 2; | ||
| 4414 | clock.p2 = 10; | ||
| 4415 | clock.n = 3; | ||
| 4416 | clock.m1 = 16; | ||
| 4417 | clock.m2 = 8; | ||
| 4418 | } else if (adjusted_mode->clock >= 140500 | ||
| 4419 | && adjusted_mode->clock <= 200000) { | ||
| 4420 | clock.p1 = 1; | ||
| 4421 | clock.p2 = 10; | ||
| 4422 | clock.n = 6; | ||
| 4423 | clock.m1 = 12; | ||
| 4424 | clock.m2 = 8; | ||
| 4425 | } | ||
| 4426 | } | ||
| 4427 | 4665 | ||
| 4428 | /* FDI link */ | 4666 | /* FDI link */ |
| 4429 | pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); | 4667 | pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); |
| @@ -4431,16 +4669,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
| 4431 | /* CPU eDP doesn't require FDI link, so just set DP M/N | 4669 | /* CPU eDP doesn't require FDI link, so just set DP M/N |
| 4432 | according to current link config */ | 4670 | according to current link config */ |
| 4433 | if (is_cpu_edp) { | 4671 | if (is_cpu_edp) { |
| 4434 | target_clock = mode->clock; | ||
| 4435 | intel_edp_link_config(edp_encoder, &lane, &link_bw); | 4672 | intel_edp_link_config(edp_encoder, &lane, &link_bw); |
| 4436 | } else { | 4673 | } else { |
| 4437 | /* [e]DP over FDI requires target mode clock | ||
| 4438 | instead of link clock */ | ||
| 4439 | if (is_dp) | ||
| 4440 | target_clock = mode->clock; | ||
| 4441 | else | ||
| 4442 | target_clock = adjusted_mode->clock; | ||
| 4443 | |||
| 4444 | /* FDI is a binary signal running at ~2.7GHz, encoding | 4674 | /* FDI is a binary signal running at ~2.7GHz, encoding |
| 4445 | * each output octet as 10 bits. The actual frequency | 4675 | * each output octet as 10 bits. The actual frequency |
| 4446 | * is stored as a divider into a 100MHz clock, and the | 4676 | * is stored as a divider into a 100MHz clock, and the |
| @@ -4451,6 +4681,14 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
| 4451 | link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; | 4681 | link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; |
| 4452 | } | 4682 | } |
| 4453 | 4683 | ||
| 4684 | /* [e]DP over FDI requires target mode clock instead of link clock. */ | ||
| 4685 | if (edp_encoder) | ||
| 4686 | target_clock = intel_edp_target_clock(edp_encoder, mode); | ||
| 4687 | else if (is_dp) | ||
| 4688 | target_clock = mode->clock; | ||
| 4689 | else | ||
| 4690 | target_clock = adjusted_mode->clock; | ||
| 4691 | |||
| 4454 | /* determine panel color depth */ | 4692 | /* determine panel color depth */ |
| 4455 | temp = I915_READ(PIPECONF(pipe)); | 4693 | temp = I915_READ(PIPECONF(pipe)); |
| 4456 | temp &= ~PIPE_BPC_MASK; | 4694 | temp &= ~PIPE_BPC_MASK; |
| @@ -4662,16 +4900,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
| 4662 | if (is_lvds && has_reduced_clock && i915_powersave) { | 4900 | if (is_lvds && has_reduced_clock && i915_powersave) { |
| 4663 | I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2); | 4901 | I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2); |
| 4664 | intel_crtc->lowfreq_avail = true; | 4902 | intel_crtc->lowfreq_avail = true; |
| 4665 | if (HAS_PIPE_CXSR(dev)) { | ||
| 4666 | DRM_DEBUG_KMS("enabling CxSR downclocking\n"); | ||
| 4667 | pipeconf |= PIPECONF_CXSR_DOWNCLOCK; | ||
| 4668 | } | ||
| 4669 | } else { | 4903 | } else { |
| 4670 | I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp); | 4904 | I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp); |
| 4671 | if (HAS_PIPE_CXSR(dev)) { | ||
| 4672 | DRM_DEBUG_KMS("disabling CxSR downclocking\n"); | ||
| 4673 | pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; | ||
| 4674 | } | ||
| 4675 | } | 4905 | } |
| 4676 | } | 4906 | } |
| 4677 | 4907 | ||
| @@ -5975,7 +6205,6 @@ static int intel_gen2_queue_flip(struct drm_device *dev, | |||
| 5975 | { | 6205 | { |
| 5976 | struct drm_i915_private *dev_priv = dev->dev_private; | 6206 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 5977 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 6207 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 5978 | unsigned long offset; | ||
| 5979 | u32 flip_mask; | 6208 | u32 flip_mask; |
| 5980 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; | 6209 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; |
| 5981 | int ret; | 6210 | int ret; |
| @@ -5984,9 +6213,6 @@ static int intel_gen2_queue_flip(struct drm_device *dev, | |||
| 5984 | if (ret) | 6213 | if (ret) |
| 5985 | goto err; | 6214 | goto err; |
| 5986 | 6215 | ||
| 5987 | /* Offset into the new buffer for cases of shared fbs between CRTCs */ | ||
| 5988 | offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8; | ||
| 5989 | |||
| 5990 | ret = intel_ring_begin(ring, 6); | 6216 | ret = intel_ring_begin(ring, 6); |
| 5991 | if (ret) | 6217 | if (ret) |
| 5992 | goto err_unpin; | 6218 | goto err_unpin; |
| @@ -6003,7 +6229,7 @@ static int intel_gen2_queue_flip(struct drm_device *dev, | |||
| 6003 | intel_ring_emit(ring, MI_DISPLAY_FLIP | | 6229 | intel_ring_emit(ring, MI_DISPLAY_FLIP | |
| 6004 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); | 6230 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); |
| 6005 | intel_ring_emit(ring, fb->pitches[0]); | 6231 | intel_ring_emit(ring, fb->pitches[0]); |
| 6006 | intel_ring_emit(ring, obj->gtt_offset + offset); | 6232 | intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); |
| 6007 | intel_ring_emit(ring, 0); /* aux display base address, unused */ | 6233 | intel_ring_emit(ring, 0); /* aux display base address, unused */ |
| 6008 | intel_ring_advance(ring); | 6234 | intel_ring_advance(ring); |
| 6009 | return 0; | 6235 | return 0; |
| @@ -6021,7 +6247,6 @@ static int intel_gen3_queue_flip(struct drm_device *dev, | |||
| 6021 | { | 6247 | { |
| 6022 | struct drm_i915_private *dev_priv = dev->dev_private; | 6248 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 6023 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 6249 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 6024 | unsigned long offset; | ||
| 6025 | u32 flip_mask; | 6250 | u32 flip_mask; |
| 6026 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; | 6251 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; |
| 6027 | int ret; | 6252 | int ret; |
| @@ -6030,9 +6255,6 @@ static int intel_gen3_queue_flip(struct drm_device *dev, | |||
| 6030 | if (ret) | 6255 | if (ret) |
| 6031 | goto err; | 6256 | goto err; |
| 6032 | 6257 | ||
| 6033 | /* Offset into the new buffer for cases of shared fbs between CRTCs */ | ||
| 6034 | offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8; | ||
| 6035 | |||
| 6036 | ret = intel_ring_begin(ring, 6); | 6258 | ret = intel_ring_begin(ring, 6); |
| 6037 | if (ret) | 6259 | if (ret) |
| 6038 | goto err_unpin; | 6260 | goto err_unpin; |
| @@ -6046,7 +6268,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev, | |||
| 6046 | intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | | 6268 | intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | |
| 6047 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); | 6269 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); |
| 6048 | intel_ring_emit(ring, fb->pitches[0]); | 6270 | intel_ring_emit(ring, fb->pitches[0]); |
| 6049 | intel_ring_emit(ring, obj->gtt_offset + offset); | 6271 | intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); |
| 6050 | intel_ring_emit(ring, MI_NOOP); | 6272 | intel_ring_emit(ring, MI_NOOP); |
| 6051 | 6273 | ||
| 6052 | intel_ring_advance(ring); | 6274 | intel_ring_advance(ring); |
| @@ -6084,7 +6306,9 @@ static int intel_gen4_queue_flip(struct drm_device *dev, | |||
| 6084 | intel_ring_emit(ring, MI_DISPLAY_FLIP | | 6306 | intel_ring_emit(ring, MI_DISPLAY_FLIP | |
| 6085 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); | 6307 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); |
| 6086 | intel_ring_emit(ring, fb->pitches[0]); | 6308 | intel_ring_emit(ring, fb->pitches[0]); |
| 6087 | intel_ring_emit(ring, obj->gtt_offset | obj->tiling_mode); | 6309 | intel_ring_emit(ring, |
| 6310 | (obj->gtt_offset + intel_crtc->dspaddr_offset) | | ||
| 6311 | obj->tiling_mode); | ||
| 6088 | 6312 | ||
| 6089 | /* XXX Enabling the panel-fitter across page-flip is so far | 6313 | /* XXX Enabling the panel-fitter across page-flip is so far |
| 6090 | * untested on non-native modes, so ignore it for now. | 6314 | * untested on non-native modes, so ignore it for now. |
| @@ -6124,7 +6348,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev, | |||
| 6124 | intel_ring_emit(ring, MI_DISPLAY_FLIP | | 6348 | intel_ring_emit(ring, MI_DISPLAY_FLIP | |
| 6125 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); | 6349 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); |
| 6126 | intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode); | 6350 | intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode); |
| 6127 | intel_ring_emit(ring, obj->gtt_offset); | 6351 | intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); |
| 6128 | 6352 | ||
| 6129 | /* Contrary to the suggestions in the documentation, | 6353 | /* Contrary to the suggestions in the documentation, |
| 6130 | * "Enable Panel Fitter" does not seem to be required when page | 6354 | * "Enable Panel Fitter" does not seem to be required when page |
| @@ -6187,7 +6411,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, | |||
| 6187 | 6411 | ||
| 6188 | intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); | 6412 | intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); |
| 6189 | intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); | 6413 | intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); |
| 6190 | intel_ring_emit(ring, (obj->gtt_offset)); | 6414 | intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); |
| 6191 | intel_ring_emit(ring, (MI_NOOP)); | 6415 | intel_ring_emit(ring, (MI_NOOP)); |
| 6192 | intel_ring_advance(ring); | 6416 | intel_ring_advance(ring); |
| 6193 | return 0; | 6417 | return 0; |
| @@ -6219,6 +6443,19 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
| 6219 | unsigned long flags; | 6443 | unsigned long flags; |
| 6220 | int ret; | 6444 | int ret; |
| 6221 | 6445 | ||
| 6446 | /* Can't change pixel format via MI display flips. */ | ||
| 6447 | if (fb->pixel_format != crtc->fb->pixel_format) | ||
| 6448 | return -EINVAL; | ||
| 6449 | |||
| 6450 | /* | ||
| 6451 | * TILEOFF/LINOFF registers can't be changed via MI display flips. | ||
| 6452 | * Note that pitch changes could also affect these register. | ||
| 6453 | */ | ||
| 6454 | if (INTEL_INFO(dev)->gen > 3 && | ||
| 6455 | (fb->offsets[0] != crtc->fb->offsets[0] || | ||
| 6456 | fb->pitches[0] != crtc->fb->pitches[0])) | ||
| 6457 | return -EINVAL; | ||
| 6458 | |||
| 6222 | work = kzalloc(sizeof *work, GFP_KERNEL); | 6459 | work = kzalloc(sizeof *work, GFP_KERNEL); |
| 6223 | if (work == NULL) | 6460 | if (work == NULL) |
| 6224 | return -ENOMEM; | 6461 | return -ENOMEM; |
| @@ -6566,7 +6803,24 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 6566 | 6803 | ||
| 6567 | if (!dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED)) | 6804 | if (!dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED)) |
| 6568 | intel_dp_init(dev, PCH_DP_D); | 6805 | intel_dp_init(dev, PCH_DP_D); |
| 6806 | } else if (IS_VALLEYVIEW(dev)) { | ||
| 6807 | int found; | ||
| 6808 | |||
| 6809 | if (I915_READ(SDVOB) & PORT_DETECTED) { | ||
| 6810 | /* SDVOB multiplex with HDMIB */ | ||
| 6811 | found = intel_sdvo_init(dev, SDVOB, true); | ||
| 6812 | if (!found) | ||
| 6813 | intel_hdmi_init(dev, SDVOB); | ||
| 6814 | if (!found && (I915_READ(DP_B) & DP_DETECTED)) | ||
| 6815 | intel_dp_init(dev, DP_B); | ||
| 6816 | } | ||
| 6817 | |||
| 6818 | if (I915_READ(SDVOC) & PORT_DETECTED) | ||
| 6819 | intel_hdmi_init(dev, SDVOC); | ||
| 6569 | 6820 | ||
| 6821 | /* Shares lanes with HDMI on SDVOC */ | ||
| 6822 | if (I915_READ(DP_C) & DP_DETECTED) | ||
| 6823 | intel_dp_init(dev, DP_C); | ||
| 6570 | } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) { | 6824 | } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) { |
| 6571 | bool found = false; | 6825 | bool found = false; |
| 6572 | 6826 | ||
| @@ -6623,7 +6877,7 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 6623 | /* disable all the possible outputs/crtcs before entering KMS mode */ | 6877 | /* disable all the possible outputs/crtcs before entering KMS mode */ |
| 6624 | drm_helper_disable_unused_functions(dev); | 6878 | drm_helper_disable_unused_functions(dev); |
| 6625 | 6879 | ||
| 6626 | if (HAS_PCH_SPLIT(dev)) | 6880 | if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) |
| 6627 | ironlake_init_pch_refclk(dev); | 6881 | ironlake_init_pch_refclk(dev); |
| 6628 | } | 6882 | } |
| 6629 | 6883 | ||
| @@ -6777,9 +7031,6 @@ static void intel_init_display(struct drm_device *dev) | |||
| 6777 | dev_priv->display.write_eld = ironlake_write_eld; | 7031 | dev_priv->display.write_eld = ironlake_write_eld; |
| 6778 | } else | 7032 | } else |
| 6779 | dev_priv->display.update_wm = NULL; | 7033 | dev_priv->display.update_wm = NULL; |
| 6780 | } else if (IS_VALLEYVIEW(dev)) { | ||
| 6781 | dev_priv->display.force_wake_get = vlv_force_wake_get; | ||
| 6782 | dev_priv->display.force_wake_put = vlv_force_wake_put; | ||
| 6783 | } else if (IS_G4X(dev)) { | 7034 | } else if (IS_G4X(dev)) { |
| 6784 | dev_priv->display.write_eld = g4x_write_eld; | 7035 | dev_priv->display.write_eld = g4x_write_eld; |
| 6785 | } | 7036 | } |
| @@ -6923,20 +7174,13 @@ static void i915_disable_vga(struct drm_device *dev) | |||
| 6923 | 7174 | ||
| 6924 | void intel_modeset_init_hw(struct drm_device *dev) | 7175 | void intel_modeset_init_hw(struct drm_device *dev) |
| 6925 | { | 7176 | { |
| 6926 | struct drm_i915_private *dev_priv = dev->dev_private; | 7177 | intel_prepare_ddi(dev); |
| 6927 | 7178 | ||
| 6928 | intel_init_clock_gating(dev); | 7179 | intel_init_clock_gating(dev); |
| 6929 | 7180 | ||
| 6930 | if (IS_IRONLAKE_M(dev)) { | 7181 | mutex_lock(&dev->struct_mutex); |
| 6931 | ironlake_enable_drps(dev); | 7182 | intel_enable_gt_powersave(dev); |
| 6932 | ironlake_enable_rc6(dev); | 7183 | mutex_unlock(&dev->struct_mutex); |
| 6933 | intel_init_emon(dev); | ||
| 6934 | } | ||
| 6935 | |||
| 6936 | if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) { | ||
| 6937 | gen6_enable_rps(dev_priv); | ||
| 6938 | gen6_update_ring_freq(dev_priv); | ||
| 6939 | } | ||
| 6940 | } | 7184 | } |
| 6941 | 7185 | ||
| 6942 | void intel_modeset_init(struct drm_device *dev) | 7186 | void intel_modeset_init(struct drm_device *dev) |
| @@ -6958,8 +7202,6 @@ void intel_modeset_init(struct drm_device *dev) | |||
| 6958 | 7202 | ||
| 6959 | intel_init_pm(dev); | 7203 | intel_init_pm(dev); |
| 6960 | 7204 | ||
| 6961 | intel_prepare_ddi(dev); | ||
| 6962 | |||
| 6963 | intel_init_display(dev); | 7205 | intel_init_display(dev); |
| 6964 | 7206 | ||
| 6965 | if (IS_GEN2(dev)) { | 7207 | if (IS_GEN2(dev)) { |
| @@ -6972,7 +7214,7 @@ void intel_modeset_init(struct drm_device *dev) | |||
| 6972 | dev->mode_config.max_width = 8192; | 7214 | dev->mode_config.max_width = 8192; |
| 6973 | dev->mode_config.max_height = 8192; | 7215 | dev->mode_config.max_height = 8192; |
| 6974 | } | 7216 | } |
| 6975 | dev->mode_config.fb_base = dev->agp->base; | 7217 | dev->mode_config.fb_base = dev_priv->mm.gtt_base_addr; |
| 6976 | 7218 | ||
| 6977 | DRM_DEBUG_KMS("%d display pipe%s available.\n", | 7219 | DRM_DEBUG_KMS("%d display pipe%s available.\n", |
| 6978 | dev_priv->num_pipe, dev_priv->num_pipe > 1 ? "s" : ""); | 7220 | dev_priv->num_pipe, dev_priv->num_pipe > 1 ? "s" : ""); |
| @@ -7025,13 +7267,9 @@ void intel_modeset_cleanup(struct drm_device *dev) | |||
| 7025 | 7267 | ||
| 7026 | intel_disable_fbc(dev); | 7268 | intel_disable_fbc(dev); |
| 7027 | 7269 | ||
| 7028 | if (IS_IRONLAKE_M(dev)) | 7270 | intel_disable_gt_powersave(dev); |
| 7029 | ironlake_disable_drps(dev); | ||
| 7030 | if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) | ||
| 7031 | gen6_disable_rps(dev); | ||
| 7032 | 7271 | ||
| 7033 | if (IS_IRONLAKE_M(dev)) | 7272 | ironlake_teardown_rc6(dev); |
| 7034 | ironlake_disable_rc6(dev); | ||
| 7035 | 7273 | ||
| 7036 | if (IS_VALLEYVIEW(dev)) | 7274 | if (IS_VALLEYVIEW(dev)) |
| 7037 | vlv_init_dpio(dev); | 7275 | vlv_init_dpio(dev); |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c0449324143c..2bc1505132c3 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -155,6 +155,18 @@ intel_edp_link_config(struct intel_encoder *intel_encoder, | |||
| 155 | *link_bw = 270000; | 155 | *link_bw = 270000; |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | int | ||
| 159 | intel_edp_target_clock(struct intel_encoder *intel_encoder, | ||
| 160 | struct drm_display_mode *mode) | ||
| 161 | { | ||
| 162 | struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base); | ||
| 163 | |||
| 164 | if (intel_dp->panel_fixed_mode) | ||
| 165 | return intel_dp->panel_fixed_mode->clock; | ||
| 166 | else | ||
| 167 | return mode->clock; | ||
| 168 | } | ||
| 169 | |||
| 158 | static int | 170 | static int |
| 159 | intel_dp_max_lane_count(struct intel_dp *intel_dp) | 171 | intel_dp_max_lane_count(struct intel_dp *intel_dp) |
| 160 | { | 172 | { |
| @@ -225,7 +237,7 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes) | |||
| 225 | static bool | 237 | static bool |
| 226 | intel_dp_adjust_dithering(struct intel_dp *intel_dp, | 238 | intel_dp_adjust_dithering(struct intel_dp *intel_dp, |
| 227 | struct drm_display_mode *mode, | 239 | struct drm_display_mode *mode, |
| 228 | struct drm_display_mode *adjusted_mode) | 240 | bool adjust_mode) |
| 229 | { | 241 | { |
| 230 | int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); | 242 | int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); |
| 231 | int max_lanes = intel_dp_max_lane_count(intel_dp); | 243 | int max_lanes = intel_dp_max_lane_count(intel_dp); |
| @@ -239,8 +251,8 @@ intel_dp_adjust_dithering(struct intel_dp *intel_dp, | |||
| 239 | if (mode_rate > max_rate) | 251 | if (mode_rate > max_rate) |
| 240 | return false; | 252 | return false; |
| 241 | 253 | ||
| 242 | if (adjusted_mode) | 254 | if (adjust_mode) |
| 243 | adjusted_mode->private_flags | 255 | mode->private_flags |
| 244 | |= INTEL_MODE_DP_FORCE_6BPC; | 256 | |= INTEL_MODE_DP_FORCE_6BPC; |
| 245 | 257 | ||
| 246 | return true; | 258 | return true; |
| @@ -263,7 +275,7 @@ intel_dp_mode_valid(struct drm_connector *connector, | |||
| 263 | return MODE_PANEL; | 275 | return MODE_PANEL; |
| 264 | } | 276 | } |
| 265 | 277 | ||
| 266 | if (!intel_dp_adjust_dithering(intel_dp, mode, NULL)) | 278 | if (!intel_dp_adjust_dithering(intel_dp, mode, false)) |
| 267 | return MODE_CLOCK_HIGH; | 279 | return MODE_CLOCK_HIGH; |
| 268 | 280 | ||
| 269 | if (mode->clock < 10000) | 281 | if (mode->clock < 10000) |
| @@ -691,7 +703,8 @@ intel_dp_i2c_init(struct intel_dp *intel_dp, | |||
| 691 | } | 703 | } |
| 692 | 704 | ||
| 693 | static bool | 705 | static bool |
| 694 | intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | 706 | intel_dp_mode_fixup(struct drm_encoder *encoder, |
| 707 | const struct drm_display_mode *mode, | ||
| 695 | struct drm_display_mode *adjusted_mode) | 708 | struct drm_display_mode *adjusted_mode) |
| 696 | { | 709 | { |
| 697 | struct drm_device *dev = encoder->dev; | 710 | struct drm_device *dev = encoder->dev; |
| @@ -706,28 +719,23 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | |||
| 706 | intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode); | 719 | intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode); |
| 707 | intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN, | 720 | intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN, |
| 708 | mode, adjusted_mode); | 721 | mode, adjusted_mode); |
| 709 | /* | ||
| 710 | * the mode->clock is used to calculate the Data&Link M/N | ||
| 711 | * of the pipe. For the eDP the fixed clock should be used. | ||
| 712 | */ | ||
| 713 | mode->clock = intel_dp->panel_fixed_mode->clock; | ||
| 714 | } | 722 | } |
| 715 | 723 | ||
| 716 | if (mode->flags & DRM_MODE_FLAG_DBLCLK) | 724 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) |
| 717 | return false; | 725 | return false; |
| 718 | 726 | ||
| 719 | DRM_DEBUG_KMS("DP link computation with max lane count %i " | 727 | DRM_DEBUG_KMS("DP link computation with max lane count %i " |
| 720 | "max bw %02x pixel clock %iKHz\n", | 728 | "max bw %02x pixel clock %iKHz\n", |
| 721 | max_lane_count, bws[max_clock], mode->clock); | 729 | max_lane_count, bws[max_clock], adjusted_mode->clock); |
| 722 | 730 | ||
| 723 | if (!intel_dp_adjust_dithering(intel_dp, mode, adjusted_mode)) | 731 | if (!intel_dp_adjust_dithering(intel_dp, adjusted_mode, true)) |
| 724 | return false; | 732 | return false; |
| 725 | 733 | ||
| 726 | bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24; | 734 | bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24; |
| 727 | mode_rate = intel_dp_link_required(mode->clock, bpp); | 735 | mode_rate = intel_dp_link_required(adjusted_mode->clock, bpp); |
| 728 | 736 | ||
| 729 | for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { | 737 | for (clock = 0; clock <= max_clock; clock++) { |
| 730 | for (clock = 0; clock <= max_clock; clock++) { | 738 | for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { |
| 731 | int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); | 739 | int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); |
| 732 | 740 | ||
| 733 | if (mode_rate <= link_avail) { | 741 | if (mode_rate <= link_avail) { |
| @@ -786,8 +794,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
| 786 | struct drm_display_mode *adjusted_mode) | 794 | struct drm_display_mode *adjusted_mode) |
| 787 | { | 795 | { |
| 788 | struct drm_device *dev = crtc->dev; | 796 | struct drm_device *dev = crtc->dev; |
| 789 | struct drm_mode_config *mode_config = &dev->mode_config; | 797 | struct intel_encoder *encoder; |
| 790 | struct drm_encoder *encoder; | ||
| 791 | struct drm_i915_private *dev_priv = dev->dev_private; | 798 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 792 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 799 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 793 | int lane_count = 4; | 800 | int lane_count = 4; |
| @@ -797,13 +804,9 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
| 797 | /* | 804 | /* |
| 798 | * Find the lane count in the intel_encoder private | 805 | * Find the lane count in the intel_encoder private |
| 799 | */ | 806 | */ |
| 800 | list_for_each_entry(encoder, &mode_config->encoder_list, head) { | 807 | for_each_encoder_on_crtc(dev, crtc, encoder) { |
| 801 | struct intel_dp *intel_dp; | 808 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
| 802 | |||
| 803 | if (encoder->crtc != crtc) | ||
| 804 | continue; | ||
| 805 | 809 | ||
| 806 | intel_dp = enc_to_intel_dp(encoder); | ||
| 807 | if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT || | 810 | if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT || |
| 808 | intel_dp->base.type == INTEL_OUTPUT_EDP) | 811 | intel_dp->base.type == INTEL_OUTPUT_EDP) |
| 809 | { | 812 | { |
| @@ -1922,7 +1925,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) | |||
| 1922 | DP |= DP_LINK_TRAIN_OFF; | 1925 | DP |= DP_LINK_TRAIN_OFF; |
| 1923 | } | 1926 | } |
| 1924 | 1927 | ||
| 1925 | if (!HAS_PCH_CPT(dev) && | 1928 | if (HAS_PCH_IBX(dev) && |
| 1926 | I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) { | 1929 | I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) { |
| 1927 | struct drm_crtc *crtc = intel_dp->base.base.crtc; | 1930 | struct drm_crtc *crtc = intel_dp->base.base.crtc; |
| 1928 | 1931 | ||
| @@ -2099,25 +2102,23 @@ g4x_dp_detect(struct intel_dp *intel_dp) | |||
| 2099 | { | 2102 | { |
| 2100 | struct drm_device *dev = intel_dp->base.base.dev; | 2103 | struct drm_device *dev = intel_dp->base.base.dev; |
| 2101 | struct drm_i915_private *dev_priv = dev->dev_private; | 2104 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 2102 | uint32_t temp, bit; | 2105 | uint32_t bit; |
| 2103 | 2106 | ||
| 2104 | switch (intel_dp->output_reg) { | 2107 | switch (intel_dp->output_reg) { |
| 2105 | case DP_B: | 2108 | case DP_B: |
| 2106 | bit = DPB_HOTPLUG_INT_STATUS; | 2109 | bit = DPB_HOTPLUG_LIVE_STATUS; |
| 2107 | break; | 2110 | break; |
| 2108 | case DP_C: | 2111 | case DP_C: |
| 2109 | bit = DPC_HOTPLUG_INT_STATUS; | 2112 | bit = DPC_HOTPLUG_LIVE_STATUS; |
| 2110 | break; | 2113 | break; |
| 2111 | case DP_D: | 2114 | case DP_D: |
| 2112 | bit = DPD_HOTPLUG_INT_STATUS; | 2115 | bit = DPD_HOTPLUG_LIVE_STATUS; |
| 2113 | break; | 2116 | break; |
| 2114 | default: | 2117 | default: |
| 2115 | return connector_status_unknown; | 2118 | return connector_status_unknown; |
| 2116 | } | 2119 | } |
| 2117 | 2120 | ||
| 2118 | temp = I915_READ(PORT_HOTPLUG_STAT); | 2121 | if ((I915_READ(PORT_HOTPLUG_STAT) & bit) == 0) |
| 2119 | |||
| 2120 | if ((temp & bit) == 0) | ||
| 2121 | return connector_status_disconnected; | 2122 | return connector_status_disconnected; |
| 2122 | 2123 | ||
| 2123 | return intel_dp_detect_dpcd(intel_dp); | 2124 | return intel_dp_detect_dpcd(intel_dp); |
| @@ -2399,16 +2400,11 @@ int | |||
| 2399 | intel_trans_dp_port_sel(struct drm_crtc *crtc) | 2400 | intel_trans_dp_port_sel(struct drm_crtc *crtc) |
| 2400 | { | 2401 | { |
| 2401 | struct drm_device *dev = crtc->dev; | 2402 | struct drm_device *dev = crtc->dev; |
| 2402 | struct drm_mode_config *mode_config = &dev->mode_config; | 2403 | struct intel_encoder *encoder; |
| 2403 | struct drm_encoder *encoder; | ||
| 2404 | |||
| 2405 | list_for_each_entry(encoder, &mode_config->encoder_list, head) { | ||
| 2406 | struct intel_dp *intel_dp; | ||
| 2407 | 2404 | ||
| 2408 | if (encoder->crtc != crtc) | 2405 | for_each_encoder_on_crtc(dev, crtc, encoder) { |
| 2409 | continue; | 2406 | struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); |
| 2410 | 2407 | ||
| 2411 | intel_dp = enc_to_intel_dp(encoder); | ||
| 2412 | if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT || | 2408 | if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT || |
| 2413 | intel_dp->base.type == INTEL_OUTPUT_EDP) | 2409 | intel_dp->base.type == INTEL_OUTPUT_EDP) |
| 2414 | return intel_dp->output_reg; | 2410 | return intel_dp->output_reg; |
| @@ -2520,19 +2516,19 @@ intel_dp_init(struct drm_device *dev, int output_reg) | |||
| 2520 | case DP_B: | 2516 | case DP_B: |
| 2521 | case PCH_DP_B: | 2517 | case PCH_DP_B: |
| 2522 | dev_priv->hotplug_supported_mask |= | 2518 | dev_priv->hotplug_supported_mask |= |
| 2523 | HDMIB_HOTPLUG_INT_STATUS; | 2519 | DPB_HOTPLUG_INT_STATUS; |
| 2524 | name = "DPDDC-B"; | 2520 | name = "DPDDC-B"; |
| 2525 | break; | 2521 | break; |
| 2526 | case DP_C: | 2522 | case DP_C: |
| 2527 | case PCH_DP_C: | 2523 | case PCH_DP_C: |
| 2528 | dev_priv->hotplug_supported_mask |= | 2524 | dev_priv->hotplug_supported_mask |= |
| 2529 | HDMIC_HOTPLUG_INT_STATUS; | 2525 | DPC_HOTPLUG_INT_STATUS; |
| 2530 | name = "DPDDC-C"; | 2526 | name = "DPDDC-C"; |
| 2531 | break; | 2527 | break; |
| 2532 | case DP_D: | 2528 | case DP_D: |
| 2533 | case PCH_DP_D: | 2529 | case PCH_DP_D: |
| 2534 | dev_priv->hotplug_supported_mask |= | 2530 | dev_priv->hotplug_supported_mask |= |
| 2535 | HDMID_HOTPLUG_INT_STATUS; | 2531 | DPD_HOTPLUG_INT_STATUS; |
| 2536 | name = "DPDDC-D"; | 2532 | name = "DPDDC-D"; |
| 2537 | break; | 2533 | break; |
| 2538 | } | 2534 | } |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 3e0918834e7e..b7859e7110a7 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
| @@ -169,6 +169,7 @@ struct intel_crtc { | |||
| 169 | u8 lut_r[256], lut_g[256], lut_b[256]; | 169 | u8 lut_r[256], lut_g[256], lut_b[256]; |
| 170 | int dpms_mode; | 170 | int dpms_mode; |
| 171 | bool active; /* is the crtc on? independent of the dpms mode */ | 171 | bool active; /* is the crtc on? independent of the dpms mode */ |
| 172 | bool primary_disabled; /* is the crtc obscured by a plane? */ | ||
| 172 | bool busy; /* is scanout buffer being updated frequently? */ | 173 | bool busy; /* is scanout buffer being updated frequently? */ |
| 173 | struct timer_list idle_timer; | 174 | struct timer_list idle_timer; |
| 174 | bool lowfreq_avail; | 175 | bool lowfreq_avail; |
| @@ -176,6 +177,11 @@ struct intel_crtc { | |||
| 176 | struct intel_unpin_work *unpin_work; | 177 | struct intel_unpin_work *unpin_work; |
| 177 | int fdi_lanes; | 178 | int fdi_lanes; |
| 178 | 179 | ||
| 180 | /* Display surface base address adjustement for pageflips. Note that on | ||
| 181 | * gen4+ this only adjusts up to a tile, offsets within a tile are | ||
| 182 | * handled in the hw itself (with the TILEOFF register). */ | ||
| 183 | unsigned long dspaddr_offset; | ||
| 184 | |||
| 179 | struct drm_i915_gem_object *cursor_bo; | 185 | struct drm_i915_gem_object *cursor_bo; |
| 180 | uint32_t cursor_addr; | 186 | uint32_t cursor_addr; |
| 181 | int16_t cursor_x, cursor_y; | 187 | int16_t cursor_x, cursor_y; |
| @@ -191,7 +197,6 @@ struct intel_plane { | |||
| 191 | struct drm_plane base; | 197 | struct drm_plane base; |
| 192 | enum pipe pipe; | 198 | enum pipe pipe; |
| 193 | struct drm_i915_gem_object *obj; | 199 | struct drm_i915_gem_object *obj; |
| 194 | bool primary_disabled; | ||
| 195 | int max_downscale; | 200 | int max_downscale; |
| 196 | u32 lut_r[1024], lut_g[1024], lut_b[1024]; | 201 | u32 lut_r[1024], lut_g[1024], lut_b[1024]; |
| 197 | void (*update_plane)(struct drm_plane *plane, | 202 | void (*update_plane)(struct drm_plane *plane, |
| @@ -301,6 +306,8 @@ struct intel_hdmi { | |||
| 301 | enum hdmi_force_audio force_audio; | 306 | enum hdmi_force_audio force_audio; |
| 302 | void (*write_infoframe)(struct drm_encoder *encoder, | 307 | void (*write_infoframe)(struct drm_encoder *encoder, |
| 303 | struct dip_infoframe *frame); | 308 | struct dip_infoframe *frame); |
| 309 | void (*set_infoframes)(struct drm_encoder *encoder, | ||
| 310 | struct drm_display_mode *adjusted_mode); | ||
| 304 | }; | 311 | }; |
| 305 | 312 | ||
| 306 | static inline struct drm_crtc * | 313 | static inline struct drm_crtc * |
| @@ -343,9 +350,6 @@ extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector) | |||
| 343 | extern void intel_crt_init(struct drm_device *dev); | 350 | extern void intel_crt_init(struct drm_device *dev); |
| 344 | extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); | 351 | extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); |
| 345 | extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder); | 352 | extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder); |
| 346 | extern void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, | ||
| 347 | struct drm_display_mode *adjusted_mode); | ||
| 348 | extern void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder); | ||
| 349 | extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if); | 353 | extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if); |
| 350 | extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, | 354 | extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, |
| 351 | bool is_sdvob); | 355 | bool is_sdvob); |
| @@ -360,6 +364,8 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
| 360 | struct drm_display_mode *adjusted_mode); | 364 | struct drm_display_mode *adjusted_mode); |
| 361 | extern bool intel_dpd_is_edp(struct drm_device *dev); | 365 | extern bool intel_dpd_is_edp(struct drm_device *dev); |
| 362 | extern void intel_edp_link_config(struct intel_encoder *, int *, int *); | 366 | extern void intel_edp_link_config(struct intel_encoder *, int *, int *); |
| 367 | extern int intel_edp_target_clock(struct intel_encoder *, | ||
| 368 | struct drm_display_mode *mode); | ||
| 363 | extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder); | 369 | extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder); |
| 364 | extern int intel_plane_init(struct drm_device *dev, enum pipe pipe); | 370 | extern int intel_plane_init(struct drm_device *dev, enum pipe pipe); |
| 365 | extern void intel_flush_display_plane(struct drm_i915_private *dev_priv, | 371 | extern void intel_flush_display_plane(struct drm_i915_private *dev_priv, |
| @@ -372,13 +378,14 @@ extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, | |||
| 372 | struct drm_display_mode *adjusted_mode); | 378 | struct drm_display_mode *adjusted_mode); |
| 373 | extern void intel_pch_panel_fitting(struct drm_device *dev, | 379 | extern void intel_pch_panel_fitting(struct drm_device *dev, |
| 374 | int fitting_mode, | 380 | int fitting_mode, |
| 375 | struct drm_display_mode *mode, | 381 | const struct drm_display_mode *mode, |
| 376 | struct drm_display_mode *adjusted_mode); | 382 | struct drm_display_mode *adjusted_mode); |
| 377 | extern u32 intel_panel_get_max_backlight(struct drm_device *dev); | 383 | extern u32 intel_panel_get_max_backlight(struct drm_device *dev); |
| 378 | extern u32 intel_panel_get_backlight(struct drm_device *dev); | 384 | extern u32 intel_panel_get_backlight(struct drm_device *dev); |
| 379 | extern void intel_panel_set_backlight(struct drm_device *dev, u32 level); | 385 | extern void intel_panel_set_backlight(struct drm_device *dev, u32 level); |
| 380 | extern int intel_panel_setup_backlight(struct drm_device *dev); | 386 | extern int intel_panel_setup_backlight(struct drm_device *dev); |
| 381 | extern void intel_panel_enable_backlight(struct drm_device *dev); | 387 | extern void intel_panel_enable_backlight(struct drm_device *dev, |
| 388 | enum pipe pipe); | ||
| 382 | extern void intel_panel_disable_backlight(struct drm_device *dev); | 389 | extern void intel_panel_disable_backlight(struct drm_device *dev); |
| 383 | extern void intel_panel_destroy_backlight(struct drm_device *dev); | 390 | extern void intel_panel_destroy_backlight(struct drm_device *dev); |
| 384 | extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); | 391 | extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); |
| @@ -423,9 +430,6 @@ extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, | |||
| 423 | extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, | 430 | extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, |
| 424 | u16 *blue, int regno); | 431 | u16 *blue, int regno); |
| 425 | extern void intel_enable_clock_gating(struct drm_device *dev); | 432 | extern void intel_enable_clock_gating(struct drm_device *dev); |
| 426 | extern void ironlake_disable_rc6(struct drm_device *dev); | ||
| 427 | extern void ironlake_enable_drps(struct drm_device *dev); | ||
| 428 | extern void ironlake_disable_drps(struct drm_device *dev); | ||
| 429 | 433 | ||
| 430 | extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, | 434 | extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, |
| 431 | struct drm_i915_gem_object *obj, | 435 | struct drm_i915_gem_object *obj, |
| @@ -492,10 +496,10 @@ extern void intel_update_fbc(struct drm_device *dev); | |||
| 492 | extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv); | 496 | extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv); |
| 493 | extern void intel_gpu_ips_teardown(void); | 497 | extern void intel_gpu_ips_teardown(void); |
| 494 | 498 | ||
| 495 | extern void gen6_enable_rps(struct drm_i915_private *dev_priv); | 499 | extern void intel_enable_gt_powersave(struct drm_device *dev); |
| 496 | extern void gen6_update_ring_freq(struct drm_i915_private *dev_priv); | 500 | extern void intel_disable_gt_powersave(struct drm_device *dev); |
| 497 | extern void gen6_disable_rps(struct drm_device *dev); | 501 | extern void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv); |
| 498 | extern void intel_init_emon(struct drm_device *dev); | 502 | extern void ironlake_teardown_rc6(struct drm_device *dev); |
| 499 | 503 | ||
| 500 | extern void intel_ddi_dpms(struct drm_encoder *encoder, int mode); | 504 | extern void intel_ddi_dpms(struct drm_encoder *encoder, int mode); |
| 501 | extern void intel_ddi_mode_set(struct drm_encoder *encoder, | 505 | extern void intel_ddi_mode_set(struct drm_encoder *encoder, |
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 60ba50b956f2..36c542e5036b 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c | |||
| @@ -136,7 +136,7 @@ static int intel_dvo_mode_valid(struct drm_connector *connector, | |||
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | static bool intel_dvo_mode_fixup(struct drm_encoder *encoder, | 138 | static bool intel_dvo_mode_fixup(struct drm_encoder *encoder, |
| 139 | struct drm_display_mode *mode, | 139 | const struct drm_display_mode *mode, |
| 140 | struct drm_display_mode *adjusted_mode) | 140 | struct drm_display_mode *adjusted_mode) |
| 141 | { | 141 | { |
| 142 | struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); | 142 | struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); |
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index bf8690720a0c..97f673523b97 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c | |||
| @@ -65,7 +65,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev, | |||
| 65 | struct drm_i915_private *dev_priv = dev->dev_private; | 65 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 66 | struct fb_info *info; | 66 | struct fb_info *info; |
| 67 | struct drm_framebuffer *fb; | 67 | struct drm_framebuffer *fb; |
| 68 | struct drm_mode_fb_cmd2 mode_cmd; | 68 | struct drm_mode_fb_cmd2 mode_cmd = {}; |
| 69 | struct drm_i915_gem_object *obj; | 69 | struct drm_i915_gem_object *obj; |
| 70 | struct device *device = &dev->pdev->dev; | 70 | struct device *device = &dev->pdev->dev; |
| 71 | int size, ret; | 71 | int size, ret; |
| @@ -140,7 +140,9 @@ static int intelfb_create(struct intel_fbdev *ifbdev, | |||
| 140 | info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset; | 140 | info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset; |
| 141 | info->fix.smem_len = size; | 141 | info->fix.smem_len = size; |
| 142 | 142 | ||
| 143 | info->screen_base = ioremap_wc(dev->agp->base + obj->gtt_offset, size); | 143 | info->screen_base = |
| 144 | ioremap_wc(dev_priv->mm.gtt_base_addr + obj->gtt_offset, | ||
| 145 | size); | ||
| 144 | if (!info->screen_base) { | 146 | if (!info->screen_base) { |
| 145 | ret = -ENOSPC; | 147 | ret = -ENOSPC; |
| 146 | goto out_unpin; | 148 | goto out_unpin; |
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 2ead3bf7c21d..98f602427eb8 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
| @@ -37,6 +37,19 @@ | |||
| 37 | #include "i915_drm.h" | 37 | #include "i915_drm.h" |
| 38 | #include "i915_drv.h" | 38 | #include "i915_drv.h" |
| 39 | 39 | ||
| 40 | static void | ||
| 41 | assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi) | ||
| 42 | { | ||
| 43 | struct drm_device *dev = intel_hdmi->base.base.dev; | ||
| 44 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 45 | uint32_t enabled_bits; | ||
| 46 | |||
| 47 | enabled_bits = IS_HASWELL(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE; | ||
| 48 | |||
| 49 | WARN(I915_READ(intel_hdmi->sdvox_reg) & enabled_bits, | ||
| 50 | "HDMI port enabled, expecting disabled\n"); | ||
| 51 | } | ||
| 52 | |||
| 40 | struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) | 53 | struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) |
| 41 | { | 54 | { |
| 42 | return container_of(encoder, struct intel_hdmi, base.base); | 55 | return container_of(encoder, struct intel_hdmi, base.base); |
| @@ -121,36 +134,31 @@ static void g4x_write_infoframe(struct drm_encoder *encoder, | |||
| 121 | uint32_t *data = (uint32_t *)frame; | 134 | uint32_t *data = (uint32_t *)frame; |
| 122 | struct drm_device *dev = encoder->dev; | 135 | struct drm_device *dev = encoder->dev; |
| 123 | struct drm_i915_private *dev_priv = dev->dev_private; | 136 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 124 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | ||
| 125 | u32 val = I915_READ(VIDEO_DIP_CTL); | 137 | u32 val = I915_READ(VIDEO_DIP_CTL); |
| 126 | unsigned i, len = DIP_HEADER_SIZE + frame->len; | 138 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
| 127 | 139 | ||
| 128 | val &= ~VIDEO_DIP_PORT_MASK; | 140 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
| 129 | if (intel_hdmi->sdvox_reg == SDVOB) | ||
| 130 | val |= VIDEO_DIP_PORT_B; | ||
| 131 | else if (intel_hdmi->sdvox_reg == SDVOC) | ||
| 132 | val |= VIDEO_DIP_PORT_C; | ||
| 133 | else | ||
| 134 | return; | ||
| 135 | 141 | ||
| 136 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ | 142 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
| 137 | val |= g4x_infoframe_index(frame); | 143 | val |= g4x_infoframe_index(frame); |
| 138 | 144 | ||
| 139 | val &= ~g4x_infoframe_enable(frame); | 145 | val &= ~g4x_infoframe_enable(frame); |
| 140 | val |= VIDEO_DIP_ENABLE; | ||
| 141 | 146 | ||
| 142 | I915_WRITE(VIDEO_DIP_CTL, val); | 147 | I915_WRITE(VIDEO_DIP_CTL, val); |
| 143 | 148 | ||
| 149 | mmiowb(); | ||
| 144 | for (i = 0; i < len; i += 4) { | 150 | for (i = 0; i < len; i += 4) { |
| 145 | I915_WRITE(VIDEO_DIP_DATA, *data); | 151 | I915_WRITE(VIDEO_DIP_DATA, *data); |
| 146 | data++; | 152 | data++; |
| 147 | } | 153 | } |
| 154 | mmiowb(); | ||
| 148 | 155 | ||
| 149 | val |= g4x_infoframe_enable(frame); | 156 | val |= g4x_infoframe_enable(frame); |
| 150 | val &= ~VIDEO_DIP_FREQ_MASK; | 157 | val &= ~VIDEO_DIP_FREQ_MASK; |
| 151 | val |= VIDEO_DIP_FREQ_VSYNC; | 158 | val |= VIDEO_DIP_FREQ_VSYNC; |
| 152 | 159 | ||
| 153 | I915_WRITE(VIDEO_DIP_CTL, val); | 160 | I915_WRITE(VIDEO_DIP_CTL, val); |
| 161 | POSTING_READ(VIDEO_DIP_CTL); | ||
| 154 | } | 162 | } |
| 155 | 163 | ||
| 156 | static void ibx_write_infoframe(struct drm_encoder *encoder, | 164 | static void ibx_write_infoframe(struct drm_encoder *encoder, |
| @@ -160,46 +168,32 @@ static void ibx_write_infoframe(struct drm_encoder *encoder, | |||
| 160 | struct drm_device *dev = encoder->dev; | 168 | struct drm_device *dev = encoder->dev; |
| 161 | struct drm_i915_private *dev_priv = dev->dev_private; | 169 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 162 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 170 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
| 163 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | ||
| 164 | int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); | 171 | int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
| 165 | unsigned i, len = DIP_HEADER_SIZE + frame->len; | 172 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
| 166 | u32 val = I915_READ(reg); | 173 | u32 val = I915_READ(reg); |
| 167 | 174 | ||
| 168 | val &= ~VIDEO_DIP_PORT_MASK; | 175 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
| 169 | switch (intel_hdmi->sdvox_reg) { | ||
| 170 | case HDMIB: | ||
| 171 | val |= VIDEO_DIP_PORT_B; | ||
| 172 | break; | ||
| 173 | case HDMIC: | ||
| 174 | val |= VIDEO_DIP_PORT_C; | ||
| 175 | break; | ||
| 176 | case HDMID: | ||
| 177 | val |= VIDEO_DIP_PORT_D; | ||
| 178 | break; | ||
| 179 | default: | ||
| 180 | return; | ||
| 181 | } | ||
| 182 | |||
| 183 | intel_wait_for_vblank(dev, intel_crtc->pipe); | ||
| 184 | 176 | ||
| 185 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ | 177 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
| 186 | val |= g4x_infoframe_index(frame); | 178 | val |= g4x_infoframe_index(frame); |
| 187 | 179 | ||
| 188 | val &= ~g4x_infoframe_enable(frame); | 180 | val &= ~g4x_infoframe_enable(frame); |
| 189 | val |= VIDEO_DIP_ENABLE; | ||
| 190 | 181 | ||
| 191 | I915_WRITE(reg, val); | 182 | I915_WRITE(reg, val); |
| 192 | 183 | ||
| 184 | mmiowb(); | ||
| 193 | for (i = 0; i < len; i += 4) { | 185 | for (i = 0; i < len; i += 4) { |
| 194 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); | 186 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); |
| 195 | data++; | 187 | data++; |
| 196 | } | 188 | } |
| 189 | mmiowb(); | ||
| 197 | 190 | ||
| 198 | val |= g4x_infoframe_enable(frame); | 191 | val |= g4x_infoframe_enable(frame); |
| 199 | val &= ~VIDEO_DIP_FREQ_MASK; | 192 | val &= ~VIDEO_DIP_FREQ_MASK; |
| 200 | val |= VIDEO_DIP_FREQ_VSYNC; | 193 | val |= VIDEO_DIP_FREQ_VSYNC; |
| 201 | 194 | ||
| 202 | I915_WRITE(reg, val); | 195 | I915_WRITE(reg, val); |
| 196 | POSTING_READ(reg); | ||
| 203 | } | 197 | } |
| 204 | 198 | ||
| 205 | static void cpt_write_infoframe(struct drm_encoder *encoder, | 199 | static void cpt_write_infoframe(struct drm_encoder *encoder, |
| @@ -213,32 +207,31 @@ static void cpt_write_infoframe(struct drm_encoder *encoder, | |||
| 213 | unsigned i, len = DIP_HEADER_SIZE + frame->len; | 207 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
| 214 | u32 val = I915_READ(reg); | 208 | u32 val = I915_READ(reg); |
| 215 | 209 | ||
| 216 | intel_wait_for_vblank(dev, intel_crtc->pipe); | 210 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
| 217 | 211 | ||
| 218 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ | 212 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
| 219 | val |= g4x_infoframe_index(frame); | 213 | val |= g4x_infoframe_index(frame); |
| 220 | 214 | ||
| 221 | /* The DIP control register spec says that we need to update the AVI | 215 | /* The DIP control register spec says that we need to update the AVI |
| 222 | * infoframe without clearing its enable bit */ | 216 | * infoframe without clearing its enable bit */ |
| 223 | if (frame->type == DIP_TYPE_AVI) | 217 | if (frame->type != DIP_TYPE_AVI) |
| 224 | val |= VIDEO_DIP_ENABLE_AVI; | ||
| 225 | else | ||
| 226 | val &= ~g4x_infoframe_enable(frame); | 218 | val &= ~g4x_infoframe_enable(frame); |
| 227 | 219 | ||
| 228 | val |= VIDEO_DIP_ENABLE; | ||
| 229 | |||
| 230 | I915_WRITE(reg, val); | 220 | I915_WRITE(reg, val); |
| 231 | 221 | ||
| 222 | mmiowb(); | ||
| 232 | for (i = 0; i < len; i += 4) { | 223 | for (i = 0; i < len; i += 4) { |
| 233 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); | 224 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); |
| 234 | data++; | 225 | data++; |
| 235 | } | 226 | } |
| 227 | mmiowb(); | ||
| 236 | 228 | ||
| 237 | val |= g4x_infoframe_enable(frame); | 229 | val |= g4x_infoframe_enable(frame); |
| 238 | val &= ~VIDEO_DIP_FREQ_MASK; | 230 | val &= ~VIDEO_DIP_FREQ_MASK; |
| 239 | val |= VIDEO_DIP_FREQ_VSYNC; | 231 | val |= VIDEO_DIP_FREQ_VSYNC; |
| 240 | 232 | ||
| 241 | I915_WRITE(reg, val); | 233 | I915_WRITE(reg, val); |
| 234 | POSTING_READ(reg); | ||
| 242 | } | 235 | } |
| 243 | 236 | ||
| 244 | static void vlv_write_infoframe(struct drm_encoder *encoder, | 237 | static void vlv_write_infoframe(struct drm_encoder *encoder, |
| @@ -252,26 +245,28 @@ static void vlv_write_infoframe(struct drm_encoder *encoder, | |||
| 252 | unsigned i, len = DIP_HEADER_SIZE + frame->len; | 245 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
| 253 | u32 val = I915_READ(reg); | 246 | u32 val = I915_READ(reg); |
| 254 | 247 | ||
| 255 | intel_wait_for_vblank(dev, intel_crtc->pipe); | 248 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
| 256 | 249 | ||
| 257 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ | 250 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
| 258 | val |= g4x_infoframe_index(frame); | 251 | val |= g4x_infoframe_index(frame); |
| 259 | 252 | ||
| 260 | val &= ~g4x_infoframe_enable(frame); | 253 | val &= ~g4x_infoframe_enable(frame); |
| 261 | val |= VIDEO_DIP_ENABLE; | ||
| 262 | 254 | ||
| 263 | I915_WRITE(reg, val); | 255 | I915_WRITE(reg, val); |
| 264 | 256 | ||
| 257 | mmiowb(); | ||
| 265 | for (i = 0; i < len; i += 4) { | 258 | for (i = 0; i < len; i += 4) { |
| 266 | I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data); | 259 | I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data); |
| 267 | data++; | 260 | data++; |
| 268 | } | 261 | } |
| 262 | mmiowb(); | ||
| 269 | 263 | ||
| 270 | val |= g4x_infoframe_enable(frame); | 264 | val |= g4x_infoframe_enable(frame); |
| 271 | val &= ~VIDEO_DIP_FREQ_MASK; | 265 | val &= ~VIDEO_DIP_FREQ_MASK; |
| 272 | val |= VIDEO_DIP_FREQ_VSYNC; | 266 | val |= VIDEO_DIP_FREQ_VSYNC; |
| 273 | 267 | ||
| 274 | I915_WRITE(reg, val); | 268 | I915_WRITE(reg, val); |
| 269 | POSTING_READ(reg); | ||
| 275 | } | 270 | } |
| 276 | 271 | ||
| 277 | static void hsw_write_infoframe(struct drm_encoder *encoder, | 272 | static void hsw_write_infoframe(struct drm_encoder *encoder, |
| @@ -289,18 +284,19 @@ static void hsw_write_infoframe(struct drm_encoder *encoder, | |||
| 289 | if (data_reg == 0) | 284 | if (data_reg == 0) |
| 290 | return; | 285 | return; |
| 291 | 286 | ||
| 292 | intel_wait_for_vblank(dev, intel_crtc->pipe); | ||
| 293 | |||
| 294 | val &= ~hsw_infoframe_enable(frame); | 287 | val &= ~hsw_infoframe_enable(frame); |
| 295 | I915_WRITE(ctl_reg, val); | 288 | I915_WRITE(ctl_reg, val); |
| 296 | 289 | ||
| 290 | mmiowb(); | ||
| 297 | for (i = 0; i < len; i += 4) { | 291 | for (i = 0; i < len; i += 4) { |
| 298 | I915_WRITE(data_reg + i, *data); | 292 | I915_WRITE(data_reg + i, *data); |
| 299 | data++; | 293 | data++; |
| 300 | } | 294 | } |
| 295 | mmiowb(); | ||
| 301 | 296 | ||
| 302 | val |= hsw_infoframe_enable(frame); | 297 | val |= hsw_infoframe_enable(frame); |
| 303 | I915_WRITE(ctl_reg, val); | 298 | I915_WRITE(ctl_reg, val); |
| 299 | POSTING_READ(ctl_reg); | ||
| 304 | } | 300 | } |
| 305 | 301 | ||
| 306 | static void intel_set_infoframe(struct drm_encoder *encoder, | 302 | static void intel_set_infoframe(struct drm_encoder *encoder, |
| @@ -308,14 +304,11 @@ static void intel_set_infoframe(struct drm_encoder *encoder, | |||
| 308 | { | 304 | { |
| 309 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | 305 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
| 310 | 306 | ||
| 311 | if (!intel_hdmi->has_hdmi_sink) | ||
| 312 | return; | ||
| 313 | |||
| 314 | intel_dip_infoframe_csum(frame); | 307 | intel_dip_infoframe_csum(frame); |
| 315 | intel_hdmi->write_infoframe(encoder, frame); | 308 | intel_hdmi->write_infoframe(encoder, frame); |
| 316 | } | 309 | } |
| 317 | 310 | ||
| 318 | void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, | 311 | static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, |
| 319 | struct drm_display_mode *adjusted_mode) | 312 | struct drm_display_mode *adjusted_mode) |
| 320 | { | 313 | { |
| 321 | struct dip_infoframe avi_if = { | 314 | struct dip_infoframe avi_if = { |
| @@ -330,7 +323,7 @@ void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, | |||
| 330 | intel_set_infoframe(encoder, &avi_if); | 323 | intel_set_infoframe(encoder, &avi_if); |
| 331 | } | 324 | } |
| 332 | 325 | ||
| 333 | void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) | 326 | static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) |
| 334 | { | 327 | { |
| 335 | struct dip_infoframe spd_if; | 328 | struct dip_infoframe spd_if; |
| 336 | 329 | ||
| @@ -345,6 +338,223 @@ void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) | |||
| 345 | intel_set_infoframe(encoder, &spd_if); | 338 | intel_set_infoframe(encoder, &spd_if); |
| 346 | } | 339 | } |
| 347 | 340 | ||
| 341 | static void g4x_set_infoframes(struct drm_encoder *encoder, | ||
| 342 | struct drm_display_mode *adjusted_mode) | ||
| 343 | { | ||
| 344 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; | ||
| 345 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | ||
| 346 | u32 reg = VIDEO_DIP_CTL; | ||
| 347 | u32 val = I915_READ(reg); | ||
| 348 | u32 port; | ||
| 349 | |||
| 350 | assert_hdmi_port_disabled(intel_hdmi); | ||
| 351 | |||
| 352 | /* If the registers were not initialized yet, they might be zeroes, | ||
| 353 | * which means we're selecting the AVI DIP and we're setting its | ||
| 354 | * frequency to once. This seems to really confuse the HW and make | ||
| 355 | * things stop working (the register spec says the AVI always needs to | ||
| 356 | * be sent every VSync). So here we avoid writing to the register more | ||
| 357 | * than we need and also explicitly select the AVI DIP and explicitly | ||
| 358 | * set its frequency to every VSync. Avoiding to write it twice seems to | ||
| 359 | * be enough to solve the problem, but being defensive shouldn't hurt us | ||
| 360 | * either. */ | ||
| 361 | val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; | ||
| 362 | |||
| 363 | if (!intel_hdmi->has_hdmi_sink) { | ||
| 364 | if (!(val & VIDEO_DIP_ENABLE)) | ||
| 365 | return; | ||
| 366 | val &= ~VIDEO_DIP_ENABLE; | ||
| 367 | I915_WRITE(reg, val); | ||
| 368 | POSTING_READ(reg); | ||
| 369 | return; | ||
| 370 | } | ||
| 371 | |||
| 372 | switch (intel_hdmi->sdvox_reg) { | ||
| 373 | case SDVOB: | ||
| 374 | port = VIDEO_DIP_PORT_B; | ||
| 375 | break; | ||
| 376 | case SDVOC: | ||
| 377 | port = VIDEO_DIP_PORT_C; | ||
| 378 | break; | ||
| 379 | default: | ||
| 380 | return; | ||
| 381 | } | ||
| 382 | |||
| 383 | if (port != (val & VIDEO_DIP_PORT_MASK)) { | ||
| 384 | if (val & VIDEO_DIP_ENABLE) { | ||
| 385 | val &= ~VIDEO_DIP_ENABLE; | ||
| 386 | I915_WRITE(reg, val); | ||
| 387 | POSTING_READ(reg); | ||
| 388 | } | ||
| 389 | val &= ~VIDEO_DIP_PORT_MASK; | ||
| 390 | val |= port; | ||
| 391 | } | ||
| 392 | |||
| 393 | val |= VIDEO_DIP_ENABLE; | ||
| 394 | val &= ~VIDEO_DIP_ENABLE_VENDOR; | ||
| 395 | |||
| 396 | I915_WRITE(reg, val); | ||
| 397 | POSTING_READ(reg); | ||
| 398 | |||
| 399 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); | ||
| 400 | intel_hdmi_set_spd_infoframe(encoder); | ||
| 401 | } | ||
| 402 | |||
| 403 | static void ibx_set_infoframes(struct drm_encoder *encoder, | ||
| 404 | struct drm_display_mode *adjusted_mode) | ||
| 405 | { | ||
| 406 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; | ||
| 407 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | ||
| 408 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | ||
| 409 | u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe); | ||
| 410 | u32 val = I915_READ(reg); | ||
| 411 | u32 port; | ||
| 412 | |||
| 413 | assert_hdmi_port_disabled(intel_hdmi); | ||
| 414 | |||
| 415 | /* See the big comment in g4x_set_infoframes() */ | ||
| 416 | val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; | ||
| 417 | |||
| 418 | if (!intel_hdmi->has_hdmi_sink) { | ||
| 419 | if (!(val & VIDEO_DIP_ENABLE)) | ||
| 420 | return; | ||
| 421 | val &= ~VIDEO_DIP_ENABLE; | ||
| 422 | I915_WRITE(reg, val); | ||
| 423 | POSTING_READ(reg); | ||
| 424 | return; | ||
| 425 | } | ||
| 426 | |||
| 427 | switch (intel_hdmi->sdvox_reg) { | ||
| 428 | case HDMIB: | ||
| 429 | port = VIDEO_DIP_PORT_B; | ||
| 430 | break; | ||
| 431 | case HDMIC: | ||
| 432 | port = VIDEO_DIP_PORT_C; | ||
| 433 | break; | ||
| 434 | case HDMID: | ||
| 435 | port = VIDEO_DIP_PORT_D; | ||
| 436 | break; | ||
| 437 | default: | ||
| 438 | return; | ||
| 439 | } | ||
| 440 | |||
| 441 | if (port != (val & VIDEO_DIP_PORT_MASK)) { | ||
| 442 | if (val & VIDEO_DIP_ENABLE) { | ||
| 443 | val &= ~VIDEO_DIP_ENABLE; | ||
| 444 | I915_WRITE(reg, val); | ||
| 445 | POSTING_READ(reg); | ||
| 446 | } | ||
| 447 | val &= ~VIDEO_DIP_PORT_MASK; | ||
| 448 | val |= port; | ||
| 449 | } | ||
| 450 | |||
| 451 | val |= VIDEO_DIP_ENABLE; | ||
| 452 | val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | | ||
| 453 | VIDEO_DIP_ENABLE_GCP); | ||
| 454 | |||
| 455 | I915_WRITE(reg, val); | ||
| 456 | POSTING_READ(reg); | ||
| 457 | |||
| 458 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); | ||
| 459 | intel_hdmi_set_spd_infoframe(encoder); | ||
| 460 | } | ||
| 461 | |||
| 462 | static void cpt_set_infoframes(struct drm_encoder *encoder, | ||
| 463 | struct drm_display_mode *adjusted_mode) | ||
| 464 | { | ||
| 465 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; | ||
| 466 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | ||
| 467 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | ||
| 468 | u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe); | ||
| 469 | u32 val = I915_READ(reg); | ||
| 470 | |||
| 471 | assert_hdmi_port_disabled(intel_hdmi); | ||
| 472 | |||
| 473 | /* See the big comment in g4x_set_infoframes() */ | ||
| 474 | val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; | ||
| 475 | |||
| 476 | if (!intel_hdmi->has_hdmi_sink) { | ||
| 477 | if (!(val & VIDEO_DIP_ENABLE)) | ||
| 478 | return; | ||
| 479 | val &= ~(VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI); | ||
| 480 | I915_WRITE(reg, val); | ||
| 481 | POSTING_READ(reg); | ||
| 482 | return; | ||
| 483 | } | ||
| 484 | |||
| 485 | /* Set both together, unset both together: see the spec. */ | ||
| 486 | val |= VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI; | ||
| 487 | val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | | ||
| 488 | VIDEO_DIP_ENABLE_GCP); | ||
| 489 | |||
| 490 | I915_WRITE(reg, val); | ||
| 491 | POSTING_READ(reg); | ||
| 492 | |||
| 493 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); | ||
| 494 | intel_hdmi_set_spd_infoframe(encoder); | ||
| 495 | } | ||
| 496 | |||
| 497 | static void vlv_set_infoframes(struct drm_encoder *encoder, | ||
| 498 | struct drm_display_mode *adjusted_mode) | ||
| 499 | { | ||
| 500 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; | ||
| 501 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | ||
| 502 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | ||
| 503 | u32 reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); | ||
| 504 | u32 val = I915_READ(reg); | ||
| 505 | |||
| 506 | assert_hdmi_port_disabled(intel_hdmi); | ||
| 507 | |||
| 508 | /* See the big comment in g4x_set_infoframes() */ | ||
| 509 | val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; | ||
| 510 | |||
| 511 | if (!intel_hdmi->has_hdmi_sink) { | ||
| 512 | if (!(val & VIDEO_DIP_ENABLE)) | ||
| 513 | return; | ||
| 514 | val &= ~VIDEO_DIP_ENABLE; | ||
| 515 | I915_WRITE(reg, val); | ||
| 516 | POSTING_READ(reg); | ||
| 517 | return; | ||
| 518 | } | ||
| 519 | |||
| 520 | val |= VIDEO_DIP_ENABLE; | ||
| 521 | val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | | ||
| 522 | VIDEO_DIP_ENABLE_GCP); | ||
| 523 | |||
| 524 | I915_WRITE(reg, val); | ||
| 525 | POSTING_READ(reg); | ||
| 526 | |||
| 527 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); | ||
| 528 | intel_hdmi_set_spd_infoframe(encoder); | ||
| 529 | } | ||
| 530 | |||
| 531 | static void hsw_set_infoframes(struct drm_encoder *encoder, | ||
| 532 | struct drm_display_mode *adjusted_mode) | ||
| 533 | { | ||
| 534 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; | ||
| 535 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | ||
| 536 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | ||
| 537 | u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->pipe); | ||
| 538 | u32 val = I915_READ(reg); | ||
| 539 | |||
| 540 | assert_hdmi_port_disabled(intel_hdmi); | ||
| 541 | |||
| 542 | if (!intel_hdmi->has_hdmi_sink) { | ||
| 543 | I915_WRITE(reg, 0); | ||
| 544 | POSTING_READ(reg); | ||
| 545 | return; | ||
| 546 | } | ||
| 547 | |||
| 548 | val &= ~(VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_GCP_HSW | | ||
| 549 | VIDEO_DIP_ENABLE_VS_HSW | VIDEO_DIP_ENABLE_GMP_HSW); | ||
| 550 | |||
| 551 | I915_WRITE(reg, val); | ||
| 552 | POSTING_READ(reg); | ||
| 553 | |||
| 554 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); | ||
| 555 | intel_hdmi_set_spd_infoframe(encoder); | ||
| 556 | } | ||
| 557 | |||
| 348 | static void intel_hdmi_mode_set(struct drm_encoder *encoder, | 558 | static void intel_hdmi_mode_set(struct drm_encoder *encoder, |
| 349 | struct drm_display_mode *mode, | 559 | struct drm_display_mode *mode, |
| 350 | struct drm_display_mode *adjusted_mode) | 560 | struct drm_display_mode *adjusted_mode) |
| @@ -355,7 +565,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, | |||
| 355 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | 565 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
| 356 | u32 sdvox; | 566 | u32 sdvox; |
| 357 | 567 | ||
| 358 | sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE; | 568 | sdvox = SDVO_ENCODING_HDMI; |
| 359 | if (!HAS_PCH_SPLIT(dev)) | 569 | if (!HAS_PCH_SPLIT(dev)) |
| 360 | sdvox |= intel_hdmi->color_range; | 570 | sdvox |= intel_hdmi->color_range; |
| 361 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) | 571 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
| @@ -382,14 +592,13 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, | |||
| 382 | 592 | ||
| 383 | if (HAS_PCH_CPT(dev)) | 593 | if (HAS_PCH_CPT(dev)) |
| 384 | sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe); | 594 | sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe); |
| 385 | else if (intel_crtc->pipe == 1) | 595 | else if (intel_crtc->pipe == PIPE_B) |
| 386 | sdvox |= SDVO_PIPE_B_SELECT; | 596 | sdvox |= SDVO_PIPE_B_SELECT; |
| 387 | 597 | ||
| 388 | I915_WRITE(intel_hdmi->sdvox_reg, sdvox); | 598 | I915_WRITE(intel_hdmi->sdvox_reg, sdvox); |
| 389 | POSTING_READ(intel_hdmi->sdvox_reg); | 599 | POSTING_READ(intel_hdmi->sdvox_reg); |
| 390 | 600 | ||
| 391 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); | 601 | intel_hdmi->set_infoframes(encoder, adjusted_mode); |
| 392 | intel_hdmi_set_spd_infoframe(encoder); | ||
| 393 | } | 602 | } |
| 394 | 603 | ||
| 395 | static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) | 604 | static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) |
| @@ -405,6 +614,36 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) | |||
| 405 | 614 | ||
| 406 | temp = I915_READ(intel_hdmi->sdvox_reg); | 615 | temp = I915_READ(intel_hdmi->sdvox_reg); |
| 407 | 616 | ||
| 617 | /* HW workaround for IBX, we need to move the port to transcoder A | ||
| 618 | * before disabling it. */ | ||
| 619 | if (HAS_PCH_IBX(dev)) { | ||
| 620 | struct drm_crtc *crtc = encoder->crtc; | ||
| 621 | int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1; | ||
| 622 | |||
| 623 | if (mode != DRM_MODE_DPMS_ON) { | ||
| 624 | if (temp & SDVO_PIPE_B_SELECT) { | ||
| 625 | temp &= ~SDVO_PIPE_B_SELECT; | ||
| 626 | I915_WRITE(intel_hdmi->sdvox_reg, temp); | ||
| 627 | POSTING_READ(intel_hdmi->sdvox_reg); | ||
| 628 | |||
| 629 | /* Again we need to write this twice. */ | ||
| 630 | I915_WRITE(intel_hdmi->sdvox_reg, temp); | ||
| 631 | POSTING_READ(intel_hdmi->sdvox_reg); | ||
| 632 | |||
| 633 | /* Transcoder selection bits only update | ||
| 634 | * effectively on vblank. */ | ||
| 635 | if (crtc) | ||
| 636 | intel_wait_for_vblank(dev, pipe); | ||
| 637 | else | ||
| 638 | msleep(50); | ||
| 639 | } | ||
| 640 | } else { | ||
| 641 | /* Restore the transcoder select bit. */ | ||
| 642 | if (pipe == PIPE_B) | ||
| 643 | enable_bits |= SDVO_PIPE_B_SELECT; | ||
| 644 | } | ||
| 645 | } | ||
| 646 | |||
| 408 | /* HW workaround, need to toggle enable bit off and on for 12bpc, but | 647 | /* HW workaround, need to toggle enable bit off and on for 12bpc, but |
| 409 | * we do this anyway which shows more stable in testing. | 648 | * we do this anyway which shows more stable in testing. |
| 410 | */ | 649 | */ |
| @@ -446,12 +685,33 @@ static int intel_hdmi_mode_valid(struct drm_connector *connector, | |||
| 446 | } | 685 | } |
| 447 | 686 | ||
| 448 | static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, | 687 | static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, |
| 449 | struct drm_display_mode *mode, | 688 | const struct drm_display_mode *mode, |
| 450 | struct drm_display_mode *adjusted_mode) | 689 | struct drm_display_mode *adjusted_mode) |
| 451 | { | 690 | { |
| 452 | return true; | 691 | return true; |
| 453 | } | 692 | } |
| 454 | 693 | ||
| 694 | static bool g4x_hdmi_connected(struct intel_hdmi *intel_hdmi) | ||
| 695 | { | ||
| 696 | struct drm_device *dev = intel_hdmi->base.base.dev; | ||
| 697 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 698 | uint32_t bit; | ||
| 699 | |||
| 700 | switch (intel_hdmi->sdvox_reg) { | ||
| 701 | case SDVOB: | ||
| 702 | bit = HDMIB_HOTPLUG_LIVE_STATUS; | ||
| 703 | break; | ||
| 704 | case SDVOC: | ||
| 705 | bit = HDMIC_HOTPLUG_LIVE_STATUS; | ||
| 706 | break; | ||
| 707 | default: | ||
| 708 | bit = 0; | ||
| 709 | break; | ||
| 710 | } | ||
| 711 | |||
| 712 | return I915_READ(PORT_HOTPLUG_STAT) & bit; | ||
| 713 | } | ||
| 714 | |||
| 455 | static enum drm_connector_status | 715 | static enum drm_connector_status |
| 456 | intel_hdmi_detect(struct drm_connector *connector, bool force) | 716 | intel_hdmi_detect(struct drm_connector *connector, bool force) |
| 457 | { | 717 | { |
| @@ -460,6 +720,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) | |||
| 460 | struct edid *edid; | 720 | struct edid *edid; |
| 461 | enum drm_connector_status status = connector_status_disconnected; | 721 | enum drm_connector_status status = connector_status_disconnected; |
| 462 | 722 | ||
| 723 | if (IS_G4X(connector->dev) && !g4x_hdmi_connected(intel_hdmi)) | ||
| 724 | return status; | ||
| 725 | |||
| 463 | intel_hdmi->has_hdmi_sink = false; | 726 | intel_hdmi->has_hdmi_sink = false; |
| 464 | intel_hdmi->has_audio = false; | 727 | intel_hdmi->has_audio = false; |
| 465 | edid = drm_get_edid(connector, | 728 | edid = drm_get_edid(connector, |
| @@ -633,7 +896,6 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | |||
| 633 | struct intel_encoder *intel_encoder; | 896 | struct intel_encoder *intel_encoder; |
| 634 | struct intel_connector *intel_connector; | 897 | struct intel_connector *intel_connector; |
| 635 | struct intel_hdmi *intel_hdmi; | 898 | struct intel_hdmi *intel_hdmi; |
| 636 | int i; | ||
| 637 | 899 | ||
| 638 | intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL); | 900 | intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL); |
| 639 | if (!intel_hdmi) | 901 | if (!intel_hdmi) |
| @@ -710,26 +972,19 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | |||
| 710 | 972 | ||
| 711 | if (!HAS_PCH_SPLIT(dev)) { | 973 | if (!HAS_PCH_SPLIT(dev)) { |
| 712 | intel_hdmi->write_infoframe = g4x_write_infoframe; | 974 | intel_hdmi->write_infoframe = g4x_write_infoframe; |
| 713 | I915_WRITE(VIDEO_DIP_CTL, 0); | 975 | intel_hdmi->set_infoframes = g4x_set_infoframes; |
| 714 | } else if (IS_VALLEYVIEW(dev)) { | 976 | } else if (IS_VALLEYVIEW(dev)) { |
| 715 | intel_hdmi->write_infoframe = vlv_write_infoframe; | 977 | intel_hdmi->write_infoframe = vlv_write_infoframe; |
| 716 | for_each_pipe(i) | 978 | intel_hdmi->set_infoframes = vlv_set_infoframes; |
| 717 | I915_WRITE(VLV_TVIDEO_DIP_CTL(i), 0); | ||
| 718 | } else if (IS_HASWELL(dev)) { | 979 | } else if (IS_HASWELL(dev)) { |
| 719 | /* FIXME: Haswell has a new set of DIP frame registers, but we are | ||
| 720 | * just doing the minimal required for HDMI to work at this stage. | ||
| 721 | */ | ||
| 722 | intel_hdmi->write_infoframe = hsw_write_infoframe; | 980 | intel_hdmi->write_infoframe = hsw_write_infoframe; |
| 723 | for_each_pipe(i) | 981 | intel_hdmi->set_infoframes = hsw_set_infoframes; |
| 724 | I915_WRITE(HSW_TVIDEO_DIP_CTL(i), 0); | ||
| 725 | } else if (HAS_PCH_IBX(dev)) { | 982 | } else if (HAS_PCH_IBX(dev)) { |
| 726 | intel_hdmi->write_infoframe = ibx_write_infoframe; | 983 | intel_hdmi->write_infoframe = ibx_write_infoframe; |
| 727 | for_each_pipe(i) | 984 | intel_hdmi->set_infoframes = ibx_set_infoframes; |
| 728 | I915_WRITE(TVIDEO_DIP_CTL(i), 0); | ||
| 729 | } else { | 985 | } else { |
| 730 | intel_hdmi->write_infoframe = cpt_write_infoframe; | 986 | intel_hdmi->write_infoframe = cpt_write_infoframe; |
| 731 | for_each_pipe(i) | 987 | intel_hdmi->set_infoframes = cpt_set_infoframes; |
| 732 | I915_WRITE(TVIDEO_DIP_CTL(i), 0); | ||
| 733 | } | 988 | } |
| 734 | 989 | ||
| 735 | if (IS_HASWELL(dev)) | 990 | if (IS_HASWELL(dev)) |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 08eb04c787e8..49f09a8b05e9 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
| @@ -71,6 +71,7 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector) | |||
| 71 | static void intel_lvds_enable(struct intel_lvds *intel_lvds) | 71 | static void intel_lvds_enable(struct intel_lvds *intel_lvds) |
| 72 | { | 72 | { |
| 73 | struct drm_device *dev = intel_lvds->base.base.dev; | 73 | struct drm_device *dev = intel_lvds->base.base.dev; |
| 74 | struct intel_crtc *intel_crtc = to_intel_crtc(intel_lvds->base.base.crtc); | ||
| 74 | struct drm_i915_private *dev_priv = dev->dev_private; | 75 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 75 | u32 ctl_reg, lvds_reg, stat_reg; | 76 | u32 ctl_reg, lvds_reg, stat_reg; |
| 76 | 77 | ||
| @@ -107,7 +108,7 @@ static void intel_lvds_enable(struct intel_lvds *intel_lvds) | |||
| 107 | if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000)) | 108 | if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000)) |
| 108 | DRM_ERROR("timed out waiting for panel to power on\n"); | 109 | DRM_ERROR("timed out waiting for panel to power on\n"); |
| 109 | 110 | ||
| 110 | intel_panel_enable_backlight(dev); | 111 | intel_panel_enable_backlight(dev, intel_crtc->pipe); |
| 111 | } | 112 | } |
| 112 | 113 | ||
| 113 | static void intel_lvds_disable(struct intel_lvds *intel_lvds) | 114 | static void intel_lvds_disable(struct intel_lvds *intel_lvds) |
| @@ -228,14 +229,14 @@ static inline u32 panel_fitter_scaling(u32 source, u32 target) | |||
| 228 | } | 229 | } |
| 229 | 230 | ||
| 230 | static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | 231 | static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, |
| 231 | struct drm_display_mode *mode, | 232 | const struct drm_display_mode *mode, |
| 232 | struct drm_display_mode *adjusted_mode) | 233 | struct drm_display_mode *adjusted_mode) |
| 233 | { | 234 | { |
| 234 | struct drm_device *dev = encoder->dev; | 235 | struct drm_device *dev = encoder->dev; |
| 235 | struct drm_i915_private *dev_priv = dev->dev_private; | 236 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 236 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 237 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
| 237 | struct intel_lvds *intel_lvds = to_intel_lvds(encoder); | 238 | struct intel_lvds *intel_lvds = to_intel_lvds(encoder); |
| 238 | struct drm_encoder *tmp_encoder; | 239 | struct intel_encoder *tmp_encoder; |
| 239 | u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; | 240 | u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; |
| 240 | int pipe; | 241 | int pipe; |
| 241 | 242 | ||
| @@ -246,8 +247,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
| 246 | } | 247 | } |
| 247 | 248 | ||
| 248 | /* Should never happen!! */ | 249 | /* Should never happen!! */ |
| 249 | list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, head) { | 250 | for_each_encoder_on_crtc(dev, encoder->crtc, tmp_encoder) { |
| 250 | if (tmp_encoder != encoder && tmp_encoder->crtc == encoder->crtc) { | 251 | if (&tmp_encoder->base != encoder) { |
| 251 | DRM_ERROR("Can't enable LVDS and another " | 252 | DRM_ERROR("Can't enable LVDS and another " |
| 252 | "encoder on the same pipe\n"); | 253 | "encoder on the same pipe\n"); |
| 253 | return false; | 254 | return false; |
| @@ -777,6 +778,14 @@ static const struct dmi_system_id intel_no_lvds[] = { | |||
| 777 | DMI_MATCH(DMI_BOARD_NAME, "MS-7469"), | 778 | DMI_MATCH(DMI_BOARD_NAME, "MS-7469"), |
| 778 | }, | 779 | }, |
| 779 | }, | 780 | }, |
| 781 | { | ||
| 782 | .callback = intel_no_lvds_dmi_callback, | ||
| 783 | .ident = "ZOTAC ZBOXSD-ID12/ID13", | ||
| 784 | .matches = { | ||
| 785 | DMI_MATCH(DMI_BOARD_VENDOR, "ZOTAC"), | ||
| 786 | DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"), | ||
| 787 | }, | ||
| 788 | }, | ||
| 780 | 789 | ||
| 781 | { } /* terminating entry */ | 790 | { } /* terminating entry */ |
| 782 | }; | 791 | }; |
| @@ -967,6 +976,8 @@ bool intel_lvds_init(struct drm_device *dev) | |||
| 967 | intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); | 976 | intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); |
| 968 | if (HAS_PCH_SPLIT(dev)) | 977 | if (HAS_PCH_SPLIT(dev)) |
| 969 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); | 978 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); |
| 979 | else if (IS_GEN4(dev)) | ||
| 980 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); | ||
| 970 | else | 981 | else |
| 971 | intel_encoder->crtc_mask = (1 << 1); | 982 | intel_encoder->crtc_mask = (1 << 1); |
| 972 | 983 | ||
| @@ -1074,35 +1085,14 @@ bool intel_lvds_init(struct drm_device *dev) | |||
| 1074 | goto failed; | 1085 | goto failed; |
| 1075 | 1086 | ||
| 1076 | out: | 1087 | out: |
| 1088 | /* | ||
| 1089 | * Unlock registers and just | ||
| 1090 | * leave them unlocked | ||
| 1091 | */ | ||
| 1077 | if (HAS_PCH_SPLIT(dev)) { | 1092 | if (HAS_PCH_SPLIT(dev)) { |
| 1078 | u32 pwm; | ||
| 1079 | |||
| 1080 | pipe = (I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT) ? 1 : 0; | ||
| 1081 | |||
| 1082 | /* make sure PWM is enabled and locked to the LVDS pipe */ | ||
| 1083 | pwm = I915_READ(BLC_PWM_CPU_CTL2); | ||
| 1084 | if (pipe == 0 && (pwm & PWM_PIPE_B)) | ||
| 1085 | I915_WRITE(BLC_PWM_CPU_CTL2, pwm & ~PWM_ENABLE); | ||
| 1086 | if (pipe) | ||
| 1087 | pwm |= PWM_PIPE_B; | ||
| 1088 | else | ||
| 1089 | pwm &= ~PWM_PIPE_B; | ||
| 1090 | I915_WRITE(BLC_PWM_CPU_CTL2, pwm | PWM_ENABLE); | ||
| 1091 | |||
| 1092 | pwm = I915_READ(BLC_PWM_PCH_CTL1); | ||
| 1093 | pwm |= PWM_PCH_ENABLE; | ||
| 1094 | I915_WRITE(BLC_PWM_PCH_CTL1, pwm); | ||
| 1095 | /* | ||
| 1096 | * Unlock registers and just | ||
| 1097 | * leave them unlocked | ||
| 1098 | */ | ||
| 1099 | I915_WRITE(PCH_PP_CONTROL, | 1093 | I915_WRITE(PCH_PP_CONTROL, |
| 1100 | I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); | 1094 | I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); |
| 1101 | } else { | 1095 | } else { |
| 1102 | /* | ||
| 1103 | * Unlock registers and just | ||
| 1104 | * leave them unlocked | ||
| 1105 | */ | ||
| 1106 | I915_WRITE(PP_CONTROL, | 1096 | I915_WRITE(PP_CONTROL, |
| 1107 | I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); | 1097 | I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); |
| 1108 | } | 1098 | } |
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 458743da3774..830d0dd610e1 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c | |||
| @@ -226,7 +226,7 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, | |||
| 226 | } | 226 | } |
| 227 | overlay->last_flip_req = request->seqno; | 227 | overlay->last_flip_req = request->seqno; |
| 228 | overlay->flip_tail = tail; | 228 | overlay->flip_tail = tail; |
| 229 | ret = i915_wait_request(ring, overlay->last_flip_req); | 229 | ret = i915_wait_seqno(ring, overlay->last_flip_req); |
| 230 | if (ret) | 230 | if (ret) |
| 231 | return ret; | 231 | return ret; |
| 232 | i915_gem_retire_requests(dev); | 232 | i915_gem_retire_requests(dev); |
| @@ -452,7 +452,7 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay) | |||
| 452 | if (overlay->last_flip_req == 0) | 452 | if (overlay->last_flip_req == 0) |
| 453 | return 0; | 453 | return 0; |
| 454 | 454 | ||
| 455 | ret = i915_wait_request(ring, overlay->last_flip_req); | 455 | ret = i915_wait_seqno(ring, overlay->last_flip_req); |
| 456 | if (ret) | 456 | if (ret) |
| 457 | return ret; | 457 | return ret; |
| 458 | i915_gem_retire_requests(dev); | 458 | i915_gem_retire_requests(dev); |
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 2a1625d84a69..58c7ee7238b8 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c | |||
| @@ -56,7 +56,7 @@ intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, | |||
| 56 | void | 56 | void |
| 57 | intel_pch_panel_fitting(struct drm_device *dev, | 57 | intel_pch_panel_fitting(struct drm_device *dev, |
| 58 | int fitting_mode, | 58 | int fitting_mode, |
| 59 | struct drm_display_mode *mode, | 59 | const struct drm_display_mode *mode, |
| 60 | struct drm_display_mode *adjusted_mode) | 60 | struct drm_display_mode *adjusted_mode) |
| 61 | { | 61 | { |
| 62 | struct drm_i915_private *dev_priv = dev->dev_private; | 62 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -287,9 +287,18 @@ void intel_panel_disable_backlight(struct drm_device *dev) | |||
| 287 | 287 | ||
| 288 | dev_priv->backlight_enabled = false; | 288 | dev_priv->backlight_enabled = false; |
| 289 | intel_panel_actually_set_backlight(dev, 0); | 289 | intel_panel_actually_set_backlight(dev, 0); |
| 290 | |||
| 291 | if (INTEL_INFO(dev)->gen >= 4) { | ||
| 292 | uint32_t reg; | ||
| 293 | |||
| 294 | reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; | ||
| 295 | |||
| 296 | I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE); | ||
| 297 | } | ||
| 290 | } | 298 | } |
| 291 | 299 | ||
| 292 | void intel_panel_enable_backlight(struct drm_device *dev) | 300 | void intel_panel_enable_backlight(struct drm_device *dev, |
| 301 | enum pipe pipe) | ||
| 293 | { | 302 | { |
| 294 | struct drm_i915_private *dev_priv = dev->dev_private; | 303 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 295 | 304 | ||
| @@ -298,6 +307,33 @@ void intel_panel_enable_backlight(struct drm_device *dev) | |||
| 298 | 307 | ||
| 299 | dev_priv->backlight_enabled = true; | 308 | dev_priv->backlight_enabled = true; |
| 300 | intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); | 309 | intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); |
| 310 | |||
| 311 | if (INTEL_INFO(dev)->gen >= 4) { | ||
| 312 | uint32_t reg, tmp; | ||
| 313 | |||
| 314 | reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; | ||
| 315 | |||
| 316 | |||
| 317 | tmp = I915_READ(reg); | ||
| 318 | |||
| 319 | /* Note that this can also get called through dpms changes. And | ||
| 320 | * we don't track the backlight dpms state, hence check whether | ||
| 321 | * we have to do anything first. */ | ||
| 322 | if (tmp & BLM_PWM_ENABLE) | ||
| 323 | return; | ||
| 324 | |||
| 325 | if (dev_priv->num_pipe == 3) | ||
| 326 | tmp &= ~BLM_PIPE_SELECT_IVB; | ||
| 327 | else | ||
| 328 | tmp &= ~BLM_PIPE_SELECT; | ||
| 329 | |||
| 330 | tmp |= BLM_PIPE(pipe); | ||
| 331 | tmp &= ~BLM_PWM_ENABLE; | ||
| 332 | |||
| 333 | I915_WRITE(reg, tmp); | ||
| 334 | POSTING_READ(reg); | ||
| 335 | I915_WRITE(reg, tmp | BLM_PWM_ENABLE); | ||
| 336 | } | ||
| 301 | } | 337 | } |
| 302 | 338 | ||
| 303 | static void intel_panel_init_backlight(struct drm_device *dev) | 339 | static void intel_panel_init_backlight(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d0ce2a5b1d3f..0bb69fd255a9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
| @@ -387,8 +387,6 @@ void intel_update_fbc(struct drm_device *dev) | |||
| 387 | struct drm_i915_gem_object *obj; | 387 | struct drm_i915_gem_object *obj; |
| 388 | int enable_fbc; | 388 | int enable_fbc; |
| 389 | 389 | ||
| 390 | DRM_DEBUG_KMS("\n"); | ||
| 391 | |||
| 392 | if (!i915_powersave) | 390 | if (!i915_powersave) |
| 393 | return; | 391 | return; |
| 394 | 392 | ||
| @@ -405,7 +403,9 @@ void intel_update_fbc(struct drm_device *dev) | |||
| 405 | * - going to an unsupported config (interlace, pixel multiply, etc.) | 403 | * - going to an unsupported config (interlace, pixel multiply, etc.) |
| 406 | */ | 404 | */ |
| 407 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { | 405 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { |
| 408 | if (tmp_crtc->enabled && tmp_crtc->fb) { | 406 | if (tmp_crtc->enabled && |
| 407 | !to_intel_crtc(tmp_crtc)->primary_disabled && | ||
| 408 | tmp_crtc->fb) { | ||
| 409 | if (crtc) { | 409 | if (crtc) { |
| 410 | DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); | 410 | DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); |
| 411 | dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; | 411 | dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; |
| @@ -2182,7 +2182,7 @@ bool ironlake_set_drps(struct drm_device *dev, u8 val) | |||
| 2182 | return true; | 2182 | return true; |
| 2183 | } | 2183 | } |
| 2184 | 2184 | ||
| 2185 | void ironlake_enable_drps(struct drm_device *dev) | 2185 | static void ironlake_enable_drps(struct drm_device *dev) |
| 2186 | { | 2186 | { |
| 2187 | struct drm_i915_private *dev_priv = dev->dev_private; | 2187 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 2188 | u32 rgvmodectl = I915_READ(MEMMODECTL); | 2188 | u32 rgvmodectl = I915_READ(MEMMODECTL); |
| @@ -2246,7 +2246,7 @@ void ironlake_enable_drps(struct drm_device *dev) | |||
| 2246 | getrawmonotonic(&dev_priv->last_time2); | 2246 | getrawmonotonic(&dev_priv->last_time2); |
| 2247 | } | 2247 | } |
| 2248 | 2248 | ||
| 2249 | void ironlake_disable_drps(struct drm_device *dev) | 2249 | static void ironlake_disable_drps(struct drm_device *dev) |
| 2250 | { | 2250 | { |
| 2251 | struct drm_i915_private *dev_priv = dev->dev_private; | 2251 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 2252 | u16 rgvswctl = I915_READ16(MEMSWCTL); | 2252 | u16 rgvswctl = I915_READ16(MEMSWCTL); |
| @@ -2299,10 +2299,11 @@ void gen6_set_rps(struct drm_device *dev, u8 val) | |||
| 2299 | dev_priv->cur_delay = val; | 2299 | dev_priv->cur_delay = val; |
| 2300 | } | 2300 | } |
| 2301 | 2301 | ||
| 2302 | void gen6_disable_rps(struct drm_device *dev) | 2302 | static void gen6_disable_rps(struct drm_device *dev) |
| 2303 | { | 2303 | { |
| 2304 | struct drm_i915_private *dev_priv = dev->dev_private; | 2304 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 2305 | 2305 | ||
| 2306 | I915_WRITE(GEN6_RC_CONTROL, 0); | ||
| 2306 | I915_WRITE(GEN6_RPNSWREQ, 1 << 31); | 2307 | I915_WRITE(GEN6_RPNSWREQ, 1 << 31); |
| 2307 | I915_WRITE(GEN6_PMINTRMSK, 0xffffffff); | 2308 | I915_WRITE(GEN6_PMINTRMSK, 0xffffffff); |
| 2308 | I915_WRITE(GEN6_PMIER, 0); | 2309 | I915_WRITE(GEN6_PMIER, 0); |
| @@ -2332,9 +2333,11 @@ int intel_enable_rc6(const struct drm_device *dev) | |||
| 2332 | if (INTEL_INFO(dev)->gen == 5) | 2333 | if (INTEL_INFO(dev)->gen == 5) |
| 2333 | return 0; | 2334 | return 0; |
| 2334 | 2335 | ||
| 2335 | /* Sorry Haswell, no RC6 for you for now. */ | 2336 | /* On Haswell, only RC6 is available. So let's enable it by default to |
| 2337 | * provide better testing and coverage since the beginning. | ||
| 2338 | */ | ||
| 2336 | if (IS_HASWELL(dev)) | 2339 | if (IS_HASWELL(dev)) |
| 2337 | return 0; | 2340 | return INTEL_RC6_ENABLE; |
| 2338 | 2341 | ||
| 2339 | /* | 2342 | /* |
| 2340 | * Disable rc6 on Sandybridge | 2343 | * Disable rc6 on Sandybridge |
| @@ -2347,8 +2350,9 @@ int intel_enable_rc6(const struct drm_device *dev) | |||
| 2347 | return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE); | 2350 | return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE); |
| 2348 | } | 2351 | } |
| 2349 | 2352 | ||
| 2350 | void gen6_enable_rps(struct drm_i915_private *dev_priv) | 2353 | static void gen6_enable_rps(struct drm_device *dev) |
| 2351 | { | 2354 | { |
| 2355 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 2352 | struct intel_ring_buffer *ring; | 2356 | struct intel_ring_buffer *ring; |
| 2353 | u32 rp_state_cap; | 2357 | u32 rp_state_cap; |
| 2354 | u32 gt_perf_status; | 2358 | u32 gt_perf_status; |
| @@ -2357,6 +2361,8 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
| 2357 | int rc6_mode; | 2361 | int rc6_mode; |
| 2358 | int i; | 2362 | int i; |
| 2359 | 2363 | ||
| 2364 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); | ||
| 2365 | |||
| 2360 | /* Here begins a magic sequence of register writes to enable | 2366 | /* Here begins a magic sequence of register writes to enable |
| 2361 | * auto-downclocking. | 2367 | * auto-downclocking. |
| 2362 | * | 2368 | * |
| @@ -2364,7 +2370,6 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
| 2364 | * userspace... | 2370 | * userspace... |
| 2365 | */ | 2371 | */ |
| 2366 | I915_WRITE(GEN6_RC_STATE, 0); | 2372 | I915_WRITE(GEN6_RC_STATE, 0); |
| 2367 | mutex_lock(&dev_priv->dev->struct_mutex); | ||
| 2368 | 2373 | ||
| 2369 | /* Clear the DBG now so we don't confuse earlier errors */ | 2374 | /* Clear the DBG now so we don't confuse earlier errors */ |
| 2370 | if ((gtfifodbg = I915_READ(GTFIFODBG))) { | 2375 | if ((gtfifodbg = I915_READ(GTFIFODBG))) { |
| @@ -2400,20 +2405,24 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
| 2400 | I915_WRITE(GEN6_RC6p_THRESHOLD, 100000); | 2405 | I915_WRITE(GEN6_RC6p_THRESHOLD, 100000); |
| 2401 | I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ | 2406 | I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ |
| 2402 | 2407 | ||
| 2408 | /* Check if we are enabling RC6 */ | ||
| 2403 | rc6_mode = intel_enable_rc6(dev_priv->dev); | 2409 | rc6_mode = intel_enable_rc6(dev_priv->dev); |
| 2404 | if (rc6_mode & INTEL_RC6_ENABLE) | 2410 | if (rc6_mode & INTEL_RC6_ENABLE) |
| 2405 | rc6_mask |= GEN6_RC_CTL_RC6_ENABLE; | 2411 | rc6_mask |= GEN6_RC_CTL_RC6_ENABLE; |
| 2406 | 2412 | ||
| 2407 | if (rc6_mode & INTEL_RC6p_ENABLE) | 2413 | /* We don't use those on Haswell */ |
| 2408 | rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE; | 2414 | if (!IS_HASWELL(dev)) { |
| 2415 | if (rc6_mode & INTEL_RC6p_ENABLE) | ||
| 2416 | rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE; | ||
| 2409 | 2417 | ||
| 2410 | if (rc6_mode & INTEL_RC6pp_ENABLE) | 2418 | if (rc6_mode & INTEL_RC6pp_ENABLE) |
| 2411 | rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; | 2419 | rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; |
| 2420 | } | ||
| 2412 | 2421 | ||
| 2413 | DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", | 2422 | DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", |
| 2414 | (rc6_mode & INTEL_RC6_ENABLE) ? "on" : "off", | 2423 | (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", |
| 2415 | (rc6_mode & INTEL_RC6p_ENABLE) ? "on" : "off", | 2424 | (rc6_mask & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", |
| 2416 | (rc6_mode & INTEL_RC6pp_ENABLE) ? "on" : "off"); | 2425 | (rc6_mask & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); |
| 2417 | 2426 | ||
| 2418 | I915_WRITE(GEN6_RC_CONTROL, | 2427 | I915_WRITE(GEN6_RC_CONTROL, |
| 2419 | rc6_mask | | 2428 | rc6_mask | |
| @@ -2431,10 +2440,19 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
| 2431 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, | 2440 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, |
| 2432 | dev_priv->max_delay << 24 | | 2441 | dev_priv->max_delay << 24 | |
| 2433 | dev_priv->min_delay << 16); | 2442 | dev_priv->min_delay << 16); |
| 2434 | I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000); | 2443 | |
| 2435 | I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000); | 2444 | if (IS_HASWELL(dev)) { |
| 2436 | I915_WRITE(GEN6_RP_UP_EI, 100000); | 2445 | I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); |
| 2437 | I915_WRITE(GEN6_RP_DOWN_EI, 5000000); | 2446 | I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); |
| 2447 | I915_WRITE(GEN6_RP_UP_EI, 66000); | ||
| 2448 | I915_WRITE(GEN6_RP_DOWN_EI, 350000); | ||
| 2449 | } else { | ||
| 2450 | I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000); | ||
| 2451 | I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000); | ||
| 2452 | I915_WRITE(GEN6_RP_UP_EI, 100000); | ||
| 2453 | I915_WRITE(GEN6_RP_DOWN_EI, 5000000); | ||
| 2454 | } | ||
| 2455 | |||
| 2438 | I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); | 2456 | I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); |
| 2439 | I915_WRITE(GEN6_RP_CONTROL, | 2457 | I915_WRITE(GEN6_RP_CONTROL, |
| 2440 | GEN6_RP_MEDIA_TURBO | | 2458 | GEN6_RP_MEDIA_TURBO | |
| @@ -2442,7 +2460,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
| 2442 | GEN6_RP_MEDIA_IS_GFX | | 2460 | GEN6_RP_MEDIA_IS_GFX | |
| 2443 | GEN6_RP_ENABLE | | 2461 | GEN6_RP_ENABLE | |
| 2444 | GEN6_RP_UP_BUSY_AVG | | 2462 | GEN6_RP_UP_BUSY_AVG | |
| 2445 | GEN6_RP_DOWN_IDLE_CONT); | 2463 | (IS_HASWELL(dev) ? GEN7_RP_DOWN_IDLE_AVG : GEN6_RP_DOWN_IDLE_CONT)); |
| 2446 | 2464 | ||
| 2447 | if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, | 2465 | if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, |
| 2448 | 500)) | 2466 | 500)) |
| @@ -2489,15 +2507,17 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
| 2489 | I915_WRITE(GEN6_PMINTRMSK, 0); | 2507 | I915_WRITE(GEN6_PMINTRMSK, 0); |
| 2490 | 2508 | ||
| 2491 | gen6_gt_force_wake_put(dev_priv); | 2509 | gen6_gt_force_wake_put(dev_priv); |
| 2492 | mutex_unlock(&dev_priv->dev->struct_mutex); | ||
| 2493 | } | 2510 | } |
| 2494 | 2511 | ||
| 2495 | void gen6_update_ring_freq(struct drm_i915_private *dev_priv) | 2512 | static void gen6_update_ring_freq(struct drm_device *dev) |
| 2496 | { | 2513 | { |
| 2514 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 2497 | int min_freq = 15; | 2515 | int min_freq = 15; |
| 2498 | int gpu_freq, ia_freq, max_ia_freq; | 2516 | int gpu_freq, ia_freq, max_ia_freq; |
| 2499 | int scaling_factor = 180; | 2517 | int scaling_factor = 180; |
| 2500 | 2518 | ||
| 2519 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); | ||
| 2520 | |||
| 2501 | max_ia_freq = cpufreq_quick_get_max(0); | 2521 | max_ia_freq = cpufreq_quick_get_max(0); |
| 2502 | /* | 2522 | /* |
| 2503 | * Default to measured freq if none found, PCU will ensure we don't go | 2523 | * Default to measured freq if none found, PCU will ensure we don't go |
| @@ -2509,8 +2529,6 @@ void gen6_update_ring_freq(struct drm_i915_private *dev_priv) | |||
| 2509 | /* Convert from kHz to MHz */ | 2529 | /* Convert from kHz to MHz */ |
| 2510 | max_ia_freq /= 1000; | 2530 | max_ia_freq /= 1000; |
| 2511 | 2531 | ||
| 2512 | mutex_lock(&dev_priv->dev->struct_mutex); | ||
| 2513 | |||
| 2514 | /* | 2532 | /* |
| 2515 | * For each potential GPU frequency, load a ring frequency we'd like | 2533 | * For each potential GPU frequency, load a ring frequency we'd like |
| 2516 | * to use for memory access. We do this by specifying the IA frequency | 2534 | * to use for memory access. We do this by specifying the IA frequency |
| @@ -2541,11 +2559,9 @@ void gen6_update_ring_freq(struct drm_i915_private *dev_priv) | |||
| 2541 | continue; | 2559 | continue; |
| 2542 | } | 2560 | } |
| 2543 | } | 2561 | } |
| 2544 | |||
| 2545 | mutex_unlock(&dev_priv->dev->struct_mutex); | ||
| 2546 | } | 2562 | } |
| 2547 | 2563 | ||
| 2548 | static void ironlake_teardown_rc6(struct drm_device *dev) | 2564 | void ironlake_teardown_rc6(struct drm_device *dev) |
| 2549 | { | 2565 | { |
| 2550 | struct drm_i915_private *dev_priv = dev->dev_private; | 2566 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 2551 | 2567 | ||
| @@ -2562,7 +2578,7 @@ static void ironlake_teardown_rc6(struct drm_device *dev) | |||
| 2562 | } | 2578 | } |
| 2563 | } | 2579 | } |
| 2564 | 2580 | ||
| 2565 | void ironlake_disable_rc6(struct drm_device *dev) | 2581 | static void ironlake_disable_rc6(struct drm_device *dev) |
| 2566 | { | 2582 | { |
| 2567 | struct drm_i915_private *dev_priv = dev->dev_private; | 2583 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 2568 | 2584 | ||
| @@ -2578,8 +2594,6 @@ void ironlake_disable_rc6(struct drm_device *dev) | |||
| 2578 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); | 2594 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); |
| 2579 | POSTING_READ(RSTDBYCTL); | 2595 | POSTING_READ(RSTDBYCTL); |
| 2580 | } | 2596 | } |
| 2581 | |||
| 2582 | ironlake_teardown_rc6(dev); | ||
| 2583 | } | 2597 | } |
| 2584 | 2598 | ||
| 2585 | static int ironlake_setup_rc6(struct drm_device *dev) | 2599 | static int ironlake_setup_rc6(struct drm_device *dev) |
| @@ -2601,7 +2615,7 @@ static int ironlake_setup_rc6(struct drm_device *dev) | |||
| 2601 | return 0; | 2615 | return 0; |
| 2602 | } | 2616 | } |
| 2603 | 2617 | ||
| 2604 | void ironlake_enable_rc6(struct drm_device *dev) | 2618 | static void ironlake_enable_rc6(struct drm_device *dev) |
| 2605 | { | 2619 | { |
| 2606 | struct drm_i915_private *dev_priv = dev->dev_private; | 2620 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 2607 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; | 2621 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; |
| @@ -2613,12 +2627,11 @@ void ironlake_enable_rc6(struct drm_device *dev) | |||
| 2613 | if (!intel_enable_rc6(dev)) | 2627 | if (!intel_enable_rc6(dev)) |
| 2614 | return; | 2628 | return; |
| 2615 | 2629 | ||
| 2616 | mutex_lock(&dev->struct_mutex); | 2630 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); |
| 2631 | |||
| 2617 | ret = ironlake_setup_rc6(dev); | 2632 | ret = ironlake_setup_rc6(dev); |
| 2618 | if (ret) { | 2633 | if (ret) |
| 2619 | mutex_unlock(&dev->struct_mutex); | ||
| 2620 | return; | 2634 | return; |
| 2621 | } | ||
| 2622 | 2635 | ||
| 2623 | /* | 2636 | /* |
| 2624 | * GPU can automatically power down the render unit if given a page | 2637 | * GPU can automatically power down the render unit if given a page |
| @@ -2627,7 +2640,6 @@ void ironlake_enable_rc6(struct drm_device *dev) | |||
| 2627 | ret = intel_ring_begin(ring, 6); | 2640 | ret = intel_ring_begin(ring, 6); |
| 2628 | if (ret) { | 2641 | if (ret) { |
| 2629 | ironlake_teardown_rc6(dev); | 2642 | ironlake_teardown_rc6(dev); |
| 2630 | mutex_unlock(&dev->struct_mutex); | ||
| 2631 | return; | 2643 | return; |
| 2632 | } | 2644 | } |
| 2633 | 2645 | ||
| @@ -2652,13 +2664,11 @@ void ironlake_enable_rc6(struct drm_device *dev) | |||
| 2652 | if (ret) { | 2664 | if (ret) { |
| 2653 | DRM_ERROR("failed to enable ironlake power power savings\n"); | 2665 | DRM_ERROR("failed to enable ironlake power power savings\n"); |
| 2654 | ironlake_teardown_rc6(dev); | 2666 | ironlake_teardown_rc6(dev); |
| 2655 | mutex_unlock(&dev->struct_mutex); | ||
| 2656 | return; | 2667 | return; |
| 2657 | } | 2668 | } |
| 2658 | 2669 | ||
| 2659 | I915_WRITE(PWRCTXA, dev_priv->pwrctx->gtt_offset | PWRCTX_EN); | 2670 | I915_WRITE(PWRCTXA, dev_priv->pwrctx->gtt_offset | PWRCTX_EN); |
| 2660 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); | 2671 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); |
| 2661 | mutex_unlock(&dev->struct_mutex); | ||
| 2662 | } | 2672 | } |
| 2663 | 2673 | ||
| 2664 | static unsigned long intel_pxfreq(u32 vidfreq) | 2674 | static unsigned long intel_pxfreq(u32 vidfreq) |
| @@ -3154,8 +3164,7 @@ void intel_gpu_ips_teardown(void) | |||
| 3154 | i915_mch_dev = NULL; | 3164 | i915_mch_dev = NULL; |
| 3155 | spin_unlock(&mchdev_lock); | 3165 | spin_unlock(&mchdev_lock); |
| 3156 | } | 3166 | } |
| 3157 | 3167 | static void intel_init_emon(struct drm_device *dev) | |
| 3158 | void intel_init_emon(struct drm_device *dev) | ||
| 3159 | { | 3168 | { |
| 3160 | struct drm_i915_private *dev_priv = dev->dev_private; | 3169 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 3161 | u32 lcfuse; | 3170 | u32 lcfuse; |
| @@ -3226,6 +3235,28 @@ void intel_init_emon(struct drm_device *dev) | |||
| 3226 | dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK); | 3235 | dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK); |
| 3227 | } | 3236 | } |
| 3228 | 3237 | ||
| 3238 | void intel_disable_gt_powersave(struct drm_device *dev) | ||
| 3239 | { | ||
| 3240 | if (IS_IRONLAKE_M(dev)) { | ||
| 3241 | ironlake_disable_drps(dev); | ||
| 3242 | ironlake_disable_rc6(dev); | ||
| 3243 | } else if (INTEL_INFO(dev)->gen >= 6 && !IS_VALLEYVIEW(dev)) { | ||
| 3244 | gen6_disable_rps(dev); | ||
| 3245 | } | ||
| 3246 | } | ||
| 3247 | |||
| 3248 | void intel_enable_gt_powersave(struct drm_device *dev) | ||
| 3249 | { | ||
| 3250 | if (IS_IRONLAKE_M(dev)) { | ||
| 3251 | ironlake_enable_drps(dev); | ||
| 3252 | ironlake_enable_rc6(dev); | ||
| 3253 | intel_init_emon(dev); | ||
| 3254 | } else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) { | ||
| 3255 | gen6_enable_rps(dev); | ||
| 3256 | gen6_update_ring_freq(dev); | ||
| 3257 | } | ||
| 3258 | } | ||
| 3259 | |||
| 3229 | static void ironlake_init_clock_gating(struct drm_device *dev) | 3260 | static void ironlake_init_clock_gating(struct drm_device *dev) |
| 3230 | { | 3261 | { |
| 3231 | struct drm_i915_private *dev_priv = dev->dev_private; | 3262 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -3328,8 +3359,12 @@ static void gen6_init_clock_gating(struct drm_device *dev) | |||
| 3328 | * | 3359 | * |
| 3329 | * According to the spec, bit 11 (RCCUNIT) must also be set, | 3360 | * According to the spec, bit 11 (RCCUNIT) must also be set, |
| 3330 | * but we didn't debug actual testcases to find it out. | 3361 | * but we didn't debug actual testcases to find it out. |
| 3362 | * | ||
| 3363 | * Also apply WaDisableVDSUnitClockGating and | ||
| 3364 | * WaDisableRCPBUnitClockGating. | ||
| 3331 | */ | 3365 | */ |
| 3332 | I915_WRITE(GEN6_UCGCTL2, | 3366 | I915_WRITE(GEN6_UCGCTL2, |
| 3367 | GEN7_VDSUNIT_CLOCK_GATE_DISABLE | | ||
| 3333 | GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | | 3368 | GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | |
| 3334 | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); | 3369 | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); |
| 3335 | 3370 | ||
| @@ -3357,6 +3392,9 @@ static void gen6_init_clock_gating(struct drm_device *dev) | |||
| 3357 | ILK_DPARB_CLK_GATE | | 3392 | ILK_DPARB_CLK_GATE | |
| 3358 | ILK_DPFD_CLK_GATE); | 3393 | ILK_DPFD_CLK_GATE); |
| 3359 | 3394 | ||
| 3395 | I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | | ||
| 3396 | GEN6_MBCTL_ENABLE_BOOT_FETCH); | ||
| 3397 | |||
| 3360 | for_each_pipe(pipe) { | 3398 | for_each_pipe(pipe) { |
| 3361 | I915_WRITE(DSPCNTR(pipe), | 3399 | I915_WRITE(DSPCNTR(pipe), |
| 3362 | I915_READ(DSPCNTR(pipe)) | | 3400 | I915_READ(DSPCNTR(pipe)) | |
| @@ -3377,7 +3415,7 @@ static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv) | |||
| 3377 | I915_WRITE(GEN7_FF_THREAD_MODE, reg); | 3415 | I915_WRITE(GEN7_FF_THREAD_MODE, reg); |
| 3378 | } | 3416 | } |
| 3379 | 3417 | ||
| 3380 | static void ivybridge_init_clock_gating(struct drm_device *dev) | 3418 | static void haswell_init_clock_gating(struct drm_device *dev) |
| 3381 | { | 3419 | { |
| 3382 | struct drm_i915_private *dev_priv = dev->dev_private; | 3420 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 3383 | int pipe; | 3421 | int pipe; |
| @@ -3427,13 +3465,24 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) | |||
| 3427 | /* WaDisable4x2SubspanOptimization */ | 3465 | /* WaDisable4x2SubspanOptimization */ |
| 3428 | I915_WRITE(CACHE_MODE_1, | 3466 | I915_WRITE(CACHE_MODE_1, |
| 3429 | _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); | 3467 | _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); |
| 3468 | |||
| 3469 | /* XXX: This is a workaround for early silicon revisions and should be | ||
| 3470 | * removed later. | ||
| 3471 | */ | ||
| 3472 | I915_WRITE(WM_DBG, | ||
| 3473 | I915_READ(WM_DBG) | | ||
| 3474 | WM_DBG_DISALLOW_MULTIPLE_LP | | ||
| 3475 | WM_DBG_DISALLOW_SPRITE | | ||
| 3476 | WM_DBG_DISALLOW_MAXFIFO); | ||
| 3477 | |||
| 3430 | } | 3478 | } |
| 3431 | 3479 | ||
| 3432 | static void valleyview_init_clock_gating(struct drm_device *dev) | 3480 | static void ivybridge_init_clock_gating(struct drm_device *dev) |
| 3433 | { | 3481 | { |
| 3434 | struct drm_i915_private *dev_priv = dev->dev_private; | 3482 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 3435 | int pipe; | 3483 | int pipe; |
| 3436 | uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE; | 3484 | uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE; |
| 3485 | uint32_t snpcr; | ||
| 3437 | 3486 | ||
| 3438 | I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); | 3487 | I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); |
| 3439 | 3488 | ||
| @@ -3441,10 +3490,77 @@ static void valleyview_init_clock_gating(struct drm_device *dev) | |||
| 3441 | I915_WRITE(WM2_LP_ILK, 0); | 3490 | I915_WRITE(WM2_LP_ILK, 0); |
| 3442 | I915_WRITE(WM1_LP_ILK, 0); | 3491 | I915_WRITE(WM1_LP_ILK, 0); |
| 3443 | 3492 | ||
| 3444 | /* According to the spec, bit 13 (RCZUNIT) must be set on IVB. | 3493 | I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE); |
| 3494 | |||
| 3495 | I915_WRITE(IVB_CHICKEN3, | ||
| 3496 | CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE | | ||
| 3497 | CHICKEN3_DGMG_DONE_FIX_DISABLE); | ||
| 3498 | |||
| 3499 | /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */ | ||
| 3500 | I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1, | ||
| 3501 | GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC); | ||
| 3502 | |||
| 3503 | /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */ | ||
| 3504 | I915_WRITE(GEN7_L3CNTLREG1, | ||
| 3505 | GEN7_WA_FOR_GEN7_L3_CONTROL); | ||
| 3506 | I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, | ||
| 3507 | GEN7_WA_L3_CHICKEN_MODE); | ||
| 3508 | |||
| 3509 | /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock | ||
| 3510 | * gating disable must be set. Failure to set it results in | ||
| 3511 | * flickering pixels due to Z write ordering failures after | ||
| 3512 | * some amount of runtime in the Mesa "fire" demo, and Unigine | ||
| 3513 | * Sanctuary and Tropics, and apparently anything else with | ||
| 3514 | * alpha test or pixel discard. | ||
| 3515 | * | ||
| 3516 | * According to the spec, bit 11 (RCCUNIT) must also be set, | ||
| 3517 | * but we didn't debug actual testcases to find it out. | ||
| 3518 | * | ||
| 3519 | * According to the spec, bit 13 (RCZUNIT) must be set on IVB. | ||
| 3445 | * This implements the WaDisableRCZUnitClockGating workaround. | 3520 | * This implements the WaDisableRCZUnitClockGating workaround. |
| 3446 | */ | 3521 | */ |
| 3447 | I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE); | 3522 | I915_WRITE(GEN6_UCGCTL2, |
| 3523 | GEN6_RCZUNIT_CLOCK_GATE_DISABLE | | ||
| 3524 | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); | ||
| 3525 | |||
| 3526 | /* This is required by WaCatErrorRejectionIssue */ | ||
| 3527 | I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, | ||
| 3528 | I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | | ||
| 3529 | GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); | ||
| 3530 | |||
| 3531 | for_each_pipe(pipe) { | ||
| 3532 | I915_WRITE(DSPCNTR(pipe), | ||
| 3533 | I915_READ(DSPCNTR(pipe)) | | ||
| 3534 | DISPPLANE_TRICKLE_FEED_DISABLE); | ||
| 3535 | intel_flush_display_plane(dev_priv, pipe); | ||
| 3536 | } | ||
| 3537 | |||
| 3538 | I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | | ||
| 3539 | GEN6_MBCTL_ENABLE_BOOT_FETCH); | ||
| 3540 | |||
| 3541 | gen7_setup_fixed_func_scheduler(dev_priv); | ||
| 3542 | |||
| 3543 | /* WaDisable4x2SubspanOptimization */ | ||
| 3544 | I915_WRITE(CACHE_MODE_1, | ||
| 3545 | _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); | ||
| 3546 | |||
| 3547 | snpcr = I915_READ(GEN6_MBCUNIT_SNPCR); | ||
| 3548 | snpcr &= ~GEN6_MBC_SNPCR_MASK; | ||
| 3549 | snpcr |= GEN6_MBC_SNPCR_MED; | ||
| 3550 | I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr); | ||
| 3551 | } | ||
| 3552 | |||
| 3553 | static void valleyview_init_clock_gating(struct drm_device *dev) | ||
| 3554 | { | ||
| 3555 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 3556 | int pipe; | ||
| 3557 | uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE; | ||
| 3558 | |||
| 3559 | I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); | ||
| 3560 | |||
| 3561 | I915_WRITE(WM3_LP_ILK, 0); | ||
| 3562 | I915_WRITE(WM2_LP_ILK, 0); | ||
| 3563 | I915_WRITE(WM1_LP_ILK, 0); | ||
| 3448 | 3564 | ||
| 3449 | I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE); | 3565 | I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE); |
| 3450 | 3566 | ||
| @@ -3465,6 +3581,35 @@ static void valleyview_init_clock_gating(struct drm_device *dev) | |||
| 3465 | I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | | 3581 | I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | |
| 3466 | GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); | 3582 | GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); |
| 3467 | 3583 | ||
| 3584 | I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | | ||
| 3585 | GEN6_MBCTL_ENABLE_BOOT_FETCH); | ||
| 3586 | |||
| 3587 | |||
| 3588 | /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock | ||
| 3589 | * gating disable must be set. Failure to set it results in | ||
| 3590 | * flickering pixels due to Z write ordering failures after | ||
| 3591 | * some amount of runtime in the Mesa "fire" demo, and Unigine | ||
| 3592 | * Sanctuary and Tropics, and apparently anything else with | ||
| 3593 | * alpha test or pixel discard. | ||
| 3594 | * | ||
| 3595 | * According to the spec, bit 11 (RCCUNIT) must also be set, | ||
| 3596 | * but we didn't debug actual testcases to find it out. | ||
| 3597 | * | ||
| 3598 | * According to the spec, bit 13 (RCZUNIT) must be set on IVB. | ||
| 3599 | * This implements the WaDisableRCZUnitClockGating workaround. | ||
| 3600 | * | ||
| 3601 | * Also apply WaDisableVDSUnitClockGating and | ||
| 3602 | * WaDisableRCPBUnitClockGating. | ||
| 3603 | */ | ||
| 3604 | I915_WRITE(GEN6_UCGCTL2, | ||
| 3605 | GEN7_VDSUNIT_CLOCK_GATE_DISABLE | | ||
| 3606 | GEN7_TDLUNIT_CLOCK_GATE_DISABLE | | ||
| 3607 | GEN6_RCZUNIT_CLOCK_GATE_DISABLE | | ||
| 3608 | GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | | ||
| 3609 | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); | ||
| 3610 | |||
| 3611 | I915_WRITE(GEN7_UCGCTL4, GEN7_L3BANK2X_CLOCK_GATE_DISABLE); | ||
| 3612 | |||
| 3468 | for_each_pipe(pipe) { | 3613 | for_each_pipe(pipe) { |
| 3469 | I915_WRITE(DSPCNTR(pipe), | 3614 | I915_WRITE(DSPCNTR(pipe), |
| 3470 | I915_READ(DSPCNTR(pipe)) | | 3615 | I915_READ(DSPCNTR(pipe)) | |
| @@ -3474,6 +3619,19 @@ static void valleyview_init_clock_gating(struct drm_device *dev) | |||
| 3474 | 3619 | ||
| 3475 | I915_WRITE(CACHE_MODE_1, | 3620 | I915_WRITE(CACHE_MODE_1, |
| 3476 | _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); | 3621 | _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); |
| 3622 | |||
| 3623 | /* | ||
| 3624 | * On ValleyView, the GUnit needs to signal the GT | ||
| 3625 | * when flip and other events complete. So enable | ||
| 3626 | * all the GUnit->GT interrupts here | ||
| 3627 | */ | ||
| 3628 | I915_WRITE(VLV_DPFLIPSTAT, PIPEB_LINE_COMPARE_INT_EN | | ||
| 3629 | PIPEB_HLINE_INT_EN | PIPEB_VBLANK_INT_EN | | ||
| 3630 | SPRITED_FLIPDONE_INT_EN | SPRITEC_FLIPDONE_INT_EN | | ||
| 3631 | PLANEB_FLIPDONE_INT_EN | PIPEA_LINE_COMPARE_INT_EN | | ||
| 3632 | PIPEA_HLINE_INT_EN | PIPEA_VBLANK_INT_EN | | ||
| 3633 | SPRITEB_FLIPDONE_INT_EN | SPRITEA_FLIPDONE_INT_EN | | ||
| 3634 | PLANEA_FLIPDONE_INT_EN); | ||
| 3477 | } | 3635 | } |
| 3478 | 3636 | ||
| 3479 | static void g4x_init_clock_gating(struct drm_device *dev) | 3637 | static void g4x_init_clock_gating(struct drm_device *dev) |
| @@ -3681,34 +3839,6 @@ void intel_init_pm(struct drm_device *dev) | |||
| 3681 | 3839 | ||
| 3682 | /* For FIFO watermark updates */ | 3840 | /* For FIFO watermark updates */ |
| 3683 | if (HAS_PCH_SPLIT(dev)) { | 3841 | if (HAS_PCH_SPLIT(dev)) { |
| 3684 | dev_priv->display.force_wake_get = __gen6_gt_force_wake_get; | ||
| 3685 | dev_priv->display.force_wake_put = __gen6_gt_force_wake_put; | ||
| 3686 | |||
| 3687 | /* IVB configs may use multi-threaded forcewake */ | ||
| 3688 | if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { | ||
| 3689 | u32 ecobus; | ||
| 3690 | |||
| 3691 | /* A small trick here - if the bios hasn't configured MT forcewake, | ||
| 3692 | * and if the device is in RC6, then force_wake_mt_get will not wake | ||
| 3693 | * the device and the ECOBUS read will return zero. Which will be | ||
| 3694 | * (correctly) interpreted by the test below as MT forcewake being | ||
| 3695 | * disabled. | ||
| 3696 | */ | ||
| 3697 | mutex_lock(&dev->struct_mutex); | ||
| 3698 | __gen6_gt_force_wake_mt_get(dev_priv); | ||
| 3699 | ecobus = I915_READ_NOTRACE(ECOBUS); | ||
| 3700 | __gen6_gt_force_wake_mt_put(dev_priv); | ||
| 3701 | mutex_unlock(&dev->struct_mutex); | ||
| 3702 | |||
| 3703 | if (ecobus & FORCEWAKE_MT_ENABLE) { | ||
| 3704 | DRM_DEBUG_KMS("Using MT version of forcewake\n"); | ||
| 3705 | dev_priv->display.force_wake_get = | ||
| 3706 | __gen6_gt_force_wake_mt_get; | ||
| 3707 | dev_priv->display.force_wake_put = | ||
| 3708 | __gen6_gt_force_wake_mt_put; | ||
| 3709 | } | ||
| 3710 | } | ||
| 3711 | |||
| 3712 | if (HAS_PCH_IBX(dev)) | 3842 | if (HAS_PCH_IBX(dev)) |
| 3713 | dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating; | 3843 | dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating; |
| 3714 | else if (HAS_PCH_CPT(dev)) | 3844 | else if (HAS_PCH_CPT(dev)) |
| @@ -3756,7 +3886,7 @@ void intel_init_pm(struct drm_device *dev) | |||
| 3756 | "Disable CxSR\n"); | 3886 | "Disable CxSR\n"); |
| 3757 | dev_priv->display.update_wm = NULL; | 3887 | dev_priv->display.update_wm = NULL; |
| 3758 | } | 3888 | } |
| 3759 | dev_priv->display.init_clock_gating = ivybridge_init_clock_gating; | 3889 | dev_priv->display.init_clock_gating = haswell_init_clock_gating; |
| 3760 | dev_priv->display.sanitize_pm = gen6_sanitize_pm; | 3890 | dev_priv->display.sanitize_pm = gen6_sanitize_pm; |
| 3761 | } else | 3891 | } else |
| 3762 | dev_priv->display.update_wm = NULL; | 3892 | dev_priv->display.update_wm = NULL; |
| @@ -3764,8 +3894,6 @@ void intel_init_pm(struct drm_device *dev) | |||
| 3764 | dev_priv->display.update_wm = valleyview_update_wm; | 3894 | dev_priv->display.update_wm = valleyview_update_wm; |
| 3765 | dev_priv->display.init_clock_gating = | 3895 | dev_priv->display.init_clock_gating = |
| 3766 | valleyview_init_clock_gating; | 3896 | valleyview_init_clock_gating; |
| 3767 | dev_priv->display.force_wake_get = vlv_force_wake_get; | ||
| 3768 | dev_priv->display.force_wake_put = vlv_force_wake_put; | ||
| 3769 | } else if (IS_PINEVIEW(dev)) { | 3897 | } else if (IS_PINEVIEW(dev)) { |
| 3770 | if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev), | 3898 | if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev), |
| 3771 | dev_priv->is_ddr3, | 3899 | dev_priv->is_ddr3, |
| @@ -3818,3 +3946,194 @@ void intel_init_pm(struct drm_device *dev) | |||
| 3818 | intel_init_power_wells(dev); | 3946 | intel_init_power_wells(dev); |
| 3819 | } | 3947 | } |
| 3820 | 3948 | ||
| 3949 | static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv) | ||
| 3950 | { | ||
| 3951 | u32 gt_thread_status_mask; | ||
| 3952 | |||
| 3953 | if (IS_HASWELL(dev_priv->dev)) | ||
| 3954 | gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK_HSW; | ||
| 3955 | else | ||
| 3956 | gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK; | ||
| 3957 | |||
| 3958 | /* w/a for a sporadic read returning 0 by waiting for the GT | ||
| 3959 | * thread to wake up. | ||
| 3960 | */ | ||
| 3961 | if (wait_for_atomic_us((I915_READ_NOTRACE(GEN6_GT_THREAD_STATUS_REG) & gt_thread_status_mask) == 0, 500)) | ||
| 3962 | DRM_ERROR("GT thread status wait timed out\n"); | ||
| 3963 | } | ||
| 3964 | |||
| 3965 | static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) | ||
| 3966 | { | ||
| 3967 | u32 forcewake_ack; | ||
| 3968 | |||
| 3969 | if (IS_HASWELL(dev_priv->dev)) | ||
| 3970 | forcewake_ack = FORCEWAKE_ACK_HSW; | ||
| 3971 | else | ||
| 3972 | forcewake_ack = FORCEWAKE_ACK; | ||
| 3973 | |||
| 3974 | if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, 500)) | ||
| 3975 | DRM_ERROR("Force wake wait timed out\n"); | ||
| 3976 | |||
| 3977 | I915_WRITE_NOTRACE(FORCEWAKE, 1); | ||
| 3978 | |||
| 3979 | if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500)) | ||
| 3980 | DRM_ERROR("Force wake wait timed out\n"); | ||
| 3981 | |||
| 3982 | __gen6_gt_wait_for_thread_c0(dev_priv); | ||
| 3983 | } | ||
| 3984 | |||
| 3985 | static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) | ||
| 3986 | { | ||
| 3987 | u32 forcewake_ack; | ||
| 3988 | |||
| 3989 | if (IS_HASWELL(dev_priv->dev)) | ||
| 3990 | forcewake_ack = FORCEWAKE_ACK_HSW; | ||
| 3991 | else | ||
| 3992 | forcewake_ack = FORCEWAKE_MT_ACK; | ||
| 3993 | |||
| 3994 | if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, 500)) | ||
| 3995 | DRM_ERROR("Force wake wait timed out\n"); | ||
| 3996 | |||
| 3997 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1)); | ||
| 3998 | |||
| 3999 | if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500)) | ||
| 4000 | DRM_ERROR("Force wake wait timed out\n"); | ||
| 4001 | |||
| 4002 | __gen6_gt_wait_for_thread_c0(dev_priv); | ||
| 4003 | } | ||
| 4004 | |||
| 4005 | /* | ||
| 4006 | * Generally this is called implicitly by the register read function. However, | ||
| 4007 | * if some sequence requires the GT to not power down then this function should | ||
| 4008 | * be called at the beginning of the sequence followed by a call to | ||
| 4009 | * gen6_gt_force_wake_put() at the end of the sequence. | ||
| 4010 | */ | ||
| 4011 | void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) | ||
| 4012 | { | ||
| 4013 | unsigned long irqflags; | ||
| 4014 | |||
| 4015 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); | ||
| 4016 | if (dev_priv->forcewake_count++ == 0) | ||
| 4017 | dev_priv->gt.force_wake_get(dev_priv); | ||
| 4018 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); | ||
| 4019 | } | ||
| 4020 | |||
| 4021 | void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) | ||
| 4022 | { | ||
| 4023 | u32 gtfifodbg; | ||
| 4024 | gtfifodbg = I915_READ_NOTRACE(GTFIFODBG); | ||
| 4025 | if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK, | ||
| 4026 | "MMIO read or write has been dropped %x\n", gtfifodbg)) | ||
| 4027 | I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK); | ||
| 4028 | } | ||
| 4029 | |||
| 4030 | static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) | ||
| 4031 | { | ||
| 4032 | I915_WRITE_NOTRACE(FORCEWAKE, 0); | ||
| 4033 | /* The below doubles as a POSTING_READ */ | ||
| 4034 | gen6_gt_check_fifodbg(dev_priv); | ||
| 4035 | } | ||
| 4036 | |||
| 4037 | static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) | ||
| 4038 | { | ||
| 4039 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1)); | ||
| 4040 | /* The below doubles as a POSTING_READ */ | ||
| 4041 | gen6_gt_check_fifodbg(dev_priv); | ||
| 4042 | } | ||
| 4043 | |||
| 4044 | /* | ||
| 4045 | * see gen6_gt_force_wake_get() | ||
| 4046 | */ | ||
| 4047 | void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) | ||
| 4048 | { | ||
| 4049 | unsigned long irqflags; | ||
| 4050 | |||
| 4051 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); | ||
| 4052 | if (--dev_priv->forcewake_count == 0) | ||
| 4053 | dev_priv->gt.force_wake_put(dev_priv); | ||
| 4054 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); | ||
| 4055 | } | ||
| 4056 | |||
| 4057 | int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) | ||
| 4058 | { | ||
| 4059 | int ret = 0; | ||
| 4060 | |||
| 4061 | if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) { | ||
| 4062 | int loop = 500; | ||
| 4063 | u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); | ||
| 4064 | while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) { | ||
| 4065 | udelay(10); | ||
| 4066 | fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); | ||
| 4067 | } | ||
| 4068 | if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES)) | ||
| 4069 | ++ret; | ||
| 4070 | dev_priv->gt_fifo_count = fifo; | ||
| 4071 | } | ||
| 4072 | dev_priv->gt_fifo_count--; | ||
| 4073 | |||
| 4074 | return ret; | ||
| 4075 | } | ||
| 4076 | |||
| 4077 | static void vlv_force_wake_get(struct drm_i915_private *dev_priv) | ||
| 4078 | { | ||
| 4079 | /* Already awake? */ | ||
| 4080 | if ((I915_READ(0x130094) & 0xa1) == 0xa1) | ||
| 4081 | return; | ||
| 4082 | |||
| 4083 | I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffffffff); | ||
| 4084 | POSTING_READ(FORCEWAKE_VLV); | ||
| 4085 | |||
| 4086 | if (wait_for_atomic_us((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1), 500)) | ||
| 4087 | DRM_ERROR("Force wake wait timed out\n"); | ||
| 4088 | |||
| 4089 | __gen6_gt_wait_for_thread_c0(dev_priv); | ||
| 4090 | } | ||
| 4091 | |||
| 4092 | static void vlv_force_wake_put(struct drm_i915_private *dev_priv) | ||
| 4093 | { | ||
| 4094 | I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffff0000); | ||
| 4095 | /* FIXME: confirm VLV behavior with Punit folks */ | ||
| 4096 | POSTING_READ(FORCEWAKE_VLV); | ||
| 4097 | } | ||
| 4098 | |||
| 4099 | void intel_gt_init(struct drm_device *dev) | ||
| 4100 | { | ||
| 4101 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 4102 | |||
| 4103 | spin_lock_init(&dev_priv->gt_lock); | ||
| 4104 | |||
| 4105 | if (IS_VALLEYVIEW(dev)) { | ||
| 4106 | dev_priv->gt.force_wake_get = vlv_force_wake_get; | ||
| 4107 | dev_priv->gt.force_wake_put = vlv_force_wake_put; | ||
| 4108 | } else if (INTEL_INFO(dev)->gen >= 6) { | ||
| 4109 | dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get; | ||
| 4110 | dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put; | ||
| 4111 | |||
| 4112 | /* IVB configs may use multi-threaded forcewake */ | ||
| 4113 | if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { | ||
| 4114 | u32 ecobus; | ||
| 4115 | |||
| 4116 | /* A small trick here - if the bios hasn't configured | ||
| 4117 | * MT forcewake, and if the device is in RC6, then | ||
| 4118 | * force_wake_mt_get will not wake the device and the | ||
| 4119 | * ECOBUS read will return zero. Which will be | ||
| 4120 | * (correctly) interpreted by the test below as MT | ||
| 4121 | * forcewake being disabled. | ||
| 4122 | */ | ||
| 4123 | mutex_lock(&dev->struct_mutex); | ||
| 4124 | __gen6_gt_force_wake_mt_get(dev_priv); | ||
| 4125 | ecobus = I915_READ_NOTRACE(ECOBUS); | ||
| 4126 | __gen6_gt_force_wake_mt_put(dev_priv); | ||
| 4127 | mutex_unlock(&dev->struct_mutex); | ||
| 4128 | |||
| 4129 | if (ecobus & FORCEWAKE_MT_ENABLE) { | ||
| 4130 | DRM_DEBUG_KMS("Using MT version of forcewake\n"); | ||
| 4131 | dev_priv->gt.force_wake_get = | ||
| 4132 | __gen6_gt_force_wake_mt_get; | ||
| 4133 | dev_priv->gt.force_wake_put = | ||
| 4134 | __gen6_gt_force_wake_mt_put; | ||
| 4135 | } | ||
| 4136 | } | ||
| 4137 | } | ||
| 4138 | } | ||
| 4139 | |||
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index e5b84ff89ca5..d42d821c64d6 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
| @@ -219,19 +219,28 @@ gen6_render_ring_flush(struct intel_ring_buffer *ring, | |||
| 219 | int ret; | 219 | int ret; |
| 220 | 220 | ||
| 221 | /* Force SNB workarounds for PIPE_CONTROL flushes */ | 221 | /* Force SNB workarounds for PIPE_CONTROL flushes */ |
| 222 | intel_emit_post_sync_nonzero_flush(ring); | 222 | ret = intel_emit_post_sync_nonzero_flush(ring); |
| 223 | if (ret) | ||
| 224 | return ret; | ||
| 223 | 225 | ||
| 224 | /* Just flush everything. Experiments have shown that reducing the | 226 | /* Just flush everything. Experiments have shown that reducing the |
| 225 | * number of bits based on the write domains has little performance | 227 | * number of bits based on the write domains has little performance |
| 226 | * impact. | 228 | * impact. |
| 227 | */ | 229 | */ |
| 228 | flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; | 230 | flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; |
| 231 | flags |= PIPE_CONTROL_TLB_INVALIDATE; | ||
| 229 | flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; | 232 | flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; |
| 230 | flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; | 233 | flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; |
| 231 | flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; | 234 | flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; |
| 232 | flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; | 235 | flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; |
| 233 | flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; | 236 | flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; |
| 234 | flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; | 237 | flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; |
| 238 | /* | ||
| 239 | * Ensure that any following seqno writes only happen when the render | ||
| 240 | * cache is indeed flushed (but only if the caller actually wants that). | ||
| 241 | */ | ||
| 242 | if (flush_domains) | ||
| 243 | flags |= PIPE_CONTROL_CS_STALL; | ||
| 235 | 244 | ||
| 236 | ret = intel_ring_begin(ring, 6); | 245 | ret = intel_ring_begin(ring, 6); |
| 237 | if (ret) | 246 | if (ret) |
| @@ -433,11 +442,21 @@ static int init_render_ring(struct intel_ring_buffer *ring) | |||
| 433 | */ | 442 | */ |
| 434 | I915_WRITE(CACHE_MODE_0, | 443 | I915_WRITE(CACHE_MODE_0, |
| 435 | _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); | 444 | _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); |
| 445 | |||
| 446 | /* This is not explicitly set for GEN6, so read the register. | ||
| 447 | * see intel_ring_mi_set_context() for why we care. | ||
| 448 | * TODO: consider explicitly setting the bit for GEN5 | ||
| 449 | */ | ||
| 450 | ring->itlb_before_ctx_switch = | ||
| 451 | !!(I915_READ(GFX_MODE) & GFX_TLB_INVALIDATE_ALWAYS); | ||
| 436 | } | 452 | } |
| 437 | 453 | ||
| 438 | if (INTEL_INFO(dev)->gen >= 6) | 454 | if (INTEL_INFO(dev)->gen >= 6) |
| 439 | I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); | 455 | I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); |
| 440 | 456 | ||
| 457 | if (IS_IVYBRIDGE(dev)) | ||
| 458 | I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR); | ||
| 459 | |||
| 441 | return ret; | 460 | return ret; |
| 442 | } | 461 | } |
| 443 | 462 | ||
| @@ -825,7 +844,11 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring) | |||
| 825 | 844 | ||
| 826 | spin_lock_irqsave(&dev_priv->irq_lock, flags); | 845 | spin_lock_irqsave(&dev_priv->irq_lock, flags); |
| 827 | if (ring->irq_refcount++ == 0) { | 846 | if (ring->irq_refcount++ == 0) { |
| 828 | I915_WRITE_IMR(ring, ~ring->irq_enable_mask); | 847 | if (IS_IVYBRIDGE(dev) && ring->id == RCS) |
| 848 | I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | | ||
| 849 | GEN6_RENDER_L3_PARITY_ERROR)); | ||
| 850 | else | ||
| 851 | I915_WRITE_IMR(ring, ~ring->irq_enable_mask); | ||
| 829 | dev_priv->gt_irq_mask &= ~ring->irq_enable_mask; | 852 | dev_priv->gt_irq_mask &= ~ring->irq_enable_mask; |
| 830 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); | 853 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); |
| 831 | POSTING_READ(GTIMR); | 854 | POSTING_READ(GTIMR); |
| @@ -844,7 +867,10 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring) | |||
| 844 | 867 | ||
| 845 | spin_lock_irqsave(&dev_priv->irq_lock, flags); | 868 | spin_lock_irqsave(&dev_priv->irq_lock, flags); |
| 846 | if (--ring->irq_refcount == 0) { | 869 | if (--ring->irq_refcount == 0) { |
| 847 | I915_WRITE_IMR(ring, ~0); | 870 | if (IS_IVYBRIDGE(dev) && ring->id == RCS) |
| 871 | I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR); | ||
| 872 | else | ||
| 873 | I915_WRITE_IMR(ring, ~0); | ||
| 848 | dev_priv->gt_irq_mask |= ring->irq_enable_mask; | 874 | dev_priv->gt_irq_mask |= ring->irq_enable_mask; |
| 849 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); | 875 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask); |
| 850 | POSTING_READ(GTIMR); | 876 | POSTING_READ(GTIMR); |
| @@ -969,6 +995,7 @@ static int intel_init_ring_buffer(struct drm_device *dev, | |||
| 969 | struct intel_ring_buffer *ring) | 995 | struct intel_ring_buffer *ring) |
| 970 | { | 996 | { |
| 971 | struct drm_i915_gem_object *obj; | 997 | struct drm_i915_gem_object *obj; |
| 998 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 972 | int ret; | 999 | int ret; |
| 973 | 1000 | ||
| 974 | ring->dev = dev; | 1001 | ring->dev = dev; |
| @@ -1002,8 +1029,9 @@ static int intel_init_ring_buffer(struct drm_device *dev, | |||
| 1002 | if (ret) | 1029 | if (ret) |
| 1003 | goto err_unpin; | 1030 | goto err_unpin; |
| 1004 | 1031 | ||
| 1005 | ring->virtual_start = ioremap_wc(dev->agp->base + obj->gtt_offset, | 1032 | ring->virtual_start = |
| 1006 | ring->size); | 1033 | ioremap_wc(dev_priv->mm.gtt->gma_bus_addr + obj->gtt_offset, |
| 1034 | ring->size); | ||
| 1007 | if (ring->virtual_start == NULL) { | 1035 | if (ring->virtual_start == NULL) { |
| 1008 | DRM_ERROR("Failed to map ringbuffer.\n"); | 1036 | DRM_ERROR("Failed to map ringbuffer.\n"); |
| 1009 | ret = -EINVAL; | 1037 | ret = -EINVAL; |
| @@ -1089,20 +1117,9 @@ static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring) | |||
| 1089 | 1117 | ||
| 1090 | static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno) | 1118 | static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno) |
| 1091 | { | 1119 | { |
| 1092 | struct drm_i915_private *dev_priv = ring->dev->dev_private; | ||
| 1093 | bool was_interruptible; | ||
| 1094 | int ret; | 1120 | int ret; |
| 1095 | 1121 | ||
| 1096 | /* XXX As we have not yet audited all the paths to check that | 1122 | ret = i915_wait_seqno(ring, seqno); |
| 1097 | * they are ready for ERESTARTSYS from intel_ring_begin, do not | ||
| 1098 | * allow us to be interruptible by a signal. | ||
| 1099 | */ | ||
| 1100 | was_interruptible = dev_priv->mm.interruptible; | ||
| 1101 | dev_priv->mm.interruptible = false; | ||
| 1102 | |||
| 1103 | ret = i915_wait_request(ring, seqno); | ||
| 1104 | |||
| 1105 | dev_priv->mm.interruptible = was_interruptible; | ||
| 1106 | if (!ret) | 1123 | if (!ret) |
| 1107 | i915_gem_retire_requests_ring(ring); | 1124 | i915_gem_retire_requests_ring(ring); |
| 1108 | 1125 | ||
| @@ -1200,8 +1217,10 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n) | |||
| 1200 | } | 1217 | } |
| 1201 | 1218 | ||
| 1202 | msleep(1); | 1219 | msleep(1); |
| 1203 | if (atomic_read(&dev_priv->mm.wedged)) | 1220 | |
| 1204 | return -EAGAIN; | 1221 | ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); |
| 1222 | if (ret) | ||
| 1223 | return ret; | ||
| 1205 | } while (!time_after(jiffies, end)); | 1224 | } while (!time_after(jiffies, end)); |
| 1206 | trace_i915_ring_wait_end(ring); | 1225 | trace_i915_ring_wait_end(ring); |
| 1207 | return -EBUSY; | 1226 | return -EBUSY; |
| @@ -1210,12 +1229,13 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n) | |||
| 1210 | int intel_ring_begin(struct intel_ring_buffer *ring, | 1229 | int intel_ring_begin(struct intel_ring_buffer *ring, |
| 1211 | int num_dwords) | 1230 | int num_dwords) |
| 1212 | { | 1231 | { |
| 1213 | struct drm_i915_private *dev_priv = ring->dev->dev_private; | 1232 | drm_i915_private_t *dev_priv = ring->dev->dev_private; |
| 1214 | int n = 4*num_dwords; | 1233 | int n = 4*num_dwords; |
| 1215 | int ret; | 1234 | int ret; |
| 1216 | 1235 | ||
| 1217 | if (unlikely(atomic_read(&dev_priv->mm.wedged))) | 1236 | ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); |
| 1218 | return -EIO; | 1237 | if (ret) |
| 1238 | return ret; | ||
| 1219 | 1239 | ||
| 1220 | if (unlikely(ring->tail + n > ring->effective_size)) { | 1240 | if (unlikely(ring->tail + n > ring->effective_size)) { |
| 1221 | ret = intel_wrap_ring_buffer(ring); | 1241 | ret = intel_wrap_ring_buffer(ring); |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 55d3da26bae7..1d3c81fdad92 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h | |||
| @@ -113,9 +113,17 @@ struct intel_ring_buffer { | |||
| 113 | * Do we have some not yet emitted requests outstanding? | 113 | * Do we have some not yet emitted requests outstanding? |
| 114 | */ | 114 | */ |
| 115 | u32 outstanding_lazy_request; | 115 | u32 outstanding_lazy_request; |
| 116 | bool gpu_caches_dirty; | ||
| 116 | 117 | ||
| 117 | wait_queue_head_t irq_queue; | 118 | wait_queue_head_t irq_queue; |
| 118 | 119 | ||
| 120 | /** | ||
| 121 | * Do an explicit TLB flush before MI_SET_CONTEXT | ||
| 122 | */ | ||
| 123 | bool itlb_before_ctx_switch; | ||
| 124 | struct i915_hw_context *default_context; | ||
| 125 | struct drm_i915_gem_object *last_context_obj; | ||
| 126 | |||
| 119 | void *private; | 127 | void *private; |
| 120 | }; | 128 | }; |
| 121 | 129 | ||
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index b6a9d45fc3c6..26a6a4d0d078 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
| @@ -140,9 +140,6 @@ struct intel_sdvo { | |||
| 140 | 140 | ||
| 141 | /* DDC bus used by this SDVO encoder */ | 141 | /* DDC bus used by this SDVO encoder */ |
| 142 | uint8_t ddc_bus; | 142 | uint8_t ddc_bus; |
| 143 | |||
| 144 | /* Input timings for adjusted_mode */ | ||
| 145 | struct intel_sdvo_dtd input_dtd; | ||
| 146 | }; | 143 | }; |
| 147 | 144 | ||
| 148 | struct intel_sdvo_connector { | 145 | struct intel_sdvo_connector { |
| @@ -938,7 +935,7 @@ static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) | |||
| 938 | 935 | ||
| 939 | static bool | 936 | static bool |
| 940 | intel_sdvo_set_output_timings_from_mode(struct intel_sdvo *intel_sdvo, | 937 | intel_sdvo_set_output_timings_from_mode(struct intel_sdvo *intel_sdvo, |
| 941 | struct drm_display_mode *mode) | 938 | const struct drm_display_mode *mode) |
| 942 | { | 939 | { |
| 943 | struct intel_sdvo_dtd output_dtd; | 940 | struct intel_sdvo_dtd output_dtd; |
| 944 | 941 | ||
| @@ -953,11 +950,15 @@ intel_sdvo_set_output_timings_from_mode(struct intel_sdvo *intel_sdvo, | |||
| 953 | return true; | 950 | return true; |
| 954 | } | 951 | } |
| 955 | 952 | ||
| 953 | /* Asks the sdvo controller for the preferred input mode given the output mode. | ||
| 954 | * Unfortunately we have to set up the full output mode to do that. */ | ||
| 956 | static bool | 955 | static bool |
| 957 | intel_sdvo_set_input_timings_for_mode(struct intel_sdvo *intel_sdvo, | 956 | intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, |
| 958 | struct drm_display_mode *mode, | 957 | const struct drm_display_mode *mode, |
| 959 | struct drm_display_mode *adjusted_mode) | 958 | struct drm_display_mode *adjusted_mode) |
| 960 | { | 959 | { |
| 960 | struct intel_sdvo_dtd input_dtd; | ||
| 961 | |||
| 961 | /* Reset the input timing to the screen. Assume always input 0. */ | 962 | /* Reset the input timing to the screen. Assume always input 0. */ |
| 962 | if (!intel_sdvo_set_target_input(intel_sdvo)) | 963 | if (!intel_sdvo_set_target_input(intel_sdvo)) |
| 963 | return false; | 964 | return false; |
| @@ -969,16 +970,16 @@ intel_sdvo_set_input_timings_for_mode(struct intel_sdvo *intel_sdvo, | |||
| 969 | return false; | 970 | return false; |
| 970 | 971 | ||
| 971 | if (!intel_sdvo_get_preferred_input_timing(intel_sdvo, | 972 | if (!intel_sdvo_get_preferred_input_timing(intel_sdvo, |
| 972 | &intel_sdvo->input_dtd)) | 973 | &input_dtd)) |
| 973 | return false; | 974 | return false; |
| 974 | 975 | ||
| 975 | intel_sdvo_get_mode_from_dtd(adjusted_mode, &intel_sdvo->input_dtd); | 976 | intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); |
| 976 | 977 | ||
| 977 | return true; | 978 | return true; |
| 978 | } | 979 | } |
| 979 | 980 | ||
| 980 | static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | 981 | static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, |
| 981 | struct drm_display_mode *mode, | 982 | const struct drm_display_mode *mode, |
| 982 | struct drm_display_mode *adjusted_mode) | 983 | struct drm_display_mode *adjusted_mode) |
| 983 | { | 984 | { |
| 984 | struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder); | 985 | struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder); |
| @@ -993,17 +994,17 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | |||
| 993 | if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode)) | 994 | if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode)) |
| 994 | return false; | 995 | return false; |
| 995 | 996 | ||
| 996 | (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo, | 997 | (void) intel_sdvo_get_preferred_input_mode(intel_sdvo, |
| 997 | mode, | 998 | mode, |
| 998 | adjusted_mode); | 999 | adjusted_mode); |
| 999 | } else if (intel_sdvo->is_lvds) { | 1000 | } else if (intel_sdvo->is_lvds) { |
| 1000 | if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, | 1001 | if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, |
| 1001 | intel_sdvo->sdvo_lvds_fixed_mode)) | 1002 | intel_sdvo->sdvo_lvds_fixed_mode)) |
| 1002 | return false; | 1003 | return false; |
| 1003 | 1004 | ||
| 1004 | (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo, | 1005 | (void) intel_sdvo_get_preferred_input_mode(intel_sdvo, |
| 1005 | mode, | 1006 | mode, |
| 1006 | adjusted_mode); | 1007 | adjusted_mode); |
| 1007 | } | 1008 | } |
| 1008 | 1009 | ||
| 1009 | /* Make the CRTC code factor in the SDVO pixel multiplier. The | 1010 | /* Make the CRTC code factor in the SDVO pixel multiplier. The |
| @@ -1057,7 +1058,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
| 1057 | intel_sdvo->sdvo_lvds_fixed_mode); | 1058 | intel_sdvo->sdvo_lvds_fixed_mode); |
| 1058 | else | 1059 | else |
| 1059 | intel_sdvo_get_dtd_from_mode(&output_dtd, mode); | 1060 | intel_sdvo_get_dtd_from_mode(&output_dtd, mode); |
| 1060 | (void) intel_sdvo_set_output_timing(intel_sdvo, &output_dtd); | 1061 | if (!intel_sdvo_set_output_timing(intel_sdvo, &output_dtd)) |
| 1062 | DRM_INFO("Setting output timings on %s failed\n", | ||
| 1063 | SDVO_NAME(intel_sdvo)); | ||
| 1061 | 1064 | ||
| 1062 | /* Set the input timing to the screen. Assume always input 0. */ | 1065 | /* Set the input timing to the screen. Assume always input 0. */ |
| 1063 | if (!intel_sdvo_set_target_input(intel_sdvo)) | 1066 | if (!intel_sdvo_set_target_input(intel_sdvo)) |
| @@ -1079,7 +1082,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
| 1079 | * adjusted_mode. | 1082 | * adjusted_mode. |
| 1080 | */ | 1083 | */ |
| 1081 | intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); | 1084 | intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); |
| 1082 | (void) intel_sdvo_set_input_timing(intel_sdvo, &input_dtd); | 1085 | if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd)) |
| 1086 | DRM_INFO("Setting input timings on %s failed\n", | ||
| 1087 | SDVO_NAME(intel_sdvo)); | ||
| 1083 | 1088 | ||
| 1084 | switch (pixel_multiplier) { | 1089 | switch (pixel_multiplier) { |
| 1085 | default: | 1090 | default: |
| @@ -1376,7 +1381,7 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) | |||
| 1376 | 1381 | ||
| 1377 | /* add 30ms delay when the output type might be TV */ | 1382 | /* add 30ms delay when the output type might be TV */ |
| 1378 | if (intel_sdvo->caps.output_flags & SDVO_TV_MASK) | 1383 | if (intel_sdvo->caps.output_flags & SDVO_TV_MASK) |
| 1379 | mdelay(30); | 1384 | msleep(30); |
| 1380 | 1385 | ||
| 1381 | if (!intel_sdvo_read_response(intel_sdvo, &response, 2)) | 1386 | if (!intel_sdvo_read_response(intel_sdvo, &response, 2)) |
| 1382 | return connector_status_unknown; | 1387 | return connector_status_unknown; |
| @@ -2521,6 +2526,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) | |||
| 2521 | struct drm_i915_private *dev_priv = dev->dev_private; | 2526 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 2522 | struct intel_encoder *intel_encoder; | 2527 | struct intel_encoder *intel_encoder; |
| 2523 | struct intel_sdvo *intel_sdvo; | 2528 | struct intel_sdvo *intel_sdvo; |
| 2529 | u32 hotplug_mask; | ||
| 2524 | int i; | 2530 | int i; |
| 2525 | 2531 | ||
| 2526 | intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL); | 2532 | intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL); |
| @@ -2552,10 +2558,18 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) | |||
| 2552 | } | 2558 | } |
| 2553 | } | 2559 | } |
| 2554 | 2560 | ||
| 2555 | if (intel_sdvo->is_sdvob) | 2561 | hotplug_mask = 0; |
| 2556 | dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS; | 2562 | if (IS_G4X(dev)) { |
| 2557 | else | 2563 | hotplug_mask = intel_sdvo->is_sdvob ? |
| 2558 | dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS; | 2564 | SDVOB_HOTPLUG_INT_STATUS_G4X : SDVOC_HOTPLUG_INT_STATUS_G4X; |
| 2565 | } else if (IS_GEN4(dev)) { | ||
| 2566 | hotplug_mask = intel_sdvo->is_sdvob ? | ||
| 2567 | SDVOB_HOTPLUG_INT_STATUS_I965 : SDVOC_HOTPLUG_INT_STATUS_I965; | ||
| 2568 | } else { | ||
| 2569 | hotplug_mask = intel_sdvo->is_sdvob ? | ||
| 2570 | SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915; | ||
| 2571 | } | ||
| 2572 | dev_priv->hotplug_supported_mask |= hotplug_mask; | ||
| 2559 | 2573 | ||
| 2560 | drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs); | 2574 | drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs); |
| 2561 | 2575 | ||
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 2a20fb0781d7..1a1483b924d0 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
| @@ -56,6 +56,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, | |||
| 56 | sprctl &= ~SPRITE_PIXFORMAT_MASK; | 56 | sprctl &= ~SPRITE_PIXFORMAT_MASK; |
| 57 | sprctl &= ~SPRITE_RGB_ORDER_RGBX; | 57 | sprctl &= ~SPRITE_RGB_ORDER_RGBX; |
| 58 | sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK; | 58 | sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK; |
| 59 | sprctl &= ~SPRITE_TILED; | ||
| 59 | 60 | ||
| 60 | switch (fb->pixel_format) { | 61 | switch (fb->pixel_format) { |
| 61 | case DRM_FORMAT_XBGR8888: | 62 | case DRM_FORMAT_XBGR8888: |
| @@ -84,7 +85,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, | |||
| 84 | break; | 85 | break; |
| 85 | default: | 86 | default: |
| 86 | DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n"); | 87 | DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n"); |
| 87 | sprctl |= DVS_FORMAT_RGBX888; | 88 | sprctl |= SPRITE_FORMAT_RGBX888; |
| 88 | pixel_size = 4; | 89 | pixel_size = 4; |
| 89 | break; | 90 | break; |
| 90 | } | 91 | } |
| @@ -326,6 +327,12 @@ intel_enable_primary(struct drm_crtc *crtc) | |||
| 326 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 327 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 327 | int reg = DSPCNTR(intel_crtc->plane); | 328 | int reg = DSPCNTR(intel_crtc->plane); |
| 328 | 329 | ||
| 330 | if (!intel_crtc->primary_disabled) | ||
| 331 | return; | ||
| 332 | |||
| 333 | intel_crtc->primary_disabled = false; | ||
| 334 | intel_update_fbc(dev); | ||
| 335 | |||
| 329 | I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); | 336 | I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); |
| 330 | } | 337 | } |
| 331 | 338 | ||
| @@ -337,7 +344,13 @@ intel_disable_primary(struct drm_crtc *crtc) | |||
| 337 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 344 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 338 | int reg = DSPCNTR(intel_crtc->plane); | 345 | int reg = DSPCNTR(intel_crtc->plane); |
| 339 | 346 | ||
| 347 | if (intel_crtc->primary_disabled) | ||
| 348 | return; | ||
| 349 | |||
| 340 | I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE); | 350 | I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE); |
| 351 | |||
| 352 | intel_crtc->primary_disabled = true; | ||
| 353 | intel_update_fbc(dev); | ||
| 341 | } | 354 | } |
| 342 | 355 | ||
| 343 | static int | 356 | static int |
| @@ -485,18 +498,14 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
| 485 | * Be sure to re-enable the primary before the sprite is no longer | 498 | * Be sure to re-enable the primary before the sprite is no longer |
| 486 | * covering it fully. | 499 | * covering it fully. |
| 487 | */ | 500 | */ |
| 488 | if (!disable_primary && intel_plane->primary_disabled) { | 501 | if (!disable_primary) |
| 489 | intel_enable_primary(crtc); | 502 | intel_enable_primary(crtc); |
| 490 | intel_plane->primary_disabled = false; | ||
| 491 | } | ||
| 492 | 503 | ||
| 493 | intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y, | 504 | intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y, |
| 494 | crtc_w, crtc_h, x, y, src_w, src_h); | 505 | crtc_w, crtc_h, x, y, src_w, src_h); |
| 495 | 506 | ||
| 496 | if (disable_primary) { | 507 | if (disable_primary) |
| 497 | intel_disable_primary(crtc); | 508 | intel_disable_primary(crtc); |
| 498 | intel_plane->primary_disabled = true; | ||
| 499 | } | ||
| 500 | 509 | ||
| 501 | /* Unpin old obj after new one is active to avoid ugliness */ | 510 | /* Unpin old obj after new one is active to avoid ugliness */ |
| 502 | if (old_obj) { | 511 | if (old_obj) { |
| @@ -527,11 +536,8 @@ intel_disable_plane(struct drm_plane *plane) | |||
| 527 | struct intel_plane *intel_plane = to_intel_plane(plane); | 536 | struct intel_plane *intel_plane = to_intel_plane(plane); |
| 528 | int ret = 0; | 537 | int ret = 0; |
| 529 | 538 | ||
| 530 | if (intel_plane->primary_disabled) { | 539 | if (plane->crtc) |
| 531 | intel_enable_primary(plane->crtc); | 540 | intel_enable_primary(plane->crtc); |
| 532 | intel_plane->primary_disabled = false; | ||
| 533 | } | ||
| 534 | |||
| 535 | intel_plane->disable_plane(plane); | 541 | intel_plane->disable_plane(plane); |
| 536 | 542 | ||
| 537 | if (!intel_plane->obj) | 543 | if (!intel_plane->obj) |
| @@ -685,6 +691,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe) | |||
| 685 | break; | 691 | break; |
| 686 | 692 | ||
| 687 | default: | 693 | default: |
| 694 | kfree(intel_plane); | ||
| 688 | return -ENODEV; | 695 | return -ENODEV; |
| 689 | } | 696 | } |
| 690 | 697 | ||
| @@ -699,4 +706,3 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe) | |||
| 699 | 706 | ||
| 700 | return ret; | 707 | return ret; |
| 701 | } | 708 | } |
| 702 | |||
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index a233a51fd7e6..befce6c49704 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c | |||
| @@ -891,24 +891,21 @@ intel_tv_mode_valid(struct drm_connector *connector, | |||
| 891 | 891 | ||
| 892 | 892 | ||
| 893 | static bool | 893 | static bool |
| 894 | intel_tv_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | 894 | intel_tv_mode_fixup(struct drm_encoder *encoder, |
| 895 | const struct drm_display_mode *mode, | ||
| 895 | struct drm_display_mode *adjusted_mode) | 896 | struct drm_display_mode *adjusted_mode) |
| 896 | { | 897 | { |
| 897 | struct drm_device *dev = encoder->dev; | 898 | struct drm_device *dev = encoder->dev; |
| 898 | struct drm_mode_config *drm_config = &dev->mode_config; | ||
| 899 | struct intel_tv *intel_tv = enc_to_intel_tv(encoder); | 899 | struct intel_tv *intel_tv = enc_to_intel_tv(encoder); |
| 900 | const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); | 900 | const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); |
| 901 | struct drm_encoder *other_encoder; | 901 | struct intel_encoder *other_encoder; |
| 902 | 902 | ||
| 903 | if (!tv_mode) | 903 | if (!tv_mode) |
| 904 | return false; | 904 | return false; |
| 905 | 905 | ||
| 906 | /* FIXME: lock encoder list */ | 906 | for_each_encoder_on_crtc(dev, encoder->crtc, other_encoder) |
| 907 | list_for_each_entry(other_encoder, &drm_config->encoder_list, head) { | 907 | if (&other_encoder->base != encoder) |
| 908 | if (other_encoder != encoder && | ||
| 909 | other_encoder->crtc == encoder->crtc) | ||
| 910 | return false; | 908 | return false; |
| 911 | } | ||
| 912 | 909 | ||
| 913 | adjusted_mode->clock = tv_mode->clock; | 910 | adjusted_mode->clock = tv_mode->clock; |
| 914 | return true; | 911 | return true; |
diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c index f9a925d58819..b1bb46de3f5a 100644 --- a/drivers/gpu/drm/mga/mga_drv.c +++ b/drivers/gpu/drm/mga/mga_drv.c | |||
| @@ -75,7 +75,6 @@ static struct drm_driver driver = { | |||
| 75 | .irq_postinstall = mga_driver_irq_postinstall, | 75 | .irq_postinstall = mga_driver_irq_postinstall, |
| 76 | .irq_uninstall = mga_driver_irq_uninstall, | 76 | .irq_uninstall = mga_driver_irq_uninstall, |
| 77 | .irq_handler = mga_driver_irq_handler, | 77 | .irq_handler = mga_driver_irq_handler, |
| 78 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 79 | .ioctls = mga_ioctls, | 78 | .ioctls = mga_ioctls, |
| 80 | .dma_ioctl = mga_dma_buffers, | 79 | .dma_ioctl = mga_dma_buffers, |
| 81 | .fops = &mga_driver_fops, | 80 | .fops = &mga_driver_fops, |
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 93e832d6c328..ea1024d79974 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c | |||
| @@ -47,6 +47,9 @@ static void mgag200_kick_out_firmware_fb(struct pci_dev *pdev) | |||
| 47 | bool primary = false; | 47 | bool primary = false; |
| 48 | 48 | ||
| 49 | ap = alloc_apertures(1); | 49 | ap = alloc_apertures(1); |
| 50 | if (!ap) | ||
| 51 | return; | ||
| 52 | |||
| 50 | ap->ranges[0].base = pci_resource_start(pdev, 0); | 53 | ap->ranges[0].base = pci_resource_start(pdev, 0); |
| 51 | ap->ranges[0].size = pci_resource_len(pdev, 0); | 54 | ap->ranges[0].size = pci_resource_len(pdev, 0); |
| 52 | 55 | ||
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index d303061b251e..a4d7c500c97b 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c | |||
| @@ -78,8 +78,8 @@ static inline void mga_wait_busy(struct mga_device *mdev) | |||
| 78 | * to just pass that straight through, so this does nothing | 78 | * to just pass that straight through, so this does nothing |
| 79 | */ | 79 | */ |
| 80 | static bool mga_crtc_mode_fixup(struct drm_crtc *crtc, | 80 | static bool mga_crtc_mode_fixup(struct drm_crtc *crtc, |
| 81 | struct drm_display_mode *mode, | 81 | const struct drm_display_mode *mode, |
| 82 | struct drm_display_mode *adjusted_mode) | 82 | struct drm_display_mode *adjusted_mode) |
| 83 | { | 83 | { |
| 84 | return true; | 84 | return true; |
| 85 | } | 85 | } |
| @@ -1322,8 +1322,8 @@ void mga_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
| 1322 | * to handle any encoder-specific limitations | 1322 | * to handle any encoder-specific limitations |
| 1323 | */ | 1323 | */ |
| 1324 | static bool mga_encoder_mode_fixup(struct drm_encoder *encoder, | 1324 | static bool mga_encoder_mode_fixup(struct drm_encoder *encoder, |
| 1325 | struct drm_display_mode *mode, | 1325 | const struct drm_display_mode *mode, |
| 1326 | struct drm_display_mode *adjusted_mode) | 1326 | struct drm_display_mode *adjusted_mode) |
| 1327 | { | 1327 | { |
| 1328 | return true; | 1328 | return true; |
| 1329 | } | 1329 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 727447d296f1..9a36f5f39b06 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c | |||
| @@ -438,7 +438,6 @@ static struct drm_driver driver = { | |||
| 438 | .get_vblank_counter = drm_vblank_count, | 438 | .get_vblank_counter = drm_vblank_count, |
| 439 | .enable_vblank = nouveau_vblank_enable, | 439 | .enable_vblank = nouveau_vblank_enable, |
| 440 | .disable_vblank = nouveau_vblank_disable, | 440 | .disable_vblank = nouveau_vblank_disable, |
| 441 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 442 | .ioctls = nouveau_ioctls, | 441 | .ioctls = nouveau_ioctls, |
| 443 | .fops = &nouveau_driver_fops, | 442 | .fops = &nouveau_driver_fops, |
| 444 | 443 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 34d0bc596213..af7cfb825716 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
| @@ -207,8 +207,7 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, | |||
| 207 | struct nouveau_bo *nvbo = NULL; | 207 | struct nouveau_bo *nvbo = NULL; |
| 208 | int ret = 0; | 208 | int ret = 0; |
| 209 | 209 | ||
| 210 | if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) | 210 | dev_priv->ttm.bdev.dev_mapping = dev->dev_mapping; |
| 211 | dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; | ||
| 212 | 211 | ||
| 213 | if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) { | 212 | if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) { |
| 214 | NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags); | 213 | NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags); |
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index 4c31c63e5528..43accc11102f 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c | |||
| @@ -215,7 +215,7 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | static bool | 217 | static bool |
| 218 | nv_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, | 218 | nv_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, |
| 219 | struct drm_display_mode *adjusted_mode) | 219 | struct drm_display_mode *adjusted_mode) |
| 220 | { | 220 | { |
| 221 | return true; | 221 | return true; |
diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index 8300266ffaea..38f19479417c 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c | |||
| @@ -332,7 +332,7 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) | |||
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | static bool nv04_dac_mode_fixup(struct drm_encoder *encoder, | 334 | static bool nv04_dac_mode_fixup(struct drm_encoder *encoder, |
| 335 | struct drm_display_mode *mode, | 335 | const struct drm_display_mode *mode, |
| 336 | struct drm_display_mode *adjusted_mode) | 336 | struct drm_display_mode *adjusted_mode) |
| 337 | { | 337 | { |
| 338 | if (nv04_dac_in_use(encoder)) | 338 | if (nv04_dac_in_use(encoder)) |
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index 2258746016f8..c2675623b7cd 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c | |||
| @@ -179,7 +179,7 @@ static struct drm_encoder *get_tmds_slave(struct drm_encoder *encoder) | |||
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder, | 181 | static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder, |
| 182 | struct drm_display_mode *mode, | 182 | const struct drm_display_mode *mode, |
| 183 | struct drm_display_mode *adjusted_mode) | 183 | struct drm_display_mode *adjusted_mode) |
| 184 | { | 184 | { |
| 185 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 185 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c index 696d7e7dc2a0..67be5db021f5 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/drivers/gpu/drm/nouveau/nv17_tv.c | |||
| @@ -338,7 +338,7 @@ static int nv17_tv_mode_valid(struct drm_encoder *encoder, | |||
| 338 | } | 338 | } |
| 339 | 339 | ||
| 340 | static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, | 340 | static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, |
| 341 | struct drm_display_mode *mode, | 341 | const struct drm_display_mode *mode, |
| 342 | struct drm_display_mode *adjusted_mode) | 342 | struct drm_display_mode *adjusted_mode) |
| 343 | { | 343 | { |
| 344 | struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); | 344 | struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); |
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index 97a477b3d52d..22cebd5dd694 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c | |||
| @@ -527,7 +527,7 @@ nv50_crtc_commit(struct drm_crtc *crtc) | |||
| 527 | } | 527 | } |
| 528 | 528 | ||
| 529 | static bool | 529 | static bool |
| 530 | nv50_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, | 530 | nv50_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, |
| 531 | struct drm_display_mode *adjusted_mode) | 531 | struct drm_display_mode *adjusted_mode) |
| 532 | { | 532 | { |
| 533 | return true; | 533 | return true; |
diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c index eb216a446b89..2c36a6b92c53 100644 --- a/drivers/gpu/drm/nouveau/nv50_dac.c +++ b/drivers/gpu/drm/nouveau/nv50_dac.c | |||
| @@ -175,7 +175,8 @@ nv50_dac_restore(struct drm_encoder *encoder) | |||
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | static bool | 177 | static bool |
| 178 | nv50_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | 178 | nv50_dac_mode_fixup(struct drm_encoder *encoder, |
| 179 | const struct drm_display_mode *mode, | ||
| 179 | struct drm_display_mode *adjusted_mode) | 180 | struct drm_display_mode *adjusted_mode) |
| 180 | { | 181 | { |
| 181 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 182 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c index a9514eaa74c1..93240bde891b 100644 --- a/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/drivers/gpu/drm/nouveau/nv50_sor.c | |||
| @@ -327,7 +327,8 @@ nv50_sor_restore(struct drm_encoder *encoder) | |||
| 327 | } | 327 | } |
| 328 | 328 | ||
| 329 | static bool | 329 | static bool |
| 330 | nv50_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | 330 | nv50_sor_mode_fixup(struct drm_encoder *encoder, |
| 331 | const struct drm_display_mode *mode, | ||
| 331 | struct drm_display_mode *adjusted_mode) | 332 | struct drm_display_mode *adjusted_mode) |
| 332 | { | 333 | { |
| 333 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 334 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index c486d3ce3c2c..d0d60e1e7f95 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c | |||
| @@ -607,7 +607,7 @@ nvd0_crtc_commit(struct drm_crtc *crtc) | |||
| 607 | } | 607 | } |
| 608 | 608 | ||
| 609 | static bool | 609 | static bool |
| 610 | nvd0_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, | 610 | nvd0_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, |
| 611 | struct drm_display_mode *adjusted_mode) | 611 | struct drm_display_mode *adjusted_mode) |
| 612 | { | 612 | { |
| 613 | return true; | 613 | return true; |
| @@ -938,7 +938,8 @@ nvd0_dac_dpms(struct drm_encoder *encoder, int mode) | |||
| 938 | } | 938 | } |
| 939 | 939 | ||
| 940 | static bool | 940 | static bool |
| 941 | nvd0_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | 941 | nvd0_dac_mode_fixup(struct drm_encoder *encoder, |
| 942 | const struct drm_display_mode *mode, | ||
| 942 | struct drm_display_mode *adjusted_mode) | 943 | struct drm_display_mode *adjusted_mode) |
| 943 | { | 944 | { |
| 944 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 945 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
| @@ -1377,7 +1378,8 @@ nvd0_sor_dpms(struct drm_encoder *encoder, int mode) | |||
| 1377 | } | 1378 | } |
| 1378 | 1379 | ||
| 1379 | static bool | 1380 | static bool |
| 1380 | nvd0_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | 1381 | nvd0_sor_mode_fixup(struct drm_encoder *encoder, |
| 1382 | const struct drm_display_mode *mode, | ||
| 1381 | struct drm_display_mode *adjusted_mode) | 1383 | struct drm_display_mode *adjusted_mode) |
| 1382 | { | 1384 | { |
| 1383 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 1385 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c index 88718fad5d6d..2666a5308ab9 100644 --- a/drivers/gpu/drm/r128/r128_drv.c +++ b/drivers/gpu/drm/r128/r128_drv.c | |||
| @@ -71,7 +71,6 @@ static struct drm_driver driver = { | |||
| 71 | .irq_postinstall = r128_driver_irq_postinstall, | 71 | .irq_postinstall = r128_driver_irq_postinstall, |
| 72 | .irq_uninstall = r128_driver_irq_uninstall, | 72 | .irq_uninstall = r128_driver_irq_uninstall, |
| 73 | .irq_handler = r128_driver_irq_handler, | 73 | .irq_handler = r128_driver_irq_handler, |
| 74 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 75 | .ioctls = r128_ioctls, | 74 | .ioctls = r128_ioctls, |
| 76 | .dma_ioctl = r128_cce_buffers, | 75 | .dma_ioctl = r128_cce_buffers, |
| 77 | .fops = &r128_driver_fops, | 76 | .fops = &r128_driver_fops, |
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 3904d7964a4b..9e6f76fec527 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
| @@ -457,22 +457,18 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev, | |||
| 457 | switch (pll_id) { | 457 | switch (pll_id) { |
| 458 | case ATOM_PPLL1: | 458 | case ATOM_PPLL1: |
| 459 | args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P1PLL; | 459 | args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P1PLL; |
| 460 | args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); | ||
| 461 | args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step); | ||
| 462 | break; | 460 | break; |
| 463 | case ATOM_PPLL2: | 461 | case ATOM_PPLL2: |
| 464 | args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P2PLL; | 462 | args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P2PLL; |
| 465 | args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); | ||
| 466 | args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step); | ||
| 467 | break; | 463 | break; |
| 468 | case ATOM_DCPLL: | 464 | case ATOM_DCPLL: |
| 469 | args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_DCPLL; | 465 | args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_DCPLL; |
| 470 | args.v3.usSpreadSpectrumAmount = cpu_to_le16(0); | ||
| 471 | args.v3.usSpreadSpectrumStep = cpu_to_le16(0); | ||
| 472 | break; | 466 | break; |
| 473 | case ATOM_PPLL_INVALID: | 467 | case ATOM_PPLL_INVALID: |
| 474 | return; | 468 | return; |
| 475 | } | 469 | } |
| 470 | args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); | ||
| 471 | args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step); | ||
| 476 | args.v3.ucEnable = enable; | 472 | args.v3.ucEnable = enable; |
| 477 | if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE61(rdev)) | 473 | if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE61(rdev)) |
| 478 | args.v3.ucEnable = ATOM_DISABLE; | 474 | args.v3.ucEnable = ATOM_DISABLE; |
| @@ -482,22 +478,18 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev, | |||
| 482 | switch (pll_id) { | 478 | switch (pll_id) { |
| 483 | case ATOM_PPLL1: | 479 | case ATOM_PPLL1: |
| 484 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P1PLL; | 480 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P1PLL; |
| 485 | args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); | ||
| 486 | args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step); | ||
| 487 | break; | 481 | break; |
| 488 | case ATOM_PPLL2: | 482 | case ATOM_PPLL2: |
| 489 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P2PLL; | 483 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P2PLL; |
| 490 | args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); | ||
| 491 | args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step); | ||
| 492 | break; | 484 | break; |
| 493 | case ATOM_DCPLL: | 485 | case ATOM_DCPLL: |
| 494 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_DCPLL; | 486 | args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_DCPLL; |
| 495 | args.v2.usSpreadSpectrumAmount = cpu_to_le16(0); | ||
| 496 | args.v2.usSpreadSpectrumStep = cpu_to_le16(0); | ||
| 497 | break; | 487 | break; |
| 498 | case ATOM_PPLL_INVALID: | 488 | case ATOM_PPLL_INVALID: |
| 499 | return; | 489 | return; |
| 500 | } | 490 | } |
| 491 | args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); | ||
| 492 | args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step); | ||
| 501 | args.v2.ucEnable = enable; | 493 | args.v2.ucEnable = enable; |
| 502 | if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE41(rdev)) | 494 | if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE41(rdev)) |
| 503 | args.v2.ucEnable = ATOM_DISABLE; | 495 | args.v2.ucEnable = ATOM_DISABLE; |
| @@ -1539,7 +1531,11 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) | |||
| 1539 | * crtc virtual pixel clock. | 1531 | * crtc virtual pixel clock. |
| 1540 | */ | 1532 | */ |
| 1541 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { | 1533 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { |
| 1542 | if (ASIC_IS_DCE5(rdev) || rdev->clock.dp_extclk) | 1534 | if (ASIC_IS_DCE5(rdev)) |
| 1535 | return ATOM_DCPLL; | ||
| 1536 | else if (ASIC_IS_DCE6(rdev)) | ||
| 1537 | return ATOM_PPLL0; | ||
| 1538 | else if (rdev->clock.dp_extclk) | ||
| 1543 | return ATOM_PPLL_INVALID; | 1539 | return ATOM_PPLL_INVALID; |
| 1544 | } | 1540 | } |
| 1545 | } | 1541 | } |
| @@ -1628,7 +1624,7 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, | |||
| 1628 | } | 1624 | } |
| 1629 | 1625 | ||
| 1630 | static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, | 1626 | static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, |
| 1631 | struct drm_display_mode *mode, | 1627 | const struct drm_display_mode *mode, |
| 1632 | struct drm_display_mode *adjusted_mode) | 1628 | struct drm_display_mode *adjusted_mode) |
| 1633 | { | 1629 | { |
| 1634 | if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) | 1630 | if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) |
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 5131b3b0f7d2..7712cf5ab33b 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | * | 22 | * |
| 23 | * Authors: Dave Airlie | 23 | * Authors: Dave Airlie |
| 24 | * Alex Deucher | 24 | * Alex Deucher |
| 25 | * Jerome Glisse | ||
| 25 | */ | 26 | */ |
| 26 | #include "drmP.h" | 27 | #include "drmP.h" |
| 27 | #include "radeon_drm.h" | 28 | #include "radeon_drm.h" |
| @@ -608,7 +609,7 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, | |||
| 608 | } | 609 | } |
| 609 | 610 | ||
| 610 | void radeon_dp_set_link_config(struct drm_connector *connector, | 611 | void radeon_dp_set_link_config(struct drm_connector *connector, |
| 611 | struct drm_display_mode *mode) | 612 | const struct drm_display_mode *mode) |
| 612 | { | 613 | { |
| 613 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 614 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 614 | struct radeon_connector_atom_dig *dig_connector; | 615 | struct radeon_connector_atom_dig *dig_connector; |
| @@ -654,7 +655,6 @@ static bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector, | |||
| 654 | ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, | 655 | ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, |
| 655 | link_status, DP_LINK_STATUS_SIZE, 100); | 656 | link_status, DP_LINK_STATUS_SIZE, 100); |
| 656 | if (ret <= 0) { | 657 | if (ret <= 0) { |
| 657 | DRM_ERROR("displayport link status failed\n"); | ||
| 658 | return false; | 658 | return false; |
| 659 | } | 659 | } |
| 660 | 660 | ||
| @@ -833,8 +833,10 @@ static int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info) | |||
| 833 | else | 833 | else |
| 834 | mdelay(dp_info->rd_interval * 4); | 834 | mdelay(dp_info->rd_interval * 4); |
| 835 | 835 | ||
| 836 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) | 836 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { |
| 837 | DRM_ERROR("displayport link status failed\n"); | ||
| 837 | break; | 838 | break; |
| 839 | } | ||
| 838 | 840 | ||
| 839 | if (dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { | 841 | if (dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { |
| 840 | clock_recovery = true; | 842 | clock_recovery = true; |
| @@ -896,8 +898,10 @@ static int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info) | |||
| 896 | else | 898 | else |
| 897 | mdelay(dp_info->rd_interval * 4); | 899 | mdelay(dp_info->rd_interval * 4); |
| 898 | 900 | ||
| 899 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) | 901 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { |
| 902 | DRM_ERROR("displayport link status failed\n"); | ||
| 900 | break; | 903 | break; |
| 904 | } | ||
| 901 | 905 | ||
| 902 | if (dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { | 906 | if (dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { |
| 903 | channel_eq = true; | 907 | channel_eq = true; |
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 486ccdf4aacd..f9bc27fe269a 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c | |||
| @@ -58,7 +58,7 @@ static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder) | |||
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, | 60 | static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, |
| 61 | struct drm_display_mode *mode, | 61 | const struct drm_display_mode *mode, |
| 62 | struct drm_display_mode *adjusted_mode) | 62 | struct drm_display_mode *adjusted_mode) |
| 63 | { | 63 | { |
| 64 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 64 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| @@ -1392,10 +1392,18 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) | |||
| 1392 | case DRM_MODE_DPMS_ON: | 1392 | case DRM_MODE_DPMS_ON: |
| 1393 | /* some early dce3.2 boards have a bug in their transmitter control table */ | 1393 | /* some early dce3.2 boards have a bug in their transmitter control table */ |
| 1394 | if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) || | 1394 | if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) || |
| 1395 | ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) | 1395 | ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { |
| 1396 | if (ASIC_IS_DCE6(rdev)) { | ||
| 1397 | /* It seems we need to call ATOM_ENCODER_CMD_SETUP again | ||
| 1398 | * before reenabling encoder on DPMS ON, otherwise we never | ||
| 1399 | * get picture | ||
| 1400 | */ | ||
| 1401 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); | ||
| 1402 | } | ||
| 1396 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); | 1403 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); |
| 1397 | else | 1404 | } else { |
| 1398 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); | 1405 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); |
| 1406 | } | ||
| 1399 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { | 1407 | if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { |
| 1400 | if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { | 1408 | if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { |
| 1401 | atombios_set_edp_panel_power(connector, | 1409 | atombios_set_edp_panel_power(connector, |
| @@ -2234,7 +2242,7 @@ radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode) | |||
| 2234 | } | 2242 | } |
| 2235 | 2243 | ||
| 2236 | static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder, | 2244 | static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder, |
| 2237 | struct drm_display_mode *mode, | 2245 | const struct drm_display_mode *mode, |
| 2238 | struct drm_display_mode *adjusted_mode) | 2246 | struct drm_display_mode *adjusted_mode) |
| 2239 | { | 2247 | { |
| 2240 | return true; | 2248 | return true; |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 7fb3d2e0434c..e585a3b947eb 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
| @@ -99,6 +99,14 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev) | |||
| 99 | } | 99 | } |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | /** | ||
| 103 | * dce4_wait_for_vblank - vblank wait asic callback. | ||
| 104 | * | ||
| 105 | * @rdev: radeon_device pointer | ||
| 106 | * @crtc: crtc to wait for vblank on | ||
| 107 | * | ||
| 108 | * Wait for vblank on the requested crtc (evergreen+). | ||
| 109 | */ | ||
| 102 | void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) | 110 | void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) |
| 103 | { | 111 | { |
| 104 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; | 112 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; |
| @@ -118,18 +126,49 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) | |||
| 118 | } | 126 | } |
| 119 | } | 127 | } |
| 120 | 128 | ||
| 129 | /** | ||
| 130 | * radeon_irq_kms_pflip_irq_get - pre-pageflip callback. | ||
| 131 | * | ||
| 132 | * @rdev: radeon_device pointer | ||
| 133 | * @crtc: crtc to prepare for pageflip on | ||
| 134 | * | ||
| 135 | * Pre-pageflip callback (evergreen+). | ||
| 136 | * Enables the pageflip irq (vblank irq). | ||
| 137 | */ | ||
| 121 | void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc) | 138 | void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc) |
| 122 | { | 139 | { |
| 123 | /* enable the pflip int */ | 140 | /* enable the pflip int */ |
| 124 | radeon_irq_kms_pflip_irq_get(rdev, crtc); | 141 | radeon_irq_kms_pflip_irq_get(rdev, crtc); |
| 125 | } | 142 | } |
| 126 | 143 | ||
| 144 | /** | ||
| 145 | * evergreen_post_page_flip - pos-pageflip callback. | ||
| 146 | * | ||
| 147 | * @rdev: radeon_device pointer | ||
| 148 | * @crtc: crtc to cleanup pageflip on | ||
| 149 | * | ||
| 150 | * Post-pageflip callback (evergreen+). | ||
| 151 | * Disables the pageflip irq (vblank irq). | ||
| 152 | */ | ||
| 127 | void evergreen_post_page_flip(struct radeon_device *rdev, int crtc) | 153 | void evergreen_post_page_flip(struct radeon_device *rdev, int crtc) |
| 128 | { | 154 | { |
| 129 | /* disable the pflip int */ | 155 | /* disable the pflip int */ |
| 130 | radeon_irq_kms_pflip_irq_put(rdev, crtc); | 156 | radeon_irq_kms_pflip_irq_put(rdev, crtc); |
| 131 | } | 157 | } |
| 132 | 158 | ||
| 159 | /** | ||
| 160 | * evergreen_page_flip - pageflip callback. | ||
| 161 | * | ||
| 162 | * @rdev: radeon_device pointer | ||
| 163 | * @crtc_id: crtc to cleanup pageflip on | ||
| 164 | * @crtc_base: new address of the crtc (GPU MC address) | ||
| 165 | * | ||
| 166 | * Does the actual pageflip (evergreen+). | ||
| 167 | * During vblank we take the crtc lock and wait for the update_pending | ||
| 168 | * bit to go high, when it does, we release the lock, and allow the | ||
| 169 | * double buffered update to take place. | ||
| 170 | * Returns the current update pending status. | ||
| 171 | */ | ||
| 133 | u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) | 172 | u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) |
| 134 | { | 173 | { |
| 135 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; | 174 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; |
| @@ -214,6 +253,15 @@ int sumo_get_temp(struct radeon_device *rdev) | |||
| 214 | return actual_temp * 1000; | 253 | return actual_temp * 1000; |
| 215 | } | 254 | } |
| 216 | 255 | ||
| 256 | /** | ||
| 257 | * sumo_pm_init_profile - Initialize power profiles callback. | ||
| 258 | * | ||
| 259 | * @rdev: radeon_device pointer | ||
| 260 | * | ||
| 261 | * Initialize the power states used in profile mode | ||
| 262 | * (sumo, trinity, SI). | ||
| 263 | * Used for profile mode only. | ||
| 264 | */ | ||
| 217 | void sumo_pm_init_profile(struct radeon_device *rdev) | 265 | void sumo_pm_init_profile(struct radeon_device *rdev) |
| 218 | { | 266 | { |
| 219 | int idx; | 267 | int idx; |
| @@ -265,6 +313,14 @@ void sumo_pm_init_profile(struct radeon_device *rdev) | |||
| 265 | rdev->pm.power_state[idx].num_clock_modes - 1; | 313 | rdev->pm.power_state[idx].num_clock_modes - 1; |
| 266 | } | 314 | } |
| 267 | 315 | ||
| 316 | /** | ||
| 317 | * evergreen_pm_misc - set additional pm hw parameters callback. | ||
| 318 | * | ||
| 319 | * @rdev: radeon_device pointer | ||
| 320 | * | ||
| 321 | * Set non-clock parameters associated with a power state | ||
| 322 | * (voltage, etc.) (evergreen+). | ||
| 323 | */ | ||
| 268 | void evergreen_pm_misc(struct radeon_device *rdev) | 324 | void evergreen_pm_misc(struct radeon_device *rdev) |
| 269 | { | 325 | { |
| 270 | int req_ps_idx = rdev->pm.requested_power_state_index; | 326 | int req_ps_idx = rdev->pm.requested_power_state_index; |
| @@ -292,6 +348,13 @@ void evergreen_pm_misc(struct radeon_device *rdev) | |||
| 292 | } | 348 | } |
| 293 | } | 349 | } |
| 294 | 350 | ||
| 351 | /** | ||
| 352 | * evergreen_pm_prepare - pre-power state change callback. | ||
| 353 | * | ||
| 354 | * @rdev: radeon_device pointer | ||
| 355 | * | ||
| 356 | * Prepare for a power state change (evergreen+). | ||
| 357 | */ | ||
| 295 | void evergreen_pm_prepare(struct radeon_device *rdev) | 358 | void evergreen_pm_prepare(struct radeon_device *rdev) |
| 296 | { | 359 | { |
| 297 | struct drm_device *ddev = rdev->ddev; | 360 | struct drm_device *ddev = rdev->ddev; |
| @@ -310,6 +373,13 @@ void evergreen_pm_prepare(struct radeon_device *rdev) | |||
| 310 | } | 373 | } |
| 311 | } | 374 | } |
| 312 | 375 | ||
| 376 | /** | ||
| 377 | * evergreen_pm_finish - post-power state change callback. | ||
| 378 | * | ||
| 379 | * @rdev: radeon_device pointer | ||
| 380 | * | ||
| 381 | * Clean up after a power state change (evergreen+). | ||
| 382 | */ | ||
| 313 | void evergreen_pm_finish(struct radeon_device *rdev) | 383 | void evergreen_pm_finish(struct radeon_device *rdev) |
| 314 | { | 384 | { |
| 315 | struct drm_device *ddev = rdev->ddev; | 385 | struct drm_device *ddev = rdev->ddev; |
| @@ -328,6 +398,15 @@ void evergreen_pm_finish(struct radeon_device *rdev) | |||
| 328 | } | 398 | } |
| 329 | } | 399 | } |
| 330 | 400 | ||
| 401 | /** | ||
| 402 | * evergreen_hpd_sense - hpd sense callback. | ||
| 403 | * | ||
| 404 | * @rdev: radeon_device pointer | ||
| 405 | * @hpd: hpd (hotplug detect) pin | ||
| 406 | * | ||
| 407 | * Checks if a digital monitor is connected (evergreen+). | ||
| 408 | * Returns true if connected, false if not connected. | ||
| 409 | */ | ||
| 331 | bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) | 410 | bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) |
| 332 | { | 411 | { |
| 333 | bool connected = false; | 412 | bool connected = false; |
| @@ -364,6 +443,14 @@ bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) | |||
| 364 | return connected; | 443 | return connected; |
| 365 | } | 444 | } |
| 366 | 445 | ||
| 446 | /** | ||
| 447 | * evergreen_hpd_set_polarity - hpd set polarity callback. | ||
| 448 | * | ||
| 449 | * @rdev: radeon_device pointer | ||
| 450 | * @hpd: hpd (hotplug detect) pin | ||
| 451 | * | ||
| 452 | * Set the polarity of the hpd pin (evergreen+). | ||
| 453 | */ | ||
| 367 | void evergreen_hpd_set_polarity(struct radeon_device *rdev, | 454 | void evergreen_hpd_set_polarity(struct radeon_device *rdev, |
| 368 | enum radeon_hpd_id hpd) | 455 | enum radeon_hpd_id hpd) |
| 369 | { | 456 | { |
| @@ -424,10 +511,19 @@ void evergreen_hpd_set_polarity(struct radeon_device *rdev, | |||
| 424 | } | 511 | } |
| 425 | } | 512 | } |
| 426 | 513 | ||
| 514 | /** | ||
| 515 | * evergreen_hpd_init - hpd setup callback. | ||
| 516 | * | ||
| 517 | * @rdev: radeon_device pointer | ||
| 518 | * | ||
| 519 | * Setup the hpd pins used by the card (evergreen+). | ||
| 520 | * Enable the pin, set the polarity, and enable the hpd interrupts. | ||
| 521 | */ | ||
| 427 | void evergreen_hpd_init(struct radeon_device *rdev) | 522 | void evergreen_hpd_init(struct radeon_device *rdev) |
| 428 | { | 523 | { |
| 429 | struct drm_device *dev = rdev->ddev; | 524 | struct drm_device *dev = rdev->ddev; |
| 430 | struct drm_connector *connector; | 525 | struct drm_connector *connector; |
| 526 | unsigned enabled = 0; | ||
| 431 | u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | | 527 | u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | |
| 432 | DC_HPDx_RX_INT_TIMER(0xfa) | DC_HPDx_EN; | 528 | DC_HPDx_RX_INT_TIMER(0xfa) | DC_HPDx_EN; |
| 433 | 529 | ||
| @@ -436,73 +532,72 @@ void evergreen_hpd_init(struct radeon_device *rdev) | |||
| 436 | switch (radeon_connector->hpd.hpd) { | 532 | switch (radeon_connector->hpd.hpd) { |
| 437 | case RADEON_HPD_1: | 533 | case RADEON_HPD_1: |
| 438 | WREG32(DC_HPD1_CONTROL, tmp); | 534 | WREG32(DC_HPD1_CONTROL, tmp); |
| 439 | rdev->irq.hpd[0] = true; | ||
| 440 | break; | 535 | break; |
| 441 | case RADEON_HPD_2: | 536 | case RADEON_HPD_2: |
| 442 | WREG32(DC_HPD2_CONTROL, tmp); | 537 | WREG32(DC_HPD2_CONTROL, tmp); |
| 443 | rdev->irq.hpd[1] = true; | ||
| 444 | break; | 538 | break; |
| 445 | case RADEON_HPD_3: | 539 | case RADEON_HPD_3: |
| 446 | WREG32(DC_HPD3_CONTROL, tmp); | 540 | WREG32(DC_HPD3_CONTROL, tmp); |
| 447 | rdev->irq.hpd[2] = true; | ||
| 448 | break; | 541 | break; |
| 449 | case RADEON_HPD_4: | 542 | case RADEON_HPD_4: |
| 450 | WREG32(DC_HPD4_CONTROL, tmp); | 543 | WREG32(DC_HPD4_CONTROL, tmp); |
| 451 | rdev->irq.hpd[3] = true; | ||
| 452 | break; | 544 | break; |
| 453 | case RADEON_HPD_5: | 545 | case RADEON_HPD_5: |
| 454 | WREG32(DC_HPD5_CONTROL, tmp); | 546 | WREG32(DC_HPD5_CONTROL, tmp); |
| 455 | rdev->irq.hpd[4] = true; | ||
| 456 | break; | 547 | break; |
| 457 | case RADEON_HPD_6: | 548 | case RADEON_HPD_6: |
| 458 | WREG32(DC_HPD6_CONTROL, tmp); | 549 | WREG32(DC_HPD6_CONTROL, tmp); |
| 459 | rdev->irq.hpd[5] = true; | ||
| 460 | break; | 550 | break; |
| 461 | default: | 551 | default: |
| 462 | break; | 552 | break; |
| 463 | } | 553 | } |
| 464 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); | 554 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); |
| 555 | enabled |= 1 << radeon_connector->hpd.hpd; | ||
| 465 | } | 556 | } |
| 466 | if (rdev->irq.installed) | 557 | radeon_irq_kms_enable_hpd(rdev, enabled); |
| 467 | evergreen_irq_set(rdev); | ||
| 468 | } | 558 | } |
| 469 | 559 | ||
| 560 | /** | ||
| 561 | * evergreen_hpd_fini - hpd tear down callback. | ||
| 562 | * | ||
| 563 | * @rdev: radeon_device pointer | ||
| 564 | * | ||
| 565 | * Tear down the hpd pins used by the card (evergreen+). | ||
| 566 | * Disable the hpd interrupts. | ||
| 567 | */ | ||
| 470 | void evergreen_hpd_fini(struct radeon_device *rdev) | 568 | void evergreen_hpd_fini(struct radeon_device *rdev) |
| 471 | { | 569 | { |
| 472 | struct drm_device *dev = rdev->ddev; | 570 | struct drm_device *dev = rdev->ddev; |
| 473 | struct drm_connector *connector; | 571 | struct drm_connector *connector; |
| 572 | unsigned disabled = 0; | ||
| 474 | 573 | ||
| 475 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 574 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 476 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 575 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 477 | switch (radeon_connector->hpd.hpd) { | 576 | switch (radeon_connector->hpd.hpd) { |
| 478 | case RADEON_HPD_1: | 577 | case RADEON_HPD_1: |
| 479 | WREG32(DC_HPD1_CONTROL, 0); | 578 | WREG32(DC_HPD1_CONTROL, 0); |
| 480 | rdev->irq.hpd[0] = false; | ||
| 481 | break; | 579 | break; |
| 482 | case RADEON_HPD_2: | 580 | case RADEON_HPD_2: |
| 483 | WREG32(DC_HPD2_CONTROL, 0); | 581 | WREG32(DC_HPD2_CONTROL, 0); |
| 484 | rdev->irq.hpd[1] = false; | ||
| 485 | break; | 582 | break; |
| 486 | case RADEON_HPD_3: | 583 | case RADEON_HPD_3: |
| 487 | WREG32(DC_HPD3_CONTROL, 0); | 584 | WREG32(DC_HPD3_CONTROL, 0); |
| 488 | rdev->irq.hpd[2] = false; | ||
| 489 | break; | 585 | break; |
| 490 | case RADEON_HPD_4: | 586 | case RADEON_HPD_4: |
| 491 | WREG32(DC_HPD4_CONTROL, 0); | 587 | WREG32(DC_HPD4_CONTROL, 0); |
| 492 | rdev->irq.hpd[3] = false; | ||
| 493 | break; | 588 | break; |
| 494 | case RADEON_HPD_5: | 589 | case RADEON_HPD_5: |
| 495 | WREG32(DC_HPD5_CONTROL, 0); | 590 | WREG32(DC_HPD5_CONTROL, 0); |
| 496 | rdev->irq.hpd[4] = false; | ||
| 497 | break; | 591 | break; |
| 498 | case RADEON_HPD_6: | 592 | case RADEON_HPD_6: |
| 499 | WREG32(DC_HPD6_CONTROL, 0); | 593 | WREG32(DC_HPD6_CONTROL, 0); |
| 500 | rdev->irq.hpd[5] = false; | ||
| 501 | break; | 594 | break; |
| 502 | default: | 595 | default: |
| 503 | break; | 596 | break; |
| 504 | } | 597 | } |
| 598 | disabled |= 1 << radeon_connector->hpd.hpd; | ||
| 505 | } | 599 | } |
| 600 | radeon_irq_kms_disable_hpd(rdev, disabled); | ||
| 506 | } | 601 | } |
| 507 | 602 | ||
| 508 | /* watermark setup */ | 603 | /* watermark setup */ |
| @@ -933,6 +1028,14 @@ static void evergreen_program_watermarks(struct radeon_device *rdev, | |||
| 933 | 1028 | ||
| 934 | } | 1029 | } |
| 935 | 1030 | ||
| 1031 | /** | ||
| 1032 | * evergreen_bandwidth_update - update display watermarks callback. | ||
| 1033 | * | ||
| 1034 | * @rdev: radeon_device pointer | ||
| 1035 | * | ||
| 1036 | * Update the display watermarks based on the requested mode(s) | ||
| 1037 | * (evergreen+). | ||
| 1038 | */ | ||
| 936 | void evergreen_bandwidth_update(struct radeon_device *rdev) | 1039 | void evergreen_bandwidth_update(struct radeon_device *rdev) |
| 937 | { | 1040 | { |
| 938 | struct drm_display_mode *mode0 = NULL; | 1041 | struct drm_display_mode *mode0 = NULL; |
| @@ -956,6 +1059,15 @@ void evergreen_bandwidth_update(struct radeon_device *rdev) | |||
| 956 | } | 1059 | } |
| 957 | } | 1060 | } |
| 958 | 1061 | ||
| 1062 | /** | ||
| 1063 | * evergreen_mc_wait_for_idle - wait for MC idle callback. | ||
| 1064 | * | ||
| 1065 | * @rdev: radeon_device pointer | ||
| 1066 | * | ||
| 1067 | * Wait for the MC (memory controller) to be idle. | ||
| 1068 | * (evergreen+). | ||
| 1069 | * Returns 0 if the MC is idle, -1 if not. | ||
| 1070 | */ | ||
| 959 | int evergreen_mc_wait_for_idle(struct radeon_device *rdev) | 1071 | int evergreen_mc_wait_for_idle(struct radeon_device *rdev) |
| 960 | { | 1072 | { |
| 961 | unsigned i; | 1073 | unsigned i; |
| @@ -1371,12 +1483,28 @@ void evergreen_mc_program(struct radeon_device *rdev) | |||
| 1371 | */ | 1483 | */ |
| 1372 | void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) | 1484 | void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) |
| 1373 | { | 1485 | { |
| 1374 | struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; | 1486 | struct radeon_ring *ring = &rdev->ring[ib->ring]; |
| 1487 | u32 next_rptr; | ||
| 1375 | 1488 | ||
| 1376 | /* set to DX10/11 mode */ | 1489 | /* set to DX10/11 mode */ |
| 1377 | radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); | 1490 | radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); |
| 1378 | radeon_ring_write(ring, 1); | 1491 | radeon_ring_write(ring, 1); |
| 1379 | /* FIXME: implement */ | 1492 | |
| 1493 | if (ring->rptr_save_reg) { | ||
| 1494 | next_rptr = ring->wptr + 3 + 4; | ||
| 1495 | radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | ||
| 1496 | radeon_ring_write(ring, ((ring->rptr_save_reg - | ||
| 1497 | PACKET3_SET_CONFIG_REG_START) >> 2)); | ||
| 1498 | radeon_ring_write(ring, next_rptr); | ||
| 1499 | } else if (rdev->wb.enabled) { | ||
| 1500 | next_rptr = ring->wptr + 5 + 4; | ||
| 1501 | radeon_ring_write(ring, PACKET3(PACKET3_MEM_WRITE, 3)); | ||
| 1502 | radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); | ||
| 1503 | radeon_ring_write(ring, (upper_32_bits(ring->next_rptr_gpu_addr) & 0xff) | (1 << 18)); | ||
| 1504 | radeon_ring_write(ring, next_rptr); | ||
| 1505 | radeon_ring_write(ring, 0); | ||
| 1506 | } | ||
| 1507 | |||
| 1380 | radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); | 1508 | radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); |
| 1381 | radeon_ring_write(ring, | 1509 | radeon_ring_write(ring, |
| 1382 | #ifdef __BIG_ENDIAN | 1510 | #ifdef __BIG_ENDIAN |
| @@ -2188,6 +2316,14 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev) | |||
| 2188 | RREG32(GRBM_STATUS_SE1)); | 2316 | RREG32(GRBM_STATUS_SE1)); |
| 2189 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", | 2317 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", |
| 2190 | RREG32(SRBM_STATUS)); | 2318 | RREG32(SRBM_STATUS)); |
| 2319 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", | ||
| 2320 | RREG32(CP_STALLED_STAT1)); | ||
| 2321 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", | ||
| 2322 | RREG32(CP_STALLED_STAT2)); | ||
| 2323 | dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", | ||
| 2324 | RREG32(CP_BUSY_STAT)); | ||
| 2325 | dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", | ||
| 2326 | RREG32(CP_STAT)); | ||
| 2191 | evergreen_mc_stop(rdev, &save); | 2327 | evergreen_mc_stop(rdev, &save); |
| 2192 | if (evergreen_mc_wait_for_idle(rdev)) { | 2328 | if (evergreen_mc_wait_for_idle(rdev)) { |
| 2193 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); | 2329 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); |
| @@ -2225,6 +2361,14 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev) | |||
| 2225 | RREG32(GRBM_STATUS_SE1)); | 2361 | RREG32(GRBM_STATUS_SE1)); |
| 2226 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", | 2362 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", |
| 2227 | RREG32(SRBM_STATUS)); | 2363 | RREG32(SRBM_STATUS)); |
| 2364 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", | ||
| 2365 | RREG32(CP_STALLED_STAT1)); | ||
| 2366 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", | ||
| 2367 | RREG32(CP_STALLED_STAT2)); | ||
| 2368 | dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", | ||
| 2369 | RREG32(CP_BUSY_STAT)); | ||
| 2370 | dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", | ||
| 2371 | RREG32(CP_STAT)); | ||
| 2228 | evergreen_mc_resume(rdev, &save); | 2372 | evergreen_mc_resume(rdev, &save); |
| 2229 | return 0; | 2373 | return 0; |
| 2230 | } | 2374 | } |
| @@ -2348,20 +2492,20 @@ int evergreen_irq_set(struct radeon_device *rdev) | |||
| 2348 | 2492 | ||
| 2349 | if (rdev->family >= CHIP_CAYMAN) { | 2493 | if (rdev->family >= CHIP_CAYMAN) { |
| 2350 | /* enable CP interrupts on all rings */ | 2494 | /* enable CP interrupts on all rings */ |
| 2351 | if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { | 2495 | if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { |
| 2352 | DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); | 2496 | DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); |
| 2353 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; | 2497 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; |
| 2354 | } | 2498 | } |
| 2355 | if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP1_INDEX]) { | 2499 | if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP1_INDEX])) { |
| 2356 | DRM_DEBUG("evergreen_irq_set: sw int cp1\n"); | 2500 | DRM_DEBUG("evergreen_irq_set: sw int cp1\n"); |
| 2357 | cp_int_cntl1 |= TIME_STAMP_INT_ENABLE; | 2501 | cp_int_cntl1 |= TIME_STAMP_INT_ENABLE; |
| 2358 | } | 2502 | } |
| 2359 | if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP2_INDEX]) { | 2503 | if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP2_INDEX])) { |
| 2360 | DRM_DEBUG("evergreen_irq_set: sw int cp2\n"); | 2504 | DRM_DEBUG("evergreen_irq_set: sw int cp2\n"); |
| 2361 | cp_int_cntl2 |= TIME_STAMP_INT_ENABLE; | 2505 | cp_int_cntl2 |= TIME_STAMP_INT_ENABLE; |
| 2362 | } | 2506 | } |
| 2363 | } else { | 2507 | } else { |
| 2364 | if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { | 2508 | if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { |
| 2365 | DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); | 2509 | DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); |
| 2366 | cp_int_cntl |= RB_INT_ENABLE; | 2510 | cp_int_cntl |= RB_INT_ENABLE; |
| 2367 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; | 2511 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; |
| @@ -2369,32 +2513,32 @@ int evergreen_irq_set(struct radeon_device *rdev) | |||
| 2369 | } | 2513 | } |
| 2370 | 2514 | ||
| 2371 | if (rdev->irq.crtc_vblank_int[0] || | 2515 | if (rdev->irq.crtc_vblank_int[0] || |
| 2372 | rdev->irq.pflip[0]) { | 2516 | atomic_read(&rdev->irq.pflip[0])) { |
| 2373 | DRM_DEBUG("evergreen_irq_set: vblank 0\n"); | 2517 | DRM_DEBUG("evergreen_irq_set: vblank 0\n"); |
| 2374 | crtc1 |= VBLANK_INT_MASK; | 2518 | crtc1 |= VBLANK_INT_MASK; |
| 2375 | } | 2519 | } |
| 2376 | if (rdev->irq.crtc_vblank_int[1] || | 2520 | if (rdev->irq.crtc_vblank_int[1] || |
| 2377 | rdev->irq.pflip[1]) { | 2521 | atomic_read(&rdev->irq.pflip[1])) { |
| 2378 | DRM_DEBUG("evergreen_irq_set: vblank 1\n"); | 2522 | DRM_DEBUG("evergreen_irq_set: vblank 1\n"); |
| 2379 | crtc2 |= VBLANK_INT_MASK; | 2523 | crtc2 |= VBLANK_INT_MASK; |
| 2380 | } | 2524 | } |
| 2381 | if (rdev->irq.crtc_vblank_int[2] || | 2525 | if (rdev->irq.crtc_vblank_int[2] || |
| 2382 | rdev->irq.pflip[2]) { | 2526 | atomic_read(&rdev->irq.pflip[2])) { |
| 2383 | DRM_DEBUG("evergreen_irq_set: vblank 2\n"); | 2527 | DRM_DEBUG("evergreen_irq_set: vblank 2\n"); |
| 2384 | crtc3 |= VBLANK_INT_MASK; | 2528 | crtc3 |= VBLANK_INT_MASK; |
| 2385 | } | 2529 | } |
| 2386 | if (rdev->irq.crtc_vblank_int[3] || | 2530 | if (rdev->irq.crtc_vblank_int[3] || |
| 2387 | rdev->irq.pflip[3]) { | 2531 | atomic_read(&rdev->irq.pflip[3])) { |
| 2388 | DRM_DEBUG("evergreen_irq_set: vblank 3\n"); | 2532 | DRM_DEBUG("evergreen_irq_set: vblank 3\n"); |
| 2389 | crtc4 |= VBLANK_INT_MASK; | 2533 | crtc4 |= VBLANK_INT_MASK; |
| 2390 | } | 2534 | } |
| 2391 | if (rdev->irq.crtc_vblank_int[4] || | 2535 | if (rdev->irq.crtc_vblank_int[4] || |
| 2392 | rdev->irq.pflip[4]) { | 2536 | atomic_read(&rdev->irq.pflip[4])) { |
| 2393 | DRM_DEBUG("evergreen_irq_set: vblank 4\n"); | 2537 | DRM_DEBUG("evergreen_irq_set: vblank 4\n"); |
| 2394 | crtc5 |= VBLANK_INT_MASK; | 2538 | crtc5 |= VBLANK_INT_MASK; |
| 2395 | } | 2539 | } |
| 2396 | if (rdev->irq.crtc_vblank_int[5] || | 2540 | if (rdev->irq.crtc_vblank_int[5] || |
| 2397 | rdev->irq.pflip[5]) { | 2541 | atomic_read(&rdev->irq.pflip[5])) { |
| 2398 | DRM_DEBUG("evergreen_irq_set: vblank 5\n"); | 2542 | DRM_DEBUG("evergreen_irq_set: vblank 5\n"); |
| 2399 | crtc6 |= VBLANK_INT_MASK; | 2543 | crtc6 |= VBLANK_INT_MASK; |
| 2400 | } | 2544 | } |
| @@ -2676,7 +2820,6 @@ int evergreen_irq_process(struct radeon_device *rdev) | |||
| 2676 | u32 rptr; | 2820 | u32 rptr; |
| 2677 | u32 src_id, src_data; | 2821 | u32 src_id, src_data; |
| 2678 | u32 ring_index; | 2822 | u32 ring_index; |
| 2679 | unsigned long flags; | ||
| 2680 | bool queue_hotplug = false; | 2823 | bool queue_hotplug = false; |
| 2681 | bool queue_hdmi = false; | 2824 | bool queue_hdmi = false; |
| 2682 | 2825 | ||
| @@ -2684,22 +2827,21 @@ int evergreen_irq_process(struct radeon_device *rdev) | |||
| 2684 | return IRQ_NONE; | 2827 | return IRQ_NONE; |
| 2685 | 2828 | ||
| 2686 | wptr = evergreen_get_ih_wptr(rdev); | 2829 | wptr = evergreen_get_ih_wptr(rdev); |
| 2830 | |||
| 2831 | restart_ih: | ||
| 2832 | /* is somebody else already processing irqs? */ | ||
| 2833 | if (atomic_xchg(&rdev->ih.lock, 1)) | ||
| 2834 | return IRQ_NONE; | ||
| 2835 | |||
| 2687 | rptr = rdev->ih.rptr; | 2836 | rptr = rdev->ih.rptr; |
| 2688 | DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); | 2837 | DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); |
| 2689 | 2838 | ||
| 2690 | spin_lock_irqsave(&rdev->ih.lock, flags); | ||
| 2691 | if (rptr == wptr) { | ||
| 2692 | spin_unlock_irqrestore(&rdev->ih.lock, flags); | ||
| 2693 | return IRQ_NONE; | ||
| 2694 | } | ||
| 2695 | restart_ih: | ||
| 2696 | /* Order reading of wptr vs. reading of IH ring data */ | 2839 | /* Order reading of wptr vs. reading of IH ring data */ |
| 2697 | rmb(); | 2840 | rmb(); |
| 2698 | 2841 | ||
| 2699 | /* display interrupts */ | 2842 | /* display interrupts */ |
| 2700 | evergreen_irq_ack(rdev); | 2843 | evergreen_irq_ack(rdev); |
| 2701 | 2844 | ||
| 2702 | rdev->ih.wptr = wptr; | ||
| 2703 | while (rptr != wptr) { | 2845 | while (rptr != wptr) { |
| 2704 | /* wptr/rptr are in bytes! */ | 2846 | /* wptr/rptr are in bytes! */ |
| 2705 | ring_index = rptr / 4; | 2847 | ring_index = rptr / 4; |
| @@ -2716,7 +2858,7 @@ restart_ih: | |||
| 2716 | rdev->pm.vblank_sync = true; | 2858 | rdev->pm.vblank_sync = true; |
| 2717 | wake_up(&rdev->irq.vblank_queue); | 2859 | wake_up(&rdev->irq.vblank_queue); |
| 2718 | } | 2860 | } |
| 2719 | if (rdev->irq.pflip[0]) | 2861 | if (atomic_read(&rdev->irq.pflip[0])) |
| 2720 | radeon_crtc_handle_flip(rdev, 0); | 2862 | radeon_crtc_handle_flip(rdev, 0); |
| 2721 | rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; | 2863 | rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; |
| 2722 | DRM_DEBUG("IH: D1 vblank\n"); | 2864 | DRM_DEBUG("IH: D1 vblank\n"); |
| @@ -2742,7 +2884,7 @@ restart_ih: | |||
| 2742 | rdev->pm.vblank_sync = true; | 2884 | rdev->pm.vblank_sync = true; |
| 2743 | wake_up(&rdev->irq.vblank_queue); | 2885 | wake_up(&rdev->irq.vblank_queue); |
| 2744 | } | 2886 | } |
| 2745 | if (rdev->irq.pflip[1]) | 2887 | if (atomic_read(&rdev->irq.pflip[1])) |
| 2746 | radeon_crtc_handle_flip(rdev, 1); | 2888 | radeon_crtc_handle_flip(rdev, 1); |
| 2747 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; | 2889 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; |
| 2748 | DRM_DEBUG("IH: D2 vblank\n"); | 2890 | DRM_DEBUG("IH: D2 vblank\n"); |
| @@ -2768,7 +2910,7 @@ restart_ih: | |||
| 2768 | rdev->pm.vblank_sync = true; | 2910 | rdev->pm.vblank_sync = true; |
| 2769 | wake_up(&rdev->irq.vblank_queue); | 2911 | wake_up(&rdev->irq.vblank_queue); |
| 2770 | } | 2912 | } |
| 2771 | if (rdev->irq.pflip[2]) | 2913 | if (atomic_read(&rdev->irq.pflip[2])) |
| 2772 | radeon_crtc_handle_flip(rdev, 2); | 2914 | radeon_crtc_handle_flip(rdev, 2); |
| 2773 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; | 2915 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; |
| 2774 | DRM_DEBUG("IH: D3 vblank\n"); | 2916 | DRM_DEBUG("IH: D3 vblank\n"); |
| @@ -2794,7 +2936,7 @@ restart_ih: | |||
| 2794 | rdev->pm.vblank_sync = true; | 2936 | rdev->pm.vblank_sync = true; |
| 2795 | wake_up(&rdev->irq.vblank_queue); | 2937 | wake_up(&rdev->irq.vblank_queue); |
| 2796 | } | 2938 | } |
| 2797 | if (rdev->irq.pflip[3]) | 2939 | if (atomic_read(&rdev->irq.pflip[3])) |
| 2798 | radeon_crtc_handle_flip(rdev, 3); | 2940 | radeon_crtc_handle_flip(rdev, 3); |
| 2799 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; | 2941 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; |
| 2800 | DRM_DEBUG("IH: D4 vblank\n"); | 2942 | DRM_DEBUG("IH: D4 vblank\n"); |
| @@ -2820,7 +2962,7 @@ restart_ih: | |||
| 2820 | rdev->pm.vblank_sync = true; | 2962 | rdev->pm.vblank_sync = true; |
| 2821 | wake_up(&rdev->irq.vblank_queue); | 2963 | wake_up(&rdev->irq.vblank_queue); |
| 2822 | } | 2964 | } |
| 2823 | if (rdev->irq.pflip[4]) | 2965 | if (atomic_read(&rdev->irq.pflip[4])) |
| 2824 | radeon_crtc_handle_flip(rdev, 4); | 2966 | radeon_crtc_handle_flip(rdev, 4); |
| 2825 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; | 2967 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; |
| 2826 | DRM_DEBUG("IH: D5 vblank\n"); | 2968 | DRM_DEBUG("IH: D5 vblank\n"); |
| @@ -2846,7 +2988,7 @@ restart_ih: | |||
| 2846 | rdev->pm.vblank_sync = true; | 2988 | rdev->pm.vblank_sync = true; |
| 2847 | wake_up(&rdev->irq.vblank_queue); | 2989 | wake_up(&rdev->irq.vblank_queue); |
| 2848 | } | 2990 | } |
| 2849 | if (rdev->irq.pflip[5]) | 2991 | if (atomic_read(&rdev->irq.pflip[5])) |
| 2850 | radeon_crtc_handle_flip(rdev, 5); | 2992 | radeon_crtc_handle_flip(rdev, 5); |
| 2851 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; | 2993 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; |
| 2852 | DRM_DEBUG("IH: D6 vblank\n"); | 2994 | DRM_DEBUG("IH: D6 vblank\n"); |
| @@ -2986,7 +3128,6 @@ restart_ih: | |||
| 2986 | break; | 3128 | break; |
| 2987 | case 233: /* GUI IDLE */ | 3129 | case 233: /* GUI IDLE */ |
| 2988 | DRM_DEBUG("IH: GUI idle\n"); | 3130 | DRM_DEBUG("IH: GUI idle\n"); |
| 2989 | rdev->pm.gui_idle = true; | ||
| 2990 | wake_up(&rdev->irq.idle_queue); | 3131 | wake_up(&rdev->irq.idle_queue); |
| 2991 | break; | 3132 | break; |
| 2992 | default: | 3133 | default: |
| @@ -2998,17 +3139,19 @@ restart_ih: | |||
| 2998 | rptr += 16; | 3139 | rptr += 16; |
| 2999 | rptr &= rdev->ih.ptr_mask; | 3140 | rptr &= rdev->ih.ptr_mask; |
| 3000 | } | 3141 | } |
| 3001 | /* make sure wptr hasn't changed while processing */ | ||
| 3002 | wptr = evergreen_get_ih_wptr(rdev); | ||
| 3003 | if (wptr != rdev->ih.wptr) | ||
| 3004 | goto restart_ih; | ||
| 3005 | if (queue_hotplug) | 3142 | if (queue_hotplug) |
| 3006 | schedule_work(&rdev->hotplug_work); | 3143 | schedule_work(&rdev->hotplug_work); |
| 3007 | if (queue_hdmi) | 3144 | if (queue_hdmi) |
| 3008 | schedule_work(&rdev->audio_work); | 3145 | schedule_work(&rdev->audio_work); |
| 3009 | rdev->ih.rptr = rptr; | 3146 | rdev->ih.rptr = rptr; |
| 3010 | WREG32(IH_RB_RPTR, rdev->ih.rptr); | 3147 | WREG32(IH_RB_RPTR, rdev->ih.rptr); |
| 3011 | spin_unlock_irqrestore(&rdev->ih.lock, flags); | 3148 | atomic_set(&rdev->ih.lock, 0); |
| 3149 | |||
| 3150 | /* make sure wptr hasn't changed while processing */ | ||
| 3151 | wptr = evergreen_get_ih_wptr(rdev); | ||
| 3152 | if (wptr != rptr) | ||
| 3153 | goto restart_ih; | ||
| 3154 | |||
| 3012 | return IRQ_HANDLED; | 3155 | return IRQ_HANDLED; |
| 3013 | } | 3156 | } |
| 3014 | 3157 | ||
| @@ -3096,13 +3239,11 @@ static int evergreen_startup(struct radeon_device *rdev) | |||
| 3096 | if (r) | 3239 | if (r) |
| 3097 | return r; | 3240 | return r; |
| 3098 | 3241 | ||
| 3099 | r = radeon_ib_pool_start(rdev); | 3242 | r = radeon_ib_pool_init(rdev); |
| 3100 | if (r) | 3243 | if (r) { |
| 3101 | return r; | 3244 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 3102 | |||
| 3103 | r = radeon_ib_ring_tests(rdev); | ||
| 3104 | if (r) | ||
| 3105 | return r; | 3245 | return r; |
| 3246 | } | ||
| 3106 | 3247 | ||
| 3107 | r = r600_audio_init(rdev); | 3248 | r = r600_audio_init(rdev); |
| 3108 | if (r) { | 3249 | if (r) { |
| @@ -3146,9 +3287,6 @@ int evergreen_suspend(struct radeon_device *rdev) | |||
| 3146 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | 3287 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
| 3147 | 3288 | ||
| 3148 | r600_audio_fini(rdev); | 3289 | r600_audio_fini(rdev); |
| 3149 | /* FIXME: we should wait for ring to be empty */ | ||
| 3150 | radeon_ib_pool_suspend(rdev); | ||
| 3151 | r600_blit_suspend(rdev); | ||
| 3152 | r700_cp_stop(rdev); | 3290 | r700_cp_stop(rdev); |
| 3153 | ring->ready = false; | 3291 | ring->ready = false; |
| 3154 | evergreen_irq_suspend(rdev); | 3292 | evergreen_irq_suspend(rdev); |
| @@ -3234,20 +3372,14 @@ int evergreen_init(struct radeon_device *rdev) | |||
| 3234 | if (r) | 3372 | if (r) |
| 3235 | return r; | 3373 | return r; |
| 3236 | 3374 | ||
| 3237 | r = radeon_ib_pool_init(rdev); | ||
| 3238 | rdev->accel_working = true; | 3375 | rdev->accel_working = true; |
| 3239 | if (r) { | ||
| 3240 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 3241 | rdev->accel_working = false; | ||
| 3242 | } | ||
| 3243 | |||
| 3244 | r = evergreen_startup(rdev); | 3376 | r = evergreen_startup(rdev); |
| 3245 | if (r) { | 3377 | if (r) { |
| 3246 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | 3378 | dev_err(rdev->dev, "disabling GPU acceleration\n"); |
| 3247 | r700_cp_fini(rdev); | 3379 | r700_cp_fini(rdev); |
| 3248 | r600_irq_fini(rdev); | 3380 | r600_irq_fini(rdev); |
| 3249 | radeon_wb_fini(rdev); | 3381 | radeon_wb_fini(rdev); |
| 3250 | r100_ib_fini(rdev); | 3382 | radeon_ib_pool_fini(rdev); |
| 3251 | radeon_irq_kms_fini(rdev); | 3383 | radeon_irq_kms_fini(rdev); |
| 3252 | evergreen_pcie_gart_fini(rdev); | 3384 | evergreen_pcie_gart_fini(rdev); |
| 3253 | rdev->accel_working = false; | 3385 | rdev->accel_working = false; |
| @@ -3274,7 +3406,7 @@ void evergreen_fini(struct radeon_device *rdev) | |||
| 3274 | r700_cp_fini(rdev); | 3406 | r700_cp_fini(rdev); |
| 3275 | r600_irq_fini(rdev); | 3407 | r600_irq_fini(rdev); |
| 3276 | radeon_wb_fini(rdev); | 3408 | radeon_wb_fini(rdev); |
| 3277 | r100_ib_fini(rdev); | 3409 | radeon_ib_pool_fini(rdev); |
| 3278 | radeon_irq_kms_fini(rdev); | 3410 | radeon_irq_kms_fini(rdev); |
| 3279 | evergreen_pcie_gart_fini(rdev); | 3411 | evergreen_pcie_gart_fini(rdev); |
| 3280 | r600_vram_scratch_fini(rdev); | 3412 | r600_vram_scratch_fini(rdev); |
| @@ -3289,7 +3421,8 @@ void evergreen_fini(struct radeon_device *rdev) | |||
| 3289 | 3421 | ||
| 3290 | void evergreen_pcie_gen2_enable(struct radeon_device *rdev) | 3422 | void evergreen_pcie_gen2_enable(struct radeon_device *rdev) |
| 3291 | { | 3423 | { |
| 3292 | u32 link_width_cntl, speed_cntl; | 3424 | u32 link_width_cntl, speed_cntl, mask; |
| 3425 | int ret; | ||
| 3293 | 3426 | ||
| 3294 | if (radeon_pcie_gen2 == 0) | 3427 | if (radeon_pcie_gen2 == 0) |
| 3295 | return; | 3428 | return; |
| @@ -3304,6 +3437,15 @@ void evergreen_pcie_gen2_enable(struct radeon_device *rdev) | |||
| 3304 | if (ASIC_IS_X2(rdev)) | 3437 | if (ASIC_IS_X2(rdev)) |
| 3305 | return; | 3438 | return; |
| 3306 | 3439 | ||
| 3440 | ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); | ||
| 3441 | if (ret != 0) | ||
| 3442 | return; | ||
| 3443 | |||
| 3444 | if (!(mask & DRM_PCIE_SPEED_50)) | ||
| 3445 | return; | ||
| 3446 | |||
| 3447 | DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); | ||
| 3448 | |||
| 3307 | speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); | 3449 | speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); |
| 3308 | if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) || | 3450 | if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) || |
| 3309 | (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) { | 3451 | (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) { |
diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/drivers/gpu/drm/radeon/evergreen_blit_kms.c index 1e96bd458cfd..89cb9feb5653 100644 --- a/drivers/gpu/drm/radeon/evergreen_blit_kms.c +++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c | |||
| @@ -622,7 +622,8 @@ int evergreen_blit_init(struct radeon_device *rdev) | |||
| 622 | rdev->r600_blit.primitives.draw_auto = draw_auto; | 622 | rdev->r600_blit.primitives.draw_auto = draw_auto; |
| 623 | rdev->r600_blit.primitives.set_default_state = set_default_state; | 623 | rdev->r600_blit.primitives.set_default_state = set_default_state; |
| 624 | 624 | ||
| 625 | rdev->r600_blit.ring_size_common = 55; /* shaders + def state */ | 625 | rdev->r600_blit.ring_size_common = 8; /* sync semaphore */ |
| 626 | rdev->r600_blit.ring_size_common += 55; /* shaders + def state */ | ||
| 626 | rdev->r600_blit.ring_size_common += 16; /* fence emit for VB IB */ | 627 | rdev->r600_blit.ring_size_common += 16; /* fence emit for VB IB */ |
| 627 | rdev->r600_blit.ring_size_common += 5; /* done copy */ | 628 | rdev->r600_blit.ring_size_common += 5; /* done copy */ |
| 628 | rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */ | 629 | rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */ |
| @@ -633,10 +634,6 @@ int evergreen_blit_init(struct radeon_device *rdev) | |||
| 633 | 634 | ||
| 634 | rdev->r600_blit.max_dim = 16384; | 635 | rdev->r600_blit.max_dim = 16384; |
| 635 | 636 | ||
| 636 | /* pin copy shader into vram if already initialized */ | ||
| 637 | if (rdev->r600_blit.shader_obj) | ||
| 638 | goto done; | ||
| 639 | |||
| 640 | rdev->r600_blit.state_offset = 0; | 637 | rdev->r600_blit.state_offset = 0; |
| 641 | 638 | ||
| 642 | if (rdev->family < CHIP_CAYMAN) | 639 | if (rdev->family < CHIP_CAYMAN) |
| @@ -667,11 +664,26 @@ int evergreen_blit_init(struct radeon_device *rdev) | |||
| 667 | obj_size += cayman_ps_size * 4; | 664 | obj_size += cayman_ps_size * 4; |
| 668 | obj_size = ALIGN(obj_size, 256); | 665 | obj_size = ALIGN(obj_size, 256); |
| 669 | 666 | ||
| 670 | r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, | 667 | /* pin copy shader into vram if not already initialized */ |
| 671 | NULL, &rdev->r600_blit.shader_obj); | 668 | if (!rdev->r600_blit.shader_obj) { |
| 672 | if (r) { | 669 | r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, |
| 673 | DRM_ERROR("evergreen failed to allocate shader\n"); | 670 | RADEON_GEM_DOMAIN_VRAM, |
| 674 | return r; | 671 | NULL, &rdev->r600_blit.shader_obj); |
| 672 | if (r) { | ||
| 673 | DRM_ERROR("evergreen failed to allocate shader\n"); | ||
| 674 | return r; | ||
| 675 | } | ||
| 676 | |||
| 677 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | ||
| 678 | if (unlikely(r != 0)) | ||
| 679 | return r; | ||
| 680 | r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, | ||
| 681 | &rdev->r600_blit.shader_gpu_addr); | ||
| 682 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
| 683 | if (r) { | ||
| 684 | dev_err(rdev->dev, "(%d) pin blit object failed\n", r); | ||
| 685 | return r; | ||
| 686 | } | ||
| 675 | } | 687 | } |
| 676 | 688 | ||
| 677 | DRM_DEBUG("evergreen blit allocated bo %08x vs %08x ps %08x\n", | 689 | DRM_DEBUG("evergreen blit allocated bo %08x vs %08x ps %08x\n", |
| @@ -713,17 +725,6 @@ int evergreen_blit_init(struct radeon_device *rdev) | |||
| 713 | radeon_bo_kunmap(rdev->r600_blit.shader_obj); | 725 | radeon_bo_kunmap(rdev->r600_blit.shader_obj); |
| 714 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | 726 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); |
| 715 | 727 | ||
| 716 | done: | ||
| 717 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | ||
| 718 | if (unlikely(r != 0)) | ||
| 719 | return r; | ||
| 720 | r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, | ||
| 721 | &rdev->r600_blit.shader_gpu_addr); | ||
| 722 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
| 723 | if (r) { | ||
| 724 | dev_err(rdev->dev, "(%d) pin blit object failed\n", r); | ||
| 725 | return r; | ||
| 726 | } | ||
| 727 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); | 728 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); |
| 728 | return 0; | 729 | return 0; |
| 729 | } | 730 | } |
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index b50b15c70498..d3bd098e4e19 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h | |||
| @@ -88,6 +88,10 @@ | |||
| 88 | #define CONFIG_MEMSIZE 0x5428 | 88 | #define CONFIG_MEMSIZE 0x5428 |
| 89 | 89 | ||
| 90 | #define CP_COHER_BASE 0x85F8 | 90 | #define CP_COHER_BASE 0x85F8 |
| 91 | #define CP_STALLED_STAT1 0x8674 | ||
| 92 | #define CP_STALLED_STAT2 0x8678 | ||
| 93 | #define CP_BUSY_STAT 0x867C | ||
| 94 | #define CP_STAT 0x8680 | ||
| 91 | #define CP_ME_CNTL 0x86D8 | 95 | #define CP_ME_CNTL 0x86D8 |
| 92 | #define CP_ME_HALT (1 << 28) | 96 | #define CP_ME_HALT (1 << 28) |
| 93 | #define CP_PFP_HALT (1 << 26) | 97 | #define CP_PFP_HALT (1 << 26) |
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index b7bf18e40215..9945d86d9001 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
| @@ -850,11 +850,20 @@ void cayman_fence_ring_emit(struct radeon_device *rdev, | |||
| 850 | 850 | ||
| 851 | void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) | 851 | void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) |
| 852 | { | 852 | { |
| 853 | struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; | 853 | struct radeon_ring *ring = &rdev->ring[ib->ring]; |
| 854 | 854 | ||
| 855 | /* set to DX10/11 mode */ | 855 | /* set to DX10/11 mode */ |
| 856 | radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); | 856 | radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); |
| 857 | radeon_ring_write(ring, 1); | 857 | radeon_ring_write(ring, 1); |
| 858 | |||
| 859 | if (ring->rptr_save_reg) { | ||
| 860 | uint32_t next_rptr = ring->wptr + 3 + 4 + 8; | ||
| 861 | radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | ||
| 862 | radeon_ring_write(ring, ((ring->rptr_save_reg - | ||
| 863 | PACKET3_SET_CONFIG_REG_START) >> 2)); | ||
| 864 | radeon_ring_write(ring, next_rptr); | ||
| 865 | } | ||
| 866 | |||
| 858 | radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); | 867 | radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); |
| 859 | radeon_ring_write(ring, | 868 | radeon_ring_write(ring, |
| 860 | #ifdef __BIG_ENDIAN | 869 | #ifdef __BIG_ENDIAN |
| @@ -981,16 +990,41 @@ static int cayman_cp_start(struct radeon_device *rdev) | |||
| 981 | 990 | ||
| 982 | static void cayman_cp_fini(struct radeon_device *rdev) | 991 | static void cayman_cp_fini(struct radeon_device *rdev) |
| 983 | { | 992 | { |
| 993 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | ||
| 984 | cayman_cp_enable(rdev, false); | 994 | cayman_cp_enable(rdev, false); |
| 985 | radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); | 995 | radeon_ring_fini(rdev, ring); |
| 996 | radeon_scratch_free(rdev, ring->rptr_save_reg); | ||
| 986 | } | 997 | } |
| 987 | 998 | ||
| 988 | int cayman_cp_resume(struct radeon_device *rdev) | 999 | int cayman_cp_resume(struct radeon_device *rdev) |
| 989 | { | 1000 | { |
| 1001 | static const int ridx[] = { | ||
| 1002 | RADEON_RING_TYPE_GFX_INDEX, | ||
| 1003 | CAYMAN_RING_TYPE_CP1_INDEX, | ||
| 1004 | CAYMAN_RING_TYPE_CP2_INDEX | ||
| 1005 | }; | ||
| 1006 | static const unsigned cp_rb_cntl[] = { | ||
| 1007 | CP_RB0_CNTL, | ||
| 1008 | CP_RB1_CNTL, | ||
| 1009 | CP_RB2_CNTL, | ||
| 1010 | }; | ||
| 1011 | static const unsigned cp_rb_rptr_addr[] = { | ||
| 1012 | CP_RB0_RPTR_ADDR, | ||
| 1013 | CP_RB1_RPTR_ADDR, | ||
| 1014 | CP_RB2_RPTR_ADDR | ||
| 1015 | }; | ||
| 1016 | static const unsigned cp_rb_rptr_addr_hi[] = { | ||
| 1017 | CP_RB0_RPTR_ADDR_HI, | ||
| 1018 | CP_RB1_RPTR_ADDR_HI, | ||
| 1019 | CP_RB2_RPTR_ADDR_HI | ||
| 1020 | }; | ||
| 1021 | static const unsigned cp_rb_base[] = { | ||
| 1022 | CP_RB0_BASE, | ||
| 1023 | CP_RB1_BASE, | ||
| 1024 | CP_RB2_BASE | ||
| 1025 | }; | ||
| 990 | struct radeon_ring *ring; | 1026 | struct radeon_ring *ring; |
| 991 | u32 tmp; | 1027 | int i, r; |
| 992 | u32 rb_bufsz; | ||
| 993 | int r; | ||
| 994 | 1028 | ||
| 995 | /* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */ | 1029 | /* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */ |
| 996 | WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP | | 1030 | WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP | |
| @@ -1012,91 +1046,47 @@ int cayman_cp_resume(struct radeon_device *rdev) | |||
| 1012 | 1046 | ||
| 1013 | WREG32(CP_DEBUG, (1 << 27)); | 1047 | WREG32(CP_DEBUG, (1 << 27)); |
| 1014 | 1048 | ||
| 1015 | /* ring 0 - compute and gfx */ | ||
| 1016 | /* Set ring buffer size */ | ||
| 1017 | ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | ||
| 1018 | rb_bufsz = drm_order(ring->ring_size / 8); | ||
| 1019 | tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; | ||
| 1020 | #ifdef __BIG_ENDIAN | ||
| 1021 | tmp |= BUF_SWAP_32BIT; | ||
| 1022 | #endif | ||
| 1023 | WREG32(CP_RB0_CNTL, tmp); | ||
| 1024 | |||
| 1025 | /* Initialize the ring buffer's read and write pointers */ | ||
| 1026 | WREG32(CP_RB0_CNTL, tmp | RB_RPTR_WR_ENA); | ||
| 1027 | ring->wptr = 0; | ||
| 1028 | WREG32(CP_RB0_WPTR, ring->wptr); | ||
| 1029 | |||
| 1030 | /* set the wb address wether it's enabled or not */ | 1049 | /* set the wb address wether it's enabled or not */ |
| 1031 | WREG32(CP_RB0_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC); | ||
| 1032 | WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF); | ||
| 1033 | WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); | 1050 | WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); |
| 1051 | WREG32(SCRATCH_UMSK, 0xff); | ||
| 1034 | 1052 | ||
| 1035 | if (rdev->wb.enabled) | 1053 | for (i = 0; i < 3; ++i) { |
| 1036 | WREG32(SCRATCH_UMSK, 0xff); | 1054 | uint32_t rb_cntl; |
| 1037 | else { | 1055 | uint64_t addr; |
| 1038 | tmp |= RB_NO_UPDATE; | ||
| 1039 | WREG32(SCRATCH_UMSK, 0); | ||
| 1040 | } | ||
| 1041 | 1056 | ||
| 1042 | mdelay(1); | 1057 | /* Set ring buffer size */ |
| 1043 | WREG32(CP_RB0_CNTL, tmp); | 1058 | ring = &rdev->ring[ridx[i]]; |
| 1044 | 1059 | rb_cntl = drm_order(ring->ring_size / 8); | |
| 1045 | WREG32(CP_RB0_BASE, ring->gpu_addr >> 8); | 1060 | rb_cntl |= drm_order(RADEON_GPU_PAGE_SIZE/8) << 8; |
| 1046 | |||
| 1047 | ring->rptr = RREG32(CP_RB0_RPTR); | ||
| 1048 | |||
| 1049 | /* ring1 - compute only */ | ||
| 1050 | /* Set ring buffer size */ | ||
| 1051 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; | ||
| 1052 | rb_bufsz = drm_order(ring->ring_size / 8); | ||
| 1053 | tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; | ||
| 1054 | #ifdef __BIG_ENDIAN | 1061 | #ifdef __BIG_ENDIAN |
| 1055 | tmp |= BUF_SWAP_32BIT; | 1062 | rb_cntl |= BUF_SWAP_32BIT; |
| 1056 | #endif | 1063 | #endif |
| 1057 | WREG32(CP_RB1_CNTL, tmp); | 1064 | WREG32(cp_rb_cntl[i], rb_cntl); |
| 1058 | |||
| 1059 | /* Initialize the ring buffer's read and write pointers */ | ||
| 1060 | WREG32(CP_RB1_CNTL, tmp | RB_RPTR_WR_ENA); | ||
| 1061 | ring->wptr = 0; | ||
| 1062 | WREG32(CP_RB1_WPTR, ring->wptr); | ||
| 1063 | |||
| 1064 | /* set the wb address wether it's enabled or not */ | ||
| 1065 | WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC); | ||
| 1066 | WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFF); | ||
| 1067 | |||
| 1068 | mdelay(1); | ||
| 1069 | WREG32(CP_RB1_CNTL, tmp); | ||
| 1070 | 1065 | ||
| 1071 | WREG32(CP_RB1_BASE, ring->gpu_addr >> 8); | 1066 | /* set the wb address wether it's enabled or not */ |
| 1072 | 1067 | addr = rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET; | |
| 1073 | ring->rptr = RREG32(CP_RB1_RPTR); | 1068 | WREG32(cp_rb_rptr_addr[i], addr & 0xFFFFFFFC); |
| 1074 | 1069 | WREG32(cp_rb_rptr_addr_hi[i], upper_32_bits(addr) & 0xFF); | |
| 1075 | /* ring2 - compute only */ | 1070 | } |
| 1076 | /* Set ring buffer size */ | ||
| 1077 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; | ||
| 1078 | rb_bufsz = drm_order(ring->ring_size / 8); | ||
| 1079 | tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; | ||
| 1080 | #ifdef __BIG_ENDIAN | ||
| 1081 | tmp |= BUF_SWAP_32BIT; | ||
| 1082 | #endif | ||
| 1083 | WREG32(CP_RB2_CNTL, tmp); | ||
| 1084 | |||
| 1085 | /* Initialize the ring buffer's read and write pointers */ | ||
| 1086 | WREG32(CP_RB2_CNTL, tmp | RB_RPTR_WR_ENA); | ||
| 1087 | ring->wptr = 0; | ||
| 1088 | WREG32(CP_RB2_WPTR, ring->wptr); | ||
| 1089 | 1071 | ||
| 1090 | /* set the wb address wether it's enabled or not */ | 1072 | /* set the rb base addr, this causes an internal reset of ALL rings */ |
| 1091 | WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC); | 1073 | for (i = 0; i < 3; ++i) { |
| 1092 | WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFF); | 1074 | ring = &rdev->ring[ridx[i]]; |
| 1075 | WREG32(cp_rb_base[i], ring->gpu_addr >> 8); | ||
| 1076 | } | ||
| 1093 | 1077 | ||
| 1094 | mdelay(1); | 1078 | for (i = 0; i < 3; ++i) { |
| 1095 | WREG32(CP_RB2_CNTL, tmp); | 1079 | /* Initialize the ring buffer's read and write pointers */ |
| 1080 | ring = &rdev->ring[ridx[i]]; | ||
| 1081 | WREG32_P(cp_rb_cntl[i], RB_RPTR_WR_ENA, ~RB_RPTR_WR_ENA); | ||
| 1096 | 1082 | ||
| 1097 | WREG32(CP_RB2_BASE, ring->gpu_addr >> 8); | 1083 | ring->rptr = ring->wptr = 0; |
| 1084 | WREG32(ring->rptr_reg, ring->rptr); | ||
| 1085 | WREG32(ring->wptr_reg, ring->wptr); | ||
| 1098 | 1086 | ||
| 1099 | ring->rptr = RREG32(CP_RB2_RPTR); | 1087 | mdelay(1); |
| 1088 | WREG32_P(cp_rb_cntl[i], 0, ~RB_RPTR_WR_ENA); | ||
| 1089 | } | ||
| 1100 | 1090 | ||
| 1101 | /* start the rings */ | 1091 | /* start the rings */ |
| 1102 | cayman_cp_start(rdev); | 1092 | cayman_cp_start(rdev); |
| @@ -1132,6 +1122,14 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev) | |||
| 1132 | RREG32(GRBM_STATUS_SE1)); | 1122 | RREG32(GRBM_STATUS_SE1)); |
| 1133 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", | 1123 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", |
| 1134 | RREG32(SRBM_STATUS)); | 1124 | RREG32(SRBM_STATUS)); |
| 1125 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", | ||
| 1126 | RREG32(CP_STALLED_STAT1)); | ||
| 1127 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", | ||
| 1128 | RREG32(CP_STALLED_STAT2)); | ||
| 1129 | dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", | ||
| 1130 | RREG32(CP_BUSY_STAT)); | ||
| 1131 | dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", | ||
| 1132 | RREG32(CP_STAT)); | ||
| 1135 | dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_ADDR 0x%08X\n", | 1133 | dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_ADDR 0x%08X\n", |
| 1136 | RREG32(0x14F8)); | 1134 | RREG32(0x14F8)); |
| 1137 | dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_STATUS 0x%08X\n", | 1135 | dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_STATUS 0x%08X\n", |
| @@ -1180,6 +1178,14 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev) | |||
| 1180 | RREG32(GRBM_STATUS_SE1)); | 1178 | RREG32(GRBM_STATUS_SE1)); |
| 1181 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", | 1179 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", |
| 1182 | RREG32(SRBM_STATUS)); | 1180 | RREG32(SRBM_STATUS)); |
| 1181 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", | ||
| 1182 | RREG32(CP_STALLED_STAT1)); | ||
| 1183 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", | ||
| 1184 | RREG32(CP_STALLED_STAT2)); | ||
| 1185 | dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", | ||
| 1186 | RREG32(CP_BUSY_STAT)); | ||
| 1187 | dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", | ||
| 1188 | RREG32(CP_STAT)); | ||
| 1183 | evergreen_mc_resume(rdev, &save); | 1189 | evergreen_mc_resume(rdev, &save); |
| 1184 | return 0; | 1190 | return 0; |
| 1185 | } | 1191 | } |
| @@ -1291,17 +1297,17 @@ static int cayman_startup(struct radeon_device *rdev) | |||
| 1291 | if (r) | 1297 | if (r) |
| 1292 | return r; | 1298 | return r; |
| 1293 | 1299 | ||
| 1294 | r = radeon_ib_pool_start(rdev); | 1300 | r = radeon_ib_pool_init(rdev); |
| 1295 | if (r) | 1301 | if (r) { |
| 1296 | return r; | 1302 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 1297 | |||
| 1298 | r = radeon_ib_ring_tests(rdev); | ||
| 1299 | if (r) | ||
| 1300 | return r; | 1303 | return r; |
| 1304 | } | ||
| 1301 | 1305 | ||
| 1302 | r = radeon_vm_manager_start(rdev); | 1306 | r = radeon_vm_manager_init(rdev); |
| 1303 | if (r) | 1307 | if (r) { |
| 1308 | dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); | ||
| 1304 | return r; | 1309 | return r; |
| 1310 | } | ||
| 1305 | 1311 | ||
| 1306 | r = r600_audio_init(rdev); | 1312 | r = r600_audio_init(rdev); |
| 1307 | if (r) | 1313 | if (r) |
| @@ -1334,10 +1340,6 @@ int cayman_resume(struct radeon_device *rdev) | |||
| 1334 | int cayman_suspend(struct radeon_device *rdev) | 1340 | int cayman_suspend(struct radeon_device *rdev) |
| 1335 | { | 1341 | { |
| 1336 | r600_audio_fini(rdev); | 1342 | r600_audio_fini(rdev); |
| 1337 | /* FIXME: we should wait for ring to be empty */ | ||
| 1338 | radeon_ib_pool_suspend(rdev); | ||
| 1339 | radeon_vm_manager_suspend(rdev); | ||
| 1340 | r600_blit_suspend(rdev); | ||
| 1341 | cayman_cp_enable(rdev, false); | 1343 | cayman_cp_enable(rdev, false); |
| 1342 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; | 1344 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; |
| 1343 | evergreen_irq_suspend(rdev); | 1345 | evergreen_irq_suspend(rdev); |
| @@ -1413,17 +1415,7 @@ int cayman_init(struct radeon_device *rdev) | |||
| 1413 | if (r) | 1415 | if (r) |
| 1414 | return r; | 1416 | return r; |
| 1415 | 1417 | ||
| 1416 | r = radeon_ib_pool_init(rdev); | ||
| 1417 | rdev->accel_working = true; | 1418 | rdev->accel_working = true; |
| 1418 | if (r) { | ||
| 1419 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 1420 | rdev->accel_working = false; | ||
| 1421 | } | ||
| 1422 | r = radeon_vm_manager_init(rdev); | ||
| 1423 | if (r) { | ||
| 1424 | dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | r = cayman_startup(rdev); | 1419 | r = cayman_startup(rdev); |
| 1428 | if (r) { | 1420 | if (r) { |
| 1429 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | 1421 | dev_err(rdev->dev, "disabling GPU acceleration\n"); |
| @@ -1432,7 +1424,7 @@ int cayman_init(struct radeon_device *rdev) | |||
| 1432 | if (rdev->flags & RADEON_IS_IGP) | 1424 | if (rdev->flags & RADEON_IS_IGP) |
| 1433 | si_rlc_fini(rdev); | 1425 | si_rlc_fini(rdev); |
| 1434 | radeon_wb_fini(rdev); | 1426 | radeon_wb_fini(rdev); |
| 1435 | r100_ib_fini(rdev); | 1427 | radeon_ib_pool_fini(rdev); |
| 1436 | radeon_vm_manager_fini(rdev); | 1428 | radeon_vm_manager_fini(rdev); |
| 1437 | radeon_irq_kms_fini(rdev); | 1429 | radeon_irq_kms_fini(rdev); |
| 1438 | cayman_pcie_gart_fini(rdev); | 1430 | cayman_pcie_gart_fini(rdev); |
| @@ -1463,7 +1455,7 @@ void cayman_fini(struct radeon_device *rdev) | |||
| 1463 | si_rlc_fini(rdev); | 1455 | si_rlc_fini(rdev); |
| 1464 | radeon_wb_fini(rdev); | 1456 | radeon_wb_fini(rdev); |
| 1465 | radeon_vm_manager_fini(rdev); | 1457 | radeon_vm_manager_fini(rdev); |
| 1466 | r100_ib_fini(rdev); | 1458 | radeon_ib_pool_fini(rdev); |
| 1467 | radeon_irq_kms_fini(rdev); | 1459 | radeon_irq_kms_fini(rdev); |
| 1468 | cayman_pcie_gart_fini(rdev); | 1460 | cayman_pcie_gart_fini(rdev); |
| 1469 | r600_vram_scratch_fini(rdev); | 1461 | r600_vram_scratch_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index a0b98066e207..870db340d377 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h | |||
| @@ -236,6 +236,10 @@ | |||
| 236 | #define CP_SEM_WAIT_TIMER 0x85BC | 236 | #define CP_SEM_WAIT_TIMER 0x85BC |
| 237 | #define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8 | 237 | #define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8 |
| 238 | #define CP_COHER_CNTL2 0x85E8 | 238 | #define CP_COHER_CNTL2 0x85E8 |
| 239 | #define CP_STALLED_STAT1 0x8674 | ||
| 240 | #define CP_STALLED_STAT2 0x8678 | ||
| 241 | #define CP_BUSY_STAT 0x867C | ||
| 242 | #define CP_STAT 0x8680 | ||
| 239 | #define CP_ME_CNTL 0x86D8 | 243 | #define CP_ME_CNTL 0x86D8 |
| 240 | #define CP_ME_HALT (1 << 28) | 244 | #define CP_ME_HALT (1 << 28) |
| 241 | #define CP_PFP_HALT (1 << 26) | 245 | #define CP_PFP_HALT (1 << 26) |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index fb44e7e49083..8acb34fd3fd5 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
| @@ -65,6 +65,19 @@ MODULE_FIRMWARE(FIRMWARE_R520); | |||
| 65 | 65 | ||
| 66 | #include "r100_track.h" | 66 | #include "r100_track.h" |
| 67 | 67 | ||
| 68 | /* This files gather functions specifics to: | ||
| 69 | * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 | ||
| 70 | * and others in some cases. | ||
| 71 | */ | ||
| 72 | |||
| 73 | /** | ||
| 74 | * r100_wait_for_vblank - vblank wait asic callback. | ||
| 75 | * | ||
| 76 | * @rdev: radeon_device pointer | ||
| 77 | * @crtc: crtc to wait for vblank on | ||
| 78 | * | ||
| 79 | * Wait for vblank on the requested crtc (r1xx-r4xx). | ||
| 80 | */ | ||
| 68 | void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) | 81 | void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) |
| 69 | { | 82 | { |
| 70 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; | 83 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; |
| @@ -99,128 +112,49 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) | |||
| 99 | } | 112 | } |
| 100 | } | 113 | } |
| 101 | 114 | ||
| 102 | /* This files gather functions specifics to: | 115 | /** |
| 103 | * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 | 116 | * r100_pre_page_flip - pre-pageflip callback. |
| 117 | * | ||
| 118 | * @rdev: radeon_device pointer | ||
| 119 | * @crtc: crtc to prepare for pageflip on | ||
| 120 | * | ||
| 121 | * Pre-pageflip callback (r1xx-r4xx). | ||
| 122 | * Enables the pageflip irq (vblank irq). | ||
| 104 | */ | 123 | */ |
| 105 | |||
| 106 | int r100_reloc_pitch_offset(struct radeon_cs_parser *p, | ||
| 107 | struct radeon_cs_packet *pkt, | ||
| 108 | unsigned idx, | ||
| 109 | unsigned reg) | ||
| 110 | { | ||
| 111 | int r; | ||
| 112 | u32 tile_flags = 0; | ||
| 113 | u32 tmp; | ||
| 114 | struct radeon_cs_reloc *reloc; | ||
| 115 | u32 value; | ||
| 116 | |||
| 117 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 118 | if (r) { | ||
| 119 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
| 120 | idx, reg); | ||
| 121 | r100_cs_dump_packet(p, pkt); | ||
| 122 | return r; | ||
| 123 | } | ||
| 124 | |||
| 125 | value = radeon_get_ib_value(p, idx); | ||
| 126 | tmp = value & 0x003fffff; | ||
| 127 | tmp += (((u32)reloc->lobj.gpu_offset) >> 10); | ||
| 128 | |||
| 129 | if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { | ||
| 130 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) | ||
| 131 | tile_flags |= RADEON_DST_TILE_MACRO; | ||
| 132 | if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { | ||
| 133 | if (reg == RADEON_SRC_PITCH_OFFSET) { | ||
| 134 | DRM_ERROR("Cannot src blit from microtiled surface\n"); | ||
| 135 | r100_cs_dump_packet(p, pkt); | ||
| 136 | return -EINVAL; | ||
| 137 | } | ||
| 138 | tile_flags |= RADEON_DST_TILE_MICRO; | ||
| 139 | } | ||
| 140 | |||
| 141 | tmp |= tile_flags; | ||
| 142 | p->ib.ptr[idx] = (value & 0x3fc00000) | tmp; | ||
| 143 | } else | ||
| 144 | p->ib.ptr[idx] = (value & 0xffc00000) | tmp; | ||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | int r100_packet3_load_vbpntr(struct radeon_cs_parser *p, | ||
| 149 | struct radeon_cs_packet *pkt, | ||
| 150 | int idx) | ||
| 151 | { | ||
| 152 | unsigned c, i; | ||
| 153 | struct radeon_cs_reloc *reloc; | ||
| 154 | struct r100_cs_track *track; | ||
| 155 | int r = 0; | ||
| 156 | volatile uint32_t *ib; | ||
| 157 | u32 idx_value; | ||
| 158 | |||
| 159 | ib = p->ib.ptr; | ||
| 160 | track = (struct r100_cs_track *)p->track; | ||
| 161 | c = radeon_get_ib_value(p, idx++) & 0x1F; | ||
| 162 | if (c > 16) { | ||
| 163 | DRM_ERROR("Only 16 vertex buffers are allowed %d\n", | ||
| 164 | pkt->opcode); | ||
| 165 | r100_cs_dump_packet(p, pkt); | ||
| 166 | return -EINVAL; | ||
| 167 | } | ||
| 168 | track->num_arrays = c; | ||
| 169 | for (i = 0; i < (c - 1); i+=2, idx+=3) { | ||
| 170 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 171 | if (r) { | ||
| 172 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 173 | pkt->opcode); | ||
| 174 | r100_cs_dump_packet(p, pkt); | ||
| 175 | return r; | ||
| 176 | } | ||
| 177 | idx_value = radeon_get_ib_value(p, idx); | ||
| 178 | ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); | ||
| 179 | |||
| 180 | track->arrays[i + 0].esize = idx_value >> 8; | ||
| 181 | track->arrays[i + 0].robj = reloc->robj; | ||
| 182 | track->arrays[i + 0].esize &= 0x7F; | ||
| 183 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 184 | if (r) { | ||
| 185 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 186 | pkt->opcode); | ||
| 187 | r100_cs_dump_packet(p, pkt); | ||
| 188 | return r; | ||
| 189 | } | ||
| 190 | ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset); | ||
| 191 | track->arrays[i + 1].robj = reloc->robj; | ||
| 192 | track->arrays[i + 1].esize = idx_value >> 24; | ||
| 193 | track->arrays[i + 1].esize &= 0x7F; | ||
| 194 | } | ||
| 195 | if (c & 1) { | ||
| 196 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 197 | if (r) { | ||
| 198 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 199 | pkt->opcode); | ||
| 200 | r100_cs_dump_packet(p, pkt); | ||
| 201 | return r; | ||
| 202 | } | ||
| 203 | idx_value = radeon_get_ib_value(p, idx); | ||
| 204 | ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); | ||
| 205 | track->arrays[i + 0].robj = reloc->robj; | ||
| 206 | track->arrays[i + 0].esize = idx_value >> 8; | ||
| 207 | track->arrays[i + 0].esize &= 0x7F; | ||
| 208 | } | ||
| 209 | return r; | ||
| 210 | } | ||
| 211 | |||
| 212 | void r100_pre_page_flip(struct radeon_device *rdev, int crtc) | 124 | void r100_pre_page_flip(struct radeon_device *rdev, int crtc) |
| 213 | { | 125 | { |
| 214 | /* enable the pflip int */ | 126 | /* enable the pflip int */ |
| 215 | radeon_irq_kms_pflip_irq_get(rdev, crtc); | 127 | radeon_irq_kms_pflip_irq_get(rdev, crtc); |
| 216 | } | 128 | } |
| 217 | 129 | ||
| 130 | /** | ||
| 131 | * r100_post_page_flip - pos-pageflip callback. | ||
| 132 | * | ||
| 133 | * @rdev: radeon_device pointer | ||
| 134 | * @crtc: crtc to cleanup pageflip on | ||
| 135 | * | ||
| 136 | * Post-pageflip callback (r1xx-r4xx). | ||
| 137 | * Disables the pageflip irq (vblank irq). | ||
| 138 | */ | ||
| 218 | void r100_post_page_flip(struct radeon_device *rdev, int crtc) | 139 | void r100_post_page_flip(struct radeon_device *rdev, int crtc) |
| 219 | { | 140 | { |
| 220 | /* disable the pflip int */ | 141 | /* disable the pflip int */ |
| 221 | radeon_irq_kms_pflip_irq_put(rdev, crtc); | 142 | radeon_irq_kms_pflip_irq_put(rdev, crtc); |
| 222 | } | 143 | } |
| 223 | 144 | ||
| 145 | /** | ||
| 146 | * r100_page_flip - pageflip callback. | ||
| 147 | * | ||
| 148 | * @rdev: radeon_device pointer | ||
| 149 | * @crtc_id: crtc to cleanup pageflip on | ||
| 150 | * @crtc_base: new address of the crtc (GPU MC address) | ||
| 151 | * | ||
| 152 | * Does the actual pageflip (r1xx-r4xx). | ||
| 153 | * During vblank we take the crtc lock and wait for the update_pending | ||
| 154 | * bit to go high, when it does, we release the lock, and allow the | ||
| 155 | * double buffered update to take place. | ||
| 156 | * Returns the current update pending status. | ||
| 157 | */ | ||
| 224 | u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) | 158 | u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) |
| 225 | { | 159 | { |
| 226 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; | 160 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; |
| @@ -247,6 +181,15 @@ u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) | |||
| 247 | return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET; | 181 | return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET; |
| 248 | } | 182 | } |
| 249 | 183 | ||
| 184 | /** | ||
| 185 | * r100_pm_get_dynpm_state - look up dynpm power state callback. | ||
| 186 | * | ||
| 187 | * @rdev: radeon_device pointer | ||
| 188 | * | ||
| 189 | * Look up the optimal power state based on the | ||
| 190 | * current state of the GPU (r1xx-r5xx). | ||
| 191 | * Used for dynpm only. | ||
| 192 | */ | ||
| 250 | void r100_pm_get_dynpm_state(struct radeon_device *rdev) | 193 | void r100_pm_get_dynpm_state(struct radeon_device *rdev) |
| 251 | { | 194 | { |
| 252 | int i; | 195 | int i; |
| @@ -329,6 +272,15 @@ void r100_pm_get_dynpm_state(struct radeon_device *rdev) | |||
| 329 | pcie_lanes); | 272 | pcie_lanes); |
| 330 | } | 273 | } |
| 331 | 274 | ||
| 275 | /** | ||
| 276 | * r100_pm_init_profile - Initialize power profiles callback. | ||
| 277 | * | ||
| 278 | * @rdev: radeon_device pointer | ||
| 279 | * | ||
| 280 | * Initialize the power states used in profile mode | ||
| 281 | * (r1xx-r3xx). | ||
| 282 | * Used for profile mode only. | ||
| 283 | */ | ||
| 332 | void r100_pm_init_profile(struct radeon_device *rdev) | 284 | void r100_pm_init_profile(struct radeon_device *rdev) |
| 333 | { | 285 | { |
| 334 | /* default */ | 286 | /* default */ |
| @@ -368,6 +320,14 @@ void r100_pm_init_profile(struct radeon_device *rdev) | |||
| 368 | rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; | 320 | rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; |
| 369 | } | 321 | } |
| 370 | 322 | ||
| 323 | /** | ||
| 324 | * r100_pm_misc - set additional pm hw parameters callback. | ||
| 325 | * | ||
| 326 | * @rdev: radeon_device pointer | ||
| 327 | * | ||
| 328 | * Set non-clock parameters associated with a power state | ||
| 329 | * (voltage, pcie lanes, etc.) (r1xx-r4xx). | ||
| 330 | */ | ||
| 371 | void r100_pm_misc(struct radeon_device *rdev) | 331 | void r100_pm_misc(struct radeon_device *rdev) |
| 372 | { | 332 | { |
| 373 | int requested_index = rdev->pm.requested_power_state_index; | 333 | int requested_index = rdev->pm.requested_power_state_index; |
| @@ -459,6 +419,13 @@ void r100_pm_misc(struct radeon_device *rdev) | |||
| 459 | } | 419 | } |
| 460 | } | 420 | } |
| 461 | 421 | ||
| 422 | /** | ||
| 423 | * r100_pm_prepare - pre-power state change callback. | ||
| 424 | * | ||
| 425 | * @rdev: radeon_device pointer | ||
| 426 | * | ||
| 427 | * Prepare for a power state change (r1xx-r4xx). | ||
| 428 | */ | ||
| 462 | void r100_pm_prepare(struct radeon_device *rdev) | 429 | void r100_pm_prepare(struct radeon_device *rdev) |
| 463 | { | 430 | { |
| 464 | struct drm_device *ddev = rdev->ddev; | 431 | struct drm_device *ddev = rdev->ddev; |
| @@ -483,6 +450,13 @@ void r100_pm_prepare(struct radeon_device *rdev) | |||
| 483 | } | 450 | } |
| 484 | } | 451 | } |
| 485 | 452 | ||
| 453 | /** | ||
| 454 | * r100_pm_finish - post-power state change callback. | ||
| 455 | * | ||
| 456 | * @rdev: radeon_device pointer | ||
| 457 | * | ||
| 458 | * Clean up after a power state change (r1xx-r4xx). | ||
| 459 | */ | ||
| 486 | void r100_pm_finish(struct radeon_device *rdev) | 460 | void r100_pm_finish(struct radeon_device *rdev) |
| 487 | { | 461 | { |
| 488 | struct drm_device *ddev = rdev->ddev; | 462 | struct drm_device *ddev = rdev->ddev; |
| @@ -507,6 +481,14 @@ void r100_pm_finish(struct radeon_device *rdev) | |||
| 507 | } | 481 | } |
| 508 | } | 482 | } |
| 509 | 483 | ||
| 484 | /** | ||
| 485 | * r100_gui_idle - gui idle callback. | ||
| 486 | * | ||
| 487 | * @rdev: radeon_device pointer | ||
| 488 | * | ||
| 489 | * Check of the GUI (2D/3D engines) are idle (r1xx-r5xx). | ||
| 490 | * Returns true if idle, false if not. | ||
| 491 | */ | ||
| 510 | bool r100_gui_idle(struct radeon_device *rdev) | 492 | bool r100_gui_idle(struct radeon_device *rdev) |
| 511 | { | 493 | { |
| 512 | if (RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE) | 494 | if (RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE) |
| @@ -516,6 +498,15 @@ bool r100_gui_idle(struct radeon_device *rdev) | |||
| 516 | } | 498 | } |
| 517 | 499 | ||
| 518 | /* hpd for digital panel detect/disconnect */ | 500 | /* hpd for digital panel detect/disconnect */ |
| 501 | /** | ||
| 502 | * r100_hpd_sense - hpd sense callback. | ||
| 503 | * | ||
| 504 | * @rdev: radeon_device pointer | ||
| 505 | * @hpd: hpd (hotplug detect) pin | ||
| 506 | * | ||
| 507 | * Checks if a digital monitor is connected (r1xx-r4xx). | ||
| 508 | * Returns true if connected, false if not connected. | ||
| 509 | */ | ||
| 519 | bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) | 510 | bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) |
| 520 | { | 511 | { |
| 521 | bool connected = false; | 512 | bool connected = false; |
| @@ -535,6 +526,14 @@ bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) | |||
| 535 | return connected; | 526 | return connected; |
| 536 | } | 527 | } |
| 537 | 528 | ||
| 529 | /** | ||
| 530 | * r100_hpd_set_polarity - hpd set polarity callback. | ||
| 531 | * | ||
| 532 | * @rdev: radeon_device pointer | ||
| 533 | * @hpd: hpd (hotplug detect) pin | ||
| 534 | * | ||
| 535 | * Set the polarity of the hpd pin (r1xx-r4xx). | ||
| 536 | */ | ||
| 538 | void r100_hpd_set_polarity(struct radeon_device *rdev, | 537 | void r100_hpd_set_polarity(struct radeon_device *rdev, |
| 539 | enum radeon_hpd_id hpd) | 538 | enum radeon_hpd_id hpd) |
| 540 | { | 539 | { |
| @@ -563,47 +562,47 @@ void r100_hpd_set_polarity(struct radeon_device *rdev, | |||
| 563 | } | 562 | } |
| 564 | } | 563 | } |
| 565 | 564 | ||
| 565 | /** | ||
| 566 | * r100_hpd_init - hpd setup callback. | ||
| 567 | * | ||
| 568 | * @rdev: radeon_device pointer | ||
| 569 | * | ||
| 570 | * Setup the hpd pins used by the card (r1xx-r4xx). | ||
| 571 | * Set the polarity, and enable the hpd interrupts. | ||
| 572 | */ | ||
| 566 | void r100_hpd_init(struct radeon_device *rdev) | 573 | void r100_hpd_init(struct radeon_device *rdev) |
| 567 | { | 574 | { |
| 568 | struct drm_device *dev = rdev->ddev; | 575 | struct drm_device *dev = rdev->ddev; |
| 569 | struct drm_connector *connector; | 576 | struct drm_connector *connector; |
| 577 | unsigned enable = 0; | ||
| 570 | 578 | ||
| 571 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 579 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 572 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 580 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 573 | switch (radeon_connector->hpd.hpd) { | 581 | enable |= 1 << radeon_connector->hpd.hpd; |
| 574 | case RADEON_HPD_1: | ||
| 575 | rdev->irq.hpd[0] = true; | ||
| 576 | break; | ||
| 577 | case RADEON_HPD_2: | ||
| 578 | rdev->irq.hpd[1] = true; | ||
| 579 | break; | ||
| 580 | default: | ||
| 581 | break; | ||
| 582 | } | ||
| 583 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); | 582 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); |
| 584 | } | 583 | } |
| 585 | if (rdev->irq.installed) | 584 | radeon_irq_kms_enable_hpd(rdev, enable); |
| 586 | r100_irq_set(rdev); | ||
| 587 | } | 585 | } |
| 588 | 586 | ||
| 587 | /** | ||
| 588 | * r100_hpd_fini - hpd tear down callback. | ||
| 589 | * | ||
| 590 | * @rdev: radeon_device pointer | ||
| 591 | * | ||
| 592 | * Tear down the hpd pins used by the card (r1xx-r4xx). | ||
| 593 | * Disable the hpd interrupts. | ||
| 594 | */ | ||
| 589 | void r100_hpd_fini(struct radeon_device *rdev) | 595 | void r100_hpd_fini(struct radeon_device *rdev) |
| 590 | { | 596 | { |
| 591 | struct drm_device *dev = rdev->ddev; | 597 | struct drm_device *dev = rdev->ddev; |
| 592 | struct drm_connector *connector; | 598 | struct drm_connector *connector; |
| 599 | unsigned disable = 0; | ||
| 593 | 600 | ||
| 594 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 601 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 595 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 602 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 596 | switch (radeon_connector->hpd.hpd) { | 603 | disable |= 1 << radeon_connector->hpd.hpd; |
| 597 | case RADEON_HPD_1: | ||
| 598 | rdev->irq.hpd[0] = false; | ||
| 599 | break; | ||
| 600 | case RADEON_HPD_2: | ||
| 601 | rdev->irq.hpd[1] = false; | ||
| 602 | break; | ||
| 603 | default: | ||
| 604 | break; | ||
| 605 | } | ||
| 606 | } | 604 | } |
| 605 | radeon_irq_kms_disable_hpd(rdev, disable); | ||
| 607 | } | 606 | } |
| 608 | 607 | ||
| 609 | /* | 608 | /* |
| @@ -635,15 +634,6 @@ int r100_pci_gart_init(struct radeon_device *rdev) | |||
| 635 | return radeon_gart_table_ram_alloc(rdev); | 634 | return radeon_gart_table_ram_alloc(rdev); |
| 636 | } | 635 | } |
| 637 | 636 | ||
| 638 | /* required on r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ | ||
| 639 | void r100_enable_bm(struct radeon_device *rdev) | ||
| 640 | { | ||
| 641 | uint32_t tmp; | ||
| 642 | /* Enable bus mastering */ | ||
| 643 | tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; | ||
| 644 | WREG32(RADEON_BUS_CNTL, tmp); | ||
| 645 | } | ||
| 646 | |||
| 647 | int r100_pci_gart_enable(struct radeon_device *rdev) | 637 | int r100_pci_gart_enable(struct radeon_device *rdev) |
| 648 | { | 638 | { |
| 649 | uint32_t tmp; | 639 | uint32_t tmp; |
| @@ -705,18 +695,18 @@ int r100_irq_set(struct radeon_device *rdev) | |||
| 705 | WREG32(R_000040_GEN_INT_CNTL, 0); | 695 | WREG32(R_000040_GEN_INT_CNTL, 0); |
| 706 | return -EINVAL; | 696 | return -EINVAL; |
| 707 | } | 697 | } |
| 708 | if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { | 698 | if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { |
| 709 | tmp |= RADEON_SW_INT_ENABLE; | 699 | tmp |= RADEON_SW_INT_ENABLE; |
| 710 | } | 700 | } |
| 711 | if (rdev->irq.gui_idle) { | 701 | if (rdev->irq.gui_idle) { |
| 712 | tmp |= RADEON_GUI_IDLE_MASK; | 702 | tmp |= RADEON_GUI_IDLE_MASK; |
| 713 | } | 703 | } |
| 714 | if (rdev->irq.crtc_vblank_int[0] || | 704 | if (rdev->irq.crtc_vblank_int[0] || |
| 715 | rdev->irq.pflip[0]) { | 705 | atomic_read(&rdev->irq.pflip[0])) { |
| 716 | tmp |= RADEON_CRTC_VBLANK_MASK; | 706 | tmp |= RADEON_CRTC_VBLANK_MASK; |
| 717 | } | 707 | } |
| 718 | if (rdev->irq.crtc_vblank_int[1] || | 708 | if (rdev->irq.crtc_vblank_int[1] || |
| 719 | rdev->irq.pflip[1]) { | 709 | atomic_read(&rdev->irq.pflip[1])) { |
| 720 | tmp |= RADEON_CRTC2_VBLANK_MASK; | 710 | tmp |= RADEON_CRTC2_VBLANK_MASK; |
| 721 | } | 711 | } |
| 722 | if (rdev->irq.hpd[0]) { | 712 | if (rdev->irq.hpd[0]) { |
| @@ -782,7 +772,6 @@ int r100_irq_process(struct radeon_device *rdev) | |||
| 782 | /* gui idle interrupt */ | 772 | /* gui idle interrupt */ |
| 783 | if (status & RADEON_GUI_IDLE_STAT) { | 773 | if (status & RADEON_GUI_IDLE_STAT) { |
| 784 | rdev->irq.gui_idle_acked = true; | 774 | rdev->irq.gui_idle_acked = true; |
| 785 | rdev->pm.gui_idle = true; | ||
| 786 | wake_up(&rdev->irq.idle_queue); | 775 | wake_up(&rdev->irq.idle_queue); |
| 787 | } | 776 | } |
| 788 | /* Vertical blank interrupts */ | 777 | /* Vertical blank interrupts */ |
| @@ -792,7 +781,7 @@ int r100_irq_process(struct radeon_device *rdev) | |||
| 792 | rdev->pm.vblank_sync = true; | 781 | rdev->pm.vblank_sync = true; |
| 793 | wake_up(&rdev->irq.vblank_queue); | 782 | wake_up(&rdev->irq.vblank_queue); |
| 794 | } | 783 | } |
| 795 | if (rdev->irq.pflip[0]) | 784 | if (atomic_read(&rdev->irq.pflip[0])) |
| 796 | radeon_crtc_handle_flip(rdev, 0); | 785 | radeon_crtc_handle_flip(rdev, 0); |
| 797 | } | 786 | } |
| 798 | if (status & RADEON_CRTC2_VBLANK_STAT) { | 787 | if (status & RADEON_CRTC2_VBLANK_STAT) { |
| @@ -801,7 +790,7 @@ int r100_irq_process(struct radeon_device *rdev) | |||
| 801 | rdev->pm.vblank_sync = true; | 790 | rdev->pm.vblank_sync = true; |
| 802 | wake_up(&rdev->irq.vblank_queue); | 791 | wake_up(&rdev->irq.vblank_queue); |
| 803 | } | 792 | } |
| 804 | if (rdev->irq.pflip[1]) | 793 | if (atomic_read(&rdev->irq.pflip[1])) |
| 805 | radeon_crtc_handle_flip(rdev, 1); | 794 | radeon_crtc_handle_flip(rdev, 1); |
| 806 | } | 795 | } |
| 807 | if (status & RADEON_FP_DETECT_STAT) { | 796 | if (status & RADEON_FP_DETECT_STAT) { |
| @@ -883,7 +872,7 @@ int r100_copy_blit(struct radeon_device *rdev, | |||
| 883 | uint64_t src_offset, | 872 | uint64_t src_offset, |
| 884 | uint64_t dst_offset, | 873 | uint64_t dst_offset, |
| 885 | unsigned num_gpu_pages, | 874 | unsigned num_gpu_pages, |
| 886 | struct radeon_fence *fence) | 875 | struct radeon_fence **fence) |
| 887 | { | 876 | { |
| 888 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | 877 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
| 889 | uint32_t cur_pages; | 878 | uint32_t cur_pages; |
| @@ -947,7 +936,7 @@ int r100_copy_blit(struct radeon_device *rdev, | |||
| 947 | RADEON_WAIT_HOST_IDLECLEAN | | 936 | RADEON_WAIT_HOST_IDLECLEAN | |
| 948 | RADEON_WAIT_DMA_GUI_IDLE); | 937 | RADEON_WAIT_DMA_GUI_IDLE); |
| 949 | if (fence) { | 938 | if (fence) { |
| 950 | r = radeon_fence_emit(rdev, fence); | 939 | r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX); |
| 951 | } | 940 | } |
| 952 | radeon_ring_unlock_commit(rdev, ring); | 941 | radeon_ring_unlock_commit(rdev, ring); |
| 953 | return r; | 942 | return r; |
| @@ -1192,6 +1181,14 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) | |||
| 1192 | } | 1181 | } |
| 1193 | ring->ready = true; | 1182 | ring->ready = true; |
| 1194 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); | 1183 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); |
| 1184 | |||
| 1185 | if (radeon_ring_supports_scratch_reg(rdev, ring)) { | ||
| 1186 | r = radeon_scratch_get(rdev, &ring->rptr_save_reg); | ||
| 1187 | if (r) { | ||
| 1188 | DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r); | ||
| 1189 | ring->rptr_save_reg = 0; | ||
| 1190 | } | ||
| 1191 | } | ||
| 1195 | return 0; | 1192 | return 0; |
| 1196 | } | 1193 | } |
| 1197 | 1194 | ||
| @@ -1202,6 +1199,7 @@ void r100_cp_fini(struct radeon_device *rdev) | |||
| 1202 | } | 1199 | } |
| 1203 | /* Disable ring */ | 1200 | /* Disable ring */ |
| 1204 | r100_cp_disable(rdev); | 1201 | r100_cp_disable(rdev); |
| 1202 | radeon_scratch_free(rdev, rdev->ring[RADEON_RING_TYPE_GFX_INDEX].rptr_save_reg); | ||
| 1205 | radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); | 1203 | radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); |
| 1206 | DRM_INFO("radeon: cp finalized\n"); | 1204 | DRM_INFO("radeon: cp finalized\n"); |
| 1207 | } | 1205 | } |
| @@ -1223,6 +1221,112 @@ void r100_cp_disable(struct radeon_device *rdev) | |||
| 1223 | /* | 1221 | /* |
| 1224 | * CS functions | 1222 | * CS functions |
| 1225 | */ | 1223 | */ |
| 1224 | int r100_reloc_pitch_offset(struct radeon_cs_parser *p, | ||
| 1225 | struct radeon_cs_packet *pkt, | ||
| 1226 | unsigned idx, | ||
| 1227 | unsigned reg) | ||
| 1228 | { | ||
| 1229 | int r; | ||
| 1230 | u32 tile_flags = 0; | ||
| 1231 | u32 tmp; | ||
| 1232 | struct radeon_cs_reloc *reloc; | ||
| 1233 | u32 value; | ||
| 1234 | |||
| 1235 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 1236 | if (r) { | ||
| 1237 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
| 1238 | idx, reg); | ||
| 1239 | r100_cs_dump_packet(p, pkt); | ||
| 1240 | return r; | ||
| 1241 | } | ||
| 1242 | |||
| 1243 | value = radeon_get_ib_value(p, idx); | ||
| 1244 | tmp = value & 0x003fffff; | ||
| 1245 | tmp += (((u32)reloc->lobj.gpu_offset) >> 10); | ||
| 1246 | |||
| 1247 | if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { | ||
| 1248 | if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) | ||
| 1249 | tile_flags |= RADEON_DST_TILE_MACRO; | ||
| 1250 | if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { | ||
| 1251 | if (reg == RADEON_SRC_PITCH_OFFSET) { | ||
| 1252 | DRM_ERROR("Cannot src blit from microtiled surface\n"); | ||
| 1253 | r100_cs_dump_packet(p, pkt); | ||
| 1254 | return -EINVAL; | ||
| 1255 | } | ||
| 1256 | tile_flags |= RADEON_DST_TILE_MICRO; | ||
| 1257 | } | ||
| 1258 | |||
| 1259 | tmp |= tile_flags; | ||
| 1260 | p->ib.ptr[idx] = (value & 0x3fc00000) | tmp; | ||
| 1261 | } else | ||
| 1262 | p->ib.ptr[idx] = (value & 0xffc00000) | tmp; | ||
| 1263 | return 0; | ||
| 1264 | } | ||
| 1265 | |||
| 1266 | int r100_packet3_load_vbpntr(struct radeon_cs_parser *p, | ||
| 1267 | struct radeon_cs_packet *pkt, | ||
| 1268 | int idx) | ||
| 1269 | { | ||
| 1270 | unsigned c, i; | ||
| 1271 | struct radeon_cs_reloc *reloc; | ||
| 1272 | struct r100_cs_track *track; | ||
| 1273 | int r = 0; | ||
| 1274 | volatile uint32_t *ib; | ||
| 1275 | u32 idx_value; | ||
| 1276 | |||
| 1277 | ib = p->ib.ptr; | ||
| 1278 | track = (struct r100_cs_track *)p->track; | ||
| 1279 | c = radeon_get_ib_value(p, idx++) & 0x1F; | ||
| 1280 | if (c > 16) { | ||
| 1281 | DRM_ERROR("Only 16 vertex buffers are allowed %d\n", | ||
| 1282 | pkt->opcode); | ||
| 1283 | r100_cs_dump_packet(p, pkt); | ||
| 1284 | return -EINVAL; | ||
| 1285 | } | ||
| 1286 | track->num_arrays = c; | ||
| 1287 | for (i = 0; i < (c - 1); i+=2, idx+=3) { | ||
| 1288 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 1289 | if (r) { | ||
| 1290 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 1291 | pkt->opcode); | ||
| 1292 | r100_cs_dump_packet(p, pkt); | ||
| 1293 | return r; | ||
| 1294 | } | ||
| 1295 | idx_value = radeon_get_ib_value(p, idx); | ||
| 1296 | ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); | ||
| 1297 | |||
| 1298 | track->arrays[i + 0].esize = idx_value >> 8; | ||
| 1299 | track->arrays[i + 0].robj = reloc->robj; | ||
| 1300 | track->arrays[i + 0].esize &= 0x7F; | ||
| 1301 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 1302 | if (r) { | ||
| 1303 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 1304 | pkt->opcode); | ||
| 1305 | r100_cs_dump_packet(p, pkt); | ||
| 1306 | return r; | ||
| 1307 | } | ||
| 1308 | ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset); | ||
| 1309 | track->arrays[i + 1].robj = reloc->robj; | ||
| 1310 | track->arrays[i + 1].esize = idx_value >> 24; | ||
| 1311 | track->arrays[i + 1].esize &= 0x7F; | ||
| 1312 | } | ||
| 1313 | if (c & 1) { | ||
| 1314 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 1315 | if (r) { | ||
| 1316 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 1317 | pkt->opcode); | ||
| 1318 | r100_cs_dump_packet(p, pkt); | ||
| 1319 | return r; | ||
| 1320 | } | ||
| 1321 | idx_value = radeon_get_ib_value(p, idx); | ||
| 1322 | ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); | ||
| 1323 | track->arrays[i + 0].robj = reloc->robj; | ||
| 1324 | track->arrays[i + 0].esize = idx_value >> 8; | ||
| 1325 | track->arrays[i + 0].esize &= 0x7F; | ||
| 1326 | } | ||
| 1327 | return r; | ||
| 1328 | } | ||
| 1329 | |||
| 1226 | int r100_cs_parse_packet0(struct radeon_cs_parser *p, | 1330 | int r100_cs_parse_packet0(struct radeon_cs_parser *p, |
| 1227 | struct radeon_cs_packet *pkt, | 1331 | struct radeon_cs_packet *pkt, |
| 1228 | const unsigned *auth, unsigned n, | 1332 | const unsigned *auth, unsigned n, |
| @@ -2048,6 +2152,379 @@ int r100_cs_parse(struct radeon_cs_parser *p) | |||
| 2048 | return 0; | 2152 | return 0; |
| 2049 | } | 2153 | } |
| 2050 | 2154 | ||
| 2155 | static void r100_cs_track_texture_print(struct r100_cs_track_texture *t) | ||
| 2156 | { | ||
| 2157 | DRM_ERROR("pitch %d\n", t->pitch); | ||
| 2158 | DRM_ERROR("use_pitch %d\n", t->use_pitch); | ||
| 2159 | DRM_ERROR("width %d\n", t->width); | ||
| 2160 | DRM_ERROR("width_11 %d\n", t->width_11); | ||
| 2161 | DRM_ERROR("height %d\n", t->height); | ||
| 2162 | DRM_ERROR("height_11 %d\n", t->height_11); | ||
| 2163 | DRM_ERROR("num levels %d\n", t->num_levels); | ||
| 2164 | DRM_ERROR("depth %d\n", t->txdepth); | ||
| 2165 | DRM_ERROR("bpp %d\n", t->cpp); | ||
| 2166 | DRM_ERROR("coordinate type %d\n", t->tex_coord_type); | ||
| 2167 | DRM_ERROR("width round to power of 2 %d\n", t->roundup_w); | ||
| 2168 | DRM_ERROR("height round to power of 2 %d\n", t->roundup_h); | ||
| 2169 | DRM_ERROR("compress format %d\n", t->compress_format); | ||
| 2170 | } | ||
| 2171 | |||
| 2172 | static int r100_track_compress_size(int compress_format, int w, int h) | ||
| 2173 | { | ||
| 2174 | int block_width, block_height, block_bytes; | ||
| 2175 | int wblocks, hblocks; | ||
| 2176 | int min_wblocks; | ||
| 2177 | int sz; | ||
| 2178 | |||
| 2179 | block_width = 4; | ||
| 2180 | block_height = 4; | ||
| 2181 | |||
| 2182 | switch (compress_format) { | ||
| 2183 | case R100_TRACK_COMP_DXT1: | ||
| 2184 | block_bytes = 8; | ||
| 2185 | min_wblocks = 4; | ||
| 2186 | break; | ||
| 2187 | default: | ||
| 2188 | case R100_TRACK_COMP_DXT35: | ||
| 2189 | block_bytes = 16; | ||
| 2190 | min_wblocks = 2; | ||
| 2191 | break; | ||
| 2192 | } | ||
| 2193 | |||
| 2194 | hblocks = (h + block_height - 1) / block_height; | ||
| 2195 | wblocks = (w + block_width - 1) / block_width; | ||
| 2196 | if (wblocks < min_wblocks) | ||
| 2197 | wblocks = min_wblocks; | ||
| 2198 | sz = wblocks * hblocks * block_bytes; | ||
| 2199 | return sz; | ||
| 2200 | } | ||
| 2201 | |||
| 2202 | static int r100_cs_track_cube(struct radeon_device *rdev, | ||
| 2203 | struct r100_cs_track *track, unsigned idx) | ||
| 2204 | { | ||
| 2205 | unsigned face, w, h; | ||
| 2206 | struct radeon_bo *cube_robj; | ||
| 2207 | unsigned long size; | ||
| 2208 | unsigned compress_format = track->textures[idx].compress_format; | ||
| 2209 | |||
| 2210 | for (face = 0; face < 5; face++) { | ||
| 2211 | cube_robj = track->textures[idx].cube_info[face].robj; | ||
| 2212 | w = track->textures[idx].cube_info[face].width; | ||
| 2213 | h = track->textures[idx].cube_info[face].height; | ||
| 2214 | |||
| 2215 | if (compress_format) { | ||
| 2216 | size = r100_track_compress_size(compress_format, w, h); | ||
| 2217 | } else | ||
| 2218 | size = w * h; | ||
| 2219 | size *= track->textures[idx].cpp; | ||
| 2220 | |||
| 2221 | size += track->textures[idx].cube_info[face].offset; | ||
| 2222 | |||
| 2223 | if (size > radeon_bo_size(cube_robj)) { | ||
| 2224 | DRM_ERROR("Cube texture offset greater than object size %lu %lu\n", | ||
| 2225 | size, radeon_bo_size(cube_robj)); | ||
| 2226 | r100_cs_track_texture_print(&track->textures[idx]); | ||
| 2227 | return -1; | ||
| 2228 | } | ||
| 2229 | } | ||
| 2230 | return 0; | ||
| 2231 | } | ||
| 2232 | |||
| 2233 | static int r100_cs_track_texture_check(struct radeon_device *rdev, | ||
| 2234 | struct r100_cs_track *track) | ||
| 2235 | { | ||
| 2236 | struct radeon_bo *robj; | ||
| 2237 | unsigned long size; | ||
| 2238 | unsigned u, i, w, h, d; | ||
| 2239 | int ret; | ||
| 2240 | |||
| 2241 | for (u = 0; u < track->num_texture; u++) { | ||
| 2242 | if (!track->textures[u].enabled) | ||
| 2243 | continue; | ||
| 2244 | if (track->textures[u].lookup_disable) | ||
| 2245 | continue; | ||
| 2246 | robj = track->textures[u].robj; | ||
| 2247 | if (robj == NULL) { | ||
| 2248 | DRM_ERROR("No texture bound to unit %u\n", u); | ||
| 2249 | return -EINVAL; | ||
| 2250 | } | ||
| 2251 | size = 0; | ||
| 2252 | for (i = 0; i <= track->textures[u].num_levels; i++) { | ||
| 2253 | if (track->textures[u].use_pitch) { | ||
| 2254 | if (rdev->family < CHIP_R300) | ||
| 2255 | w = (track->textures[u].pitch / track->textures[u].cpp) / (1 << i); | ||
| 2256 | else | ||
| 2257 | w = track->textures[u].pitch / (1 << i); | ||
| 2258 | } else { | ||
| 2259 | w = track->textures[u].width; | ||
| 2260 | if (rdev->family >= CHIP_RV515) | ||
| 2261 | w |= track->textures[u].width_11; | ||
| 2262 | w = w / (1 << i); | ||
| 2263 | if (track->textures[u].roundup_w) | ||
| 2264 | w = roundup_pow_of_two(w); | ||
| 2265 | } | ||
| 2266 | h = track->textures[u].height; | ||
| 2267 | if (rdev->family >= CHIP_RV515) | ||
| 2268 | h |= track->textures[u].height_11; | ||
| 2269 | h = h / (1 << i); | ||
| 2270 | if (track->textures[u].roundup_h) | ||
| 2271 | h = roundup_pow_of_two(h); | ||
| 2272 | if (track->textures[u].tex_coord_type == 1) { | ||
| 2273 | d = (1 << track->textures[u].txdepth) / (1 << i); | ||
| 2274 | if (!d) | ||
| 2275 | d = 1; | ||
| 2276 | } else { | ||
| 2277 | d = 1; | ||
| 2278 | } | ||
| 2279 | if (track->textures[u].compress_format) { | ||
| 2280 | |||
| 2281 | size += r100_track_compress_size(track->textures[u].compress_format, w, h) * d; | ||
| 2282 | /* compressed textures are block based */ | ||
| 2283 | } else | ||
| 2284 | size += w * h * d; | ||
| 2285 | } | ||
| 2286 | size *= track->textures[u].cpp; | ||
| 2287 | |||
| 2288 | switch (track->textures[u].tex_coord_type) { | ||
| 2289 | case 0: | ||
| 2290 | case 1: | ||
| 2291 | break; | ||
| 2292 | case 2: | ||
| 2293 | if (track->separate_cube) { | ||
| 2294 | ret = r100_cs_track_cube(rdev, track, u); | ||
| 2295 | if (ret) | ||
| 2296 | return ret; | ||
| 2297 | } else | ||
| 2298 | size *= 6; | ||
| 2299 | break; | ||
| 2300 | default: | ||
| 2301 | DRM_ERROR("Invalid texture coordinate type %u for unit " | ||
| 2302 | "%u\n", track->textures[u].tex_coord_type, u); | ||
| 2303 | return -EINVAL; | ||
| 2304 | } | ||
| 2305 | if (size > radeon_bo_size(robj)) { | ||
| 2306 | DRM_ERROR("Texture of unit %u needs %lu bytes but is " | ||
| 2307 | "%lu\n", u, size, radeon_bo_size(robj)); | ||
| 2308 | r100_cs_track_texture_print(&track->textures[u]); | ||
| 2309 | return -EINVAL; | ||
| 2310 | } | ||
| 2311 | } | ||
| 2312 | return 0; | ||
| 2313 | } | ||
| 2314 | |||
| 2315 | int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) | ||
| 2316 | { | ||
| 2317 | unsigned i; | ||
| 2318 | unsigned long size; | ||
| 2319 | unsigned prim_walk; | ||
| 2320 | unsigned nverts; | ||
| 2321 | unsigned num_cb = track->cb_dirty ? track->num_cb : 0; | ||
| 2322 | |||
| 2323 | if (num_cb && !track->zb_cb_clear && !track->color_channel_mask && | ||
| 2324 | !track->blend_read_enable) | ||
| 2325 | num_cb = 0; | ||
| 2326 | |||
| 2327 | for (i = 0; i < num_cb; i++) { | ||
| 2328 | if (track->cb[i].robj == NULL) { | ||
| 2329 | DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); | ||
| 2330 | return -EINVAL; | ||
| 2331 | } | ||
| 2332 | size = track->cb[i].pitch * track->cb[i].cpp * track->maxy; | ||
| 2333 | size += track->cb[i].offset; | ||
| 2334 | if (size > radeon_bo_size(track->cb[i].robj)) { | ||
| 2335 | DRM_ERROR("[drm] Buffer too small for color buffer %d " | ||
| 2336 | "(need %lu have %lu) !\n", i, size, | ||
| 2337 | radeon_bo_size(track->cb[i].robj)); | ||
| 2338 | DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n", | ||
| 2339 | i, track->cb[i].pitch, track->cb[i].cpp, | ||
| 2340 | track->cb[i].offset, track->maxy); | ||
| 2341 | return -EINVAL; | ||
| 2342 | } | ||
| 2343 | } | ||
| 2344 | track->cb_dirty = false; | ||
| 2345 | |||
| 2346 | if (track->zb_dirty && track->z_enabled) { | ||
| 2347 | if (track->zb.robj == NULL) { | ||
| 2348 | DRM_ERROR("[drm] No buffer for z buffer !\n"); | ||
| 2349 | return -EINVAL; | ||
| 2350 | } | ||
| 2351 | size = track->zb.pitch * track->zb.cpp * track->maxy; | ||
| 2352 | size += track->zb.offset; | ||
| 2353 | if (size > radeon_bo_size(track->zb.robj)) { | ||
| 2354 | DRM_ERROR("[drm] Buffer too small for z buffer " | ||
| 2355 | "(need %lu have %lu) !\n", size, | ||
| 2356 | radeon_bo_size(track->zb.robj)); | ||
| 2357 | DRM_ERROR("[drm] zbuffer (%u %u %u %u)\n", | ||
| 2358 | track->zb.pitch, track->zb.cpp, | ||
| 2359 | track->zb.offset, track->maxy); | ||
| 2360 | return -EINVAL; | ||
| 2361 | } | ||
| 2362 | } | ||
| 2363 | track->zb_dirty = false; | ||
| 2364 | |||
| 2365 | if (track->aa_dirty && track->aaresolve) { | ||
| 2366 | if (track->aa.robj == NULL) { | ||
| 2367 | DRM_ERROR("[drm] No buffer for AA resolve buffer %d !\n", i); | ||
| 2368 | return -EINVAL; | ||
| 2369 | } | ||
| 2370 | /* I believe the format comes from colorbuffer0. */ | ||
| 2371 | size = track->aa.pitch * track->cb[0].cpp * track->maxy; | ||
| 2372 | size += track->aa.offset; | ||
| 2373 | if (size > radeon_bo_size(track->aa.robj)) { | ||
| 2374 | DRM_ERROR("[drm] Buffer too small for AA resolve buffer %d " | ||
| 2375 | "(need %lu have %lu) !\n", i, size, | ||
| 2376 | radeon_bo_size(track->aa.robj)); | ||
| 2377 | DRM_ERROR("[drm] AA resolve buffer %d (%u %u %u %u)\n", | ||
| 2378 | i, track->aa.pitch, track->cb[0].cpp, | ||
| 2379 | track->aa.offset, track->maxy); | ||
| 2380 | return -EINVAL; | ||
| 2381 | } | ||
| 2382 | } | ||
| 2383 | track->aa_dirty = false; | ||
| 2384 | |||
| 2385 | prim_walk = (track->vap_vf_cntl >> 4) & 0x3; | ||
| 2386 | if (track->vap_vf_cntl & (1 << 14)) { | ||
| 2387 | nverts = track->vap_alt_nverts; | ||
| 2388 | } else { | ||
| 2389 | nverts = (track->vap_vf_cntl >> 16) & 0xFFFF; | ||
| 2390 | } | ||
| 2391 | switch (prim_walk) { | ||
| 2392 | case 1: | ||
| 2393 | for (i = 0; i < track->num_arrays; i++) { | ||
| 2394 | size = track->arrays[i].esize * track->max_indx * 4; | ||
| 2395 | if (track->arrays[i].robj == NULL) { | ||
| 2396 | DRM_ERROR("(PW %u) Vertex array %u no buffer " | ||
| 2397 | "bound\n", prim_walk, i); | ||
| 2398 | return -EINVAL; | ||
| 2399 | } | ||
| 2400 | if (size > radeon_bo_size(track->arrays[i].robj)) { | ||
| 2401 | dev_err(rdev->dev, "(PW %u) Vertex array %u " | ||
| 2402 | "need %lu dwords have %lu dwords\n", | ||
| 2403 | prim_walk, i, size >> 2, | ||
| 2404 | radeon_bo_size(track->arrays[i].robj) | ||
| 2405 | >> 2); | ||
| 2406 | DRM_ERROR("Max indices %u\n", track->max_indx); | ||
| 2407 | return -EINVAL; | ||
| 2408 | } | ||
| 2409 | } | ||
| 2410 | break; | ||
| 2411 | case 2: | ||
| 2412 | for (i = 0; i < track->num_arrays; i++) { | ||
| 2413 | size = track->arrays[i].esize * (nverts - 1) * 4; | ||
| 2414 | if (track->arrays[i].robj == NULL) { | ||
| 2415 | DRM_ERROR("(PW %u) Vertex array %u no buffer " | ||
| 2416 | "bound\n", prim_walk, i); | ||
| 2417 | return -EINVAL; | ||
| 2418 | } | ||
| 2419 | if (size > radeon_bo_size(track->arrays[i].robj)) { | ||
| 2420 | dev_err(rdev->dev, "(PW %u) Vertex array %u " | ||
| 2421 | "need %lu dwords have %lu dwords\n", | ||
| 2422 | prim_walk, i, size >> 2, | ||
| 2423 | radeon_bo_size(track->arrays[i].robj) | ||
| 2424 | >> 2); | ||
| 2425 | return -EINVAL; | ||
| 2426 | } | ||
| 2427 | } | ||
| 2428 | break; | ||
| 2429 | case 3: | ||
| 2430 | size = track->vtx_size * nverts; | ||
| 2431 | if (size != track->immd_dwords) { | ||
| 2432 | DRM_ERROR("IMMD draw %u dwors but needs %lu dwords\n", | ||
| 2433 | track->immd_dwords, size); | ||
| 2434 | DRM_ERROR("VAP_VF_CNTL.NUM_VERTICES %u, VTX_SIZE %u\n", | ||
| 2435 | nverts, track->vtx_size); | ||
| 2436 | return -EINVAL; | ||
| 2437 | } | ||
| 2438 | break; | ||
| 2439 | default: | ||
| 2440 | DRM_ERROR("[drm] Invalid primitive walk %d for VAP_VF_CNTL\n", | ||
| 2441 | prim_walk); | ||
| 2442 | return -EINVAL; | ||
| 2443 | } | ||
| 2444 | |||
| 2445 | if (track->tex_dirty) { | ||
| 2446 | track->tex_dirty = false; | ||
| 2447 | return r100_cs_track_texture_check(rdev, track); | ||
| 2448 | } | ||
| 2449 | return 0; | ||
| 2450 | } | ||
| 2451 | |||
| 2452 | void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track) | ||
| 2453 | { | ||
| 2454 | unsigned i, face; | ||
| 2455 | |||
| 2456 | track->cb_dirty = true; | ||
| 2457 | track->zb_dirty = true; | ||
| 2458 | track->tex_dirty = true; | ||
| 2459 | track->aa_dirty = true; | ||
| 2460 | |||
| 2461 | if (rdev->family < CHIP_R300) { | ||
| 2462 | track->num_cb = 1; | ||
| 2463 | if (rdev->family <= CHIP_RS200) | ||
| 2464 | track->num_texture = 3; | ||
| 2465 | else | ||
| 2466 | track->num_texture = 6; | ||
| 2467 | track->maxy = 2048; | ||
| 2468 | track->separate_cube = 1; | ||
| 2469 | } else { | ||
| 2470 | track->num_cb = 4; | ||
| 2471 | track->num_texture = 16; | ||
| 2472 | track->maxy = 4096; | ||
| 2473 | track->separate_cube = 0; | ||
| 2474 | track->aaresolve = false; | ||
| 2475 | track->aa.robj = NULL; | ||
| 2476 | } | ||
| 2477 | |||
| 2478 | for (i = 0; i < track->num_cb; i++) { | ||
| 2479 | track->cb[i].robj = NULL; | ||
| 2480 | track->cb[i].pitch = 8192; | ||
| 2481 | track->cb[i].cpp = 16; | ||
| 2482 | track->cb[i].offset = 0; | ||
| 2483 | } | ||
| 2484 | track->z_enabled = true; | ||
| 2485 | track->zb.robj = NULL; | ||
| 2486 | track->zb.pitch = 8192; | ||
| 2487 | track->zb.cpp = 4; | ||
| 2488 | track->zb.offset = 0; | ||
| 2489 | track->vtx_size = 0x7F; | ||
| 2490 | track->immd_dwords = 0xFFFFFFFFUL; | ||
| 2491 | track->num_arrays = 11; | ||
| 2492 | track->max_indx = 0x00FFFFFFUL; | ||
| 2493 | for (i = 0; i < track->num_arrays; i++) { | ||
| 2494 | track->arrays[i].robj = NULL; | ||
| 2495 | track->arrays[i].esize = 0x7F; | ||
| 2496 | } | ||
| 2497 | for (i = 0; i < track->num_texture; i++) { | ||
| 2498 | track->textures[i].compress_format = R100_TRACK_COMP_NONE; | ||
| 2499 | track->textures[i].pitch = 16536; | ||
| 2500 | track->textures[i].width = 16536; | ||
| 2501 | track->textures[i].height = 16536; | ||
| 2502 | track->textures[i].width_11 = 1 << 11; | ||
| 2503 | track->textures[i].height_11 = 1 << 11; | ||
| 2504 | track->textures[i].num_levels = 12; | ||
| 2505 | if (rdev->family <= CHIP_RS200) { | ||
| 2506 | track->textures[i].tex_coord_type = 0; | ||
| 2507 | track->textures[i].txdepth = 0; | ||
| 2508 | } else { | ||
| 2509 | track->textures[i].txdepth = 16; | ||
| 2510 | track->textures[i].tex_coord_type = 1; | ||
| 2511 | } | ||
| 2512 | track->textures[i].cpp = 64; | ||
| 2513 | track->textures[i].robj = NULL; | ||
| 2514 | /* CS IB emission code makes sure texture unit are disabled */ | ||
| 2515 | track->textures[i].enabled = false; | ||
| 2516 | track->textures[i].lookup_disable = false; | ||
| 2517 | track->textures[i].roundup_w = true; | ||
| 2518 | track->textures[i].roundup_h = true; | ||
| 2519 | if (track->separate_cube) | ||
| 2520 | for (face = 0; face < 5; face++) { | ||
| 2521 | track->textures[i].cube_info[face].robj = NULL; | ||
| 2522 | track->textures[i].cube_info[face].width = 16536; | ||
| 2523 | track->textures[i].cube_info[face].height = 16536; | ||
| 2524 | track->textures[i].cube_info[face].offset = 0; | ||
| 2525 | } | ||
| 2526 | } | ||
| 2527 | } | ||
| 2051 | 2528 | ||
| 2052 | /* | 2529 | /* |
| 2053 | * Global GPU functions | 2530 | * Global GPU functions |
| @@ -2175,6 +2652,15 @@ bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 2175 | return radeon_ring_test_lockup(rdev, ring); | 2652 | return radeon_ring_test_lockup(rdev, ring); |
| 2176 | } | 2653 | } |
| 2177 | 2654 | ||
| 2655 | /* required on r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ | ||
| 2656 | void r100_enable_bm(struct radeon_device *rdev) | ||
| 2657 | { | ||
| 2658 | uint32_t tmp; | ||
| 2659 | /* Enable bus mastering */ | ||
| 2660 | tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; | ||
| 2661 | WREG32(RADEON_BUS_CNTL, tmp); | ||
| 2662 | } | ||
| 2663 | |||
| 2178 | void r100_bm_disable(struct radeon_device *rdev) | 2664 | void r100_bm_disable(struct radeon_device *rdev) |
| 2179 | { | 2665 | { |
| 2180 | u32 tmp; | 2666 | u32 tmp; |
| @@ -3261,380 +3747,6 @@ void r100_bandwidth_update(struct radeon_device *rdev) | |||
| 3261 | } | 3747 | } |
| 3262 | } | 3748 | } |
| 3263 | 3749 | ||
| 3264 | static void r100_cs_track_texture_print(struct r100_cs_track_texture *t) | ||
| 3265 | { | ||
| 3266 | DRM_ERROR("pitch %d\n", t->pitch); | ||
| 3267 | DRM_ERROR("use_pitch %d\n", t->use_pitch); | ||
| 3268 | DRM_ERROR("width %d\n", t->width); | ||
| 3269 | DRM_ERROR("width_11 %d\n", t->width_11); | ||
| 3270 | DRM_ERROR("height %d\n", t->height); | ||
| 3271 | DRM_ERROR("height_11 %d\n", t->height_11); | ||
| 3272 | DRM_ERROR("num levels %d\n", t->num_levels); | ||
| 3273 | DRM_ERROR("depth %d\n", t->txdepth); | ||
| 3274 | DRM_ERROR("bpp %d\n", t->cpp); | ||
| 3275 | DRM_ERROR("coordinate type %d\n", t->tex_coord_type); | ||
| 3276 | DRM_ERROR("width round to power of 2 %d\n", t->roundup_w); | ||
| 3277 | DRM_ERROR("height round to power of 2 %d\n", t->roundup_h); | ||
| 3278 | DRM_ERROR("compress format %d\n", t->compress_format); | ||
| 3279 | } | ||
| 3280 | |||
| 3281 | static int r100_track_compress_size(int compress_format, int w, int h) | ||
| 3282 | { | ||
| 3283 | int block_width, block_height, block_bytes; | ||
| 3284 | int wblocks, hblocks; | ||
| 3285 | int min_wblocks; | ||
| 3286 | int sz; | ||
| 3287 | |||
| 3288 | block_width = 4; | ||
| 3289 | block_height = 4; | ||
| 3290 | |||
| 3291 | switch (compress_format) { | ||
| 3292 | case R100_TRACK_COMP_DXT1: | ||
| 3293 | block_bytes = 8; | ||
| 3294 | min_wblocks = 4; | ||
| 3295 | break; | ||
| 3296 | default: | ||
| 3297 | case R100_TRACK_COMP_DXT35: | ||
| 3298 | block_bytes = 16; | ||
| 3299 | min_wblocks = 2; | ||
| 3300 | break; | ||
| 3301 | } | ||
| 3302 | |||
| 3303 | hblocks = (h + block_height - 1) / block_height; | ||
| 3304 | wblocks = (w + block_width - 1) / block_width; | ||
| 3305 | if (wblocks < min_wblocks) | ||
| 3306 | wblocks = min_wblocks; | ||
| 3307 | sz = wblocks * hblocks * block_bytes; | ||
| 3308 | return sz; | ||
| 3309 | } | ||
| 3310 | |||
| 3311 | static int r100_cs_track_cube(struct radeon_device *rdev, | ||
| 3312 | struct r100_cs_track *track, unsigned idx) | ||
| 3313 | { | ||
| 3314 | unsigned face, w, h; | ||
| 3315 | struct radeon_bo *cube_robj; | ||
| 3316 | unsigned long size; | ||
| 3317 | unsigned compress_format = track->textures[idx].compress_format; | ||
| 3318 | |||
| 3319 | for (face = 0; face < 5; face++) { | ||
| 3320 | cube_robj = track->textures[idx].cube_info[face].robj; | ||
| 3321 | w = track->textures[idx].cube_info[face].width; | ||
| 3322 | h = track->textures[idx].cube_info[face].height; | ||
| 3323 | |||
| 3324 | if (compress_format) { | ||
| 3325 | size = r100_track_compress_size(compress_format, w, h); | ||
| 3326 | } else | ||
| 3327 | size = w * h; | ||
| 3328 | size *= track->textures[idx].cpp; | ||
| 3329 | |||
| 3330 | size += track->textures[idx].cube_info[face].offset; | ||
| 3331 | |||
| 3332 | if (size > radeon_bo_size(cube_robj)) { | ||
| 3333 | DRM_ERROR("Cube texture offset greater than object size %lu %lu\n", | ||
| 3334 | size, radeon_bo_size(cube_robj)); | ||
| 3335 | r100_cs_track_texture_print(&track->textures[idx]); | ||
| 3336 | return -1; | ||
| 3337 | } | ||
| 3338 | } | ||
| 3339 | return 0; | ||
| 3340 | } | ||
| 3341 | |||
| 3342 | static int r100_cs_track_texture_check(struct radeon_device *rdev, | ||
| 3343 | struct r100_cs_track *track) | ||
| 3344 | { | ||
| 3345 | struct radeon_bo *robj; | ||
| 3346 | unsigned long size; | ||
| 3347 | unsigned u, i, w, h, d; | ||
| 3348 | int ret; | ||
| 3349 | |||
| 3350 | for (u = 0; u < track->num_texture; u++) { | ||
| 3351 | if (!track->textures[u].enabled) | ||
| 3352 | continue; | ||
| 3353 | if (track->textures[u].lookup_disable) | ||
| 3354 | continue; | ||
| 3355 | robj = track->textures[u].robj; | ||
| 3356 | if (robj == NULL) { | ||
| 3357 | DRM_ERROR("No texture bound to unit %u\n", u); | ||
| 3358 | return -EINVAL; | ||
| 3359 | } | ||
| 3360 | size = 0; | ||
| 3361 | for (i = 0; i <= track->textures[u].num_levels; i++) { | ||
| 3362 | if (track->textures[u].use_pitch) { | ||
| 3363 | if (rdev->family < CHIP_R300) | ||
| 3364 | w = (track->textures[u].pitch / track->textures[u].cpp) / (1 << i); | ||
| 3365 | else | ||
| 3366 | w = track->textures[u].pitch / (1 << i); | ||
| 3367 | } else { | ||
| 3368 | w = track->textures[u].width; | ||
| 3369 | if (rdev->family >= CHIP_RV515) | ||
| 3370 | w |= track->textures[u].width_11; | ||
| 3371 | w = w / (1 << i); | ||
| 3372 | if (track->textures[u].roundup_w) | ||
| 3373 | w = roundup_pow_of_two(w); | ||
| 3374 | } | ||
| 3375 | h = track->textures[u].height; | ||
| 3376 | if (rdev->family >= CHIP_RV515) | ||
| 3377 | h |= track->textures[u].height_11; | ||
| 3378 | h = h / (1 << i); | ||
| 3379 | if (track->textures[u].roundup_h) | ||
| 3380 | h = roundup_pow_of_two(h); | ||
| 3381 | if (track->textures[u].tex_coord_type == 1) { | ||
| 3382 | d = (1 << track->textures[u].txdepth) / (1 << i); | ||
| 3383 | if (!d) | ||
| 3384 | d = 1; | ||
| 3385 | } else { | ||
| 3386 | d = 1; | ||
| 3387 | } | ||
| 3388 | if (track->textures[u].compress_format) { | ||
| 3389 | |||
| 3390 | size += r100_track_compress_size(track->textures[u].compress_format, w, h) * d; | ||
| 3391 | /* compressed textures are block based */ | ||
| 3392 | } else | ||
| 3393 | size += w * h * d; | ||
| 3394 | } | ||
| 3395 | size *= track->textures[u].cpp; | ||
| 3396 | |||
| 3397 | switch (track->textures[u].tex_coord_type) { | ||
| 3398 | case 0: | ||
| 3399 | case 1: | ||
| 3400 | break; | ||
| 3401 | case 2: | ||
| 3402 | if (track->separate_cube) { | ||
| 3403 | ret = r100_cs_track_cube(rdev, track, u); | ||
| 3404 | if (ret) | ||
| 3405 | return ret; | ||
| 3406 | } else | ||
| 3407 | size *= 6; | ||
| 3408 | break; | ||
| 3409 | default: | ||
| 3410 | DRM_ERROR("Invalid texture coordinate type %u for unit " | ||
| 3411 | "%u\n", track->textures[u].tex_coord_type, u); | ||
| 3412 | return -EINVAL; | ||
| 3413 | } | ||
| 3414 | if (size > radeon_bo_size(robj)) { | ||
| 3415 | DRM_ERROR("Texture of unit %u needs %lu bytes but is " | ||
| 3416 | "%lu\n", u, size, radeon_bo_size(robj)); | ||
| 3417 | r100_cs_track_texture_print(&track->textures[u]); | ||
| 3418 | return -EINVAL; | ||
| 3419 | } | ||
| 3420 | } | ||
| 3421 | return 0; | ||
| 3422 | } | ||
| 3423 | |||
| 3424 | int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) | ||
| 3425 | { | ||
| 3426 | unsigned i; | ||
| 3427 | unsigned long size; | ||
| 3428 | unsigned prim_walk; | ||
| 3429 | unsigned nverts; | ||
| 3430 | unsigned num_cb = track->cb_dirty ? track->num_cb : 0; | ||
| 3431 | |||
| 3432 | if (num_cb && !track->zb_cb_clear && !track->color_channel_mask && | ||
| 3433 | !track->blend_read_enable) | ||
| 3434 | num_cb = 0; | ||
| 3435 | |||
| 3436 | for (i = 0; i < num_cb; i++) { | ||
| 3437 | if (track->cb[i].robj == NULL) { | ||
| 3438 | DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); | ||
| 3439 | return -EINVAL; | ||
| 3440 | } | ||
| 3441 | size = track->cb[i].pitch * track->cb[i].cpp * track->maxy; | ||
| 3442 | size += track->cb[i].offset; | ||
| 3443 | if (size > radeon_bo_size(track->cb[i].robj)) { | ||
| 3444 | DRM_ERROR("[drm] Buffer too small for color buffer %d " | ||
| 3445 | "(need %lu have %lu) !\n", i, size, | ||
| 3446 | radeon_bo_size(track->cb[i].robj)); | ||
| 3447 | DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n", | ||
| 3448 | i, track->cb[i].pitch, track->cb[i].cpp, | ||
| 3449 | track->cb[i].offset, track->maxy); | ||
| 3450 | return -EINVAL; | ||
| 3451 | } | ||
| 3452 | } | ||
| 3453 | track->cb_dirty = false; | ||
| 3454 | |||
| 3455 | if (track->zb_dirty && track->z_enabled) { | ||
| 3456 | if (track->zb.robj == NULL) { | ||
| 3457 | DRM_ERROR("[drm] No buffer for z buffer !\n"); | ||
| 3458 | return -EINVAL; | ||
| 3459 | } | ||
| 3460 | size = track->zb.pitch * track->zb.cpp * track->maxy; | ||
| 3461 | size += track->zb.offset; | ||
| 3462 | if (size > radeon_bo_size(track->zb.robj)) { | ||
| 3463 | DRM_ERROR("[drm] Buffer too small for z buffer " | ||
| 3464 | "(need %lu have %lu) !\n", size, | ||
| 3465 | radeon_bo_size(track->zb.robj)); | ||
| 3466 | DRM_ERROR("[drm] zbuffer (%u %u %u %u)\n", | ||
| 3467 | track->zb.pitch, track->zb.cpp, | ||
| 3468 | track->zb.offset, track->maxy); | ||
| 3469 | return -EINVAL; | ||
| 3470 | } | ||
| 3471 | } | ||
| 3472 | track->zb_dirty = false; | ||
| 3473 | |||
| 3474 | if (track->aa_dirty && track->aaresolve) { | ||
| 3475 | if (track->aa.robj == NULL) { | ||
| 3476 | DRM_ERROR("[drm] No buffer for AA resolve buffer %d !\n", i); | ||
| 3477 | return -EINVAL; | ||
| 3478 | } | ||
| 3479 | /* I believe the format comes from colorbuffer0. */ | ||
| 3480 | size = track->aa.pitch * track->cb[0].cpp * track->maxy; | ||
| 3481 | size += track->aa.offset; | ||
| 3482 | if (size > radeon_bo_size(track->aa.robj)) { | ||
| 3483 | DRM_ERROR("[drm] Buffer too small for AA resolve buffer %d " | ||
| 3484 | "(need %lu have %lu) !\n", i, size, | ||
| 3485 | radeon_bo_size(track->aa.robj)); | ||
| 3486 | DRM_ERROR("[drm] AA resolve buffer %d (%u %u %u %u)\n", | ||
| 3487 | i, track->aa.pitch, track->cb[0].cpp, | ||
| 3488 | track->aa.offset, track->maxy); | ||
| 3489 | return -EINVAL; | ||
| 3490 | } | ||
| 3491 | } | ||
| 3492 | track->aa_dirty = false; | ||
| 3493 | |||
| 3494 | prim_walk = (track->vap_vf_cntl >> 4) & 0x3; | ||
| 3495 | if (track->vap_vf_cntl & (1 << 14)) { | ||
| 3496 | nverts = track->vap_alt_nverts; | ||
| 3497 | } else { | ||
| 3498 | nverts = (track->vap_vf_cntl >> 16) & 0xFFFF; | ||
| 3499 | } | ||
| 3500 | switch (prim_walk) { | ||
| 3501 | case 1: | ||
| 3502 | for (i = 0; i < track->num_arrays; i++) { | ||
| 3503 | size = track->arrays[i].esize * track->max_indx * 4; | ||
| 3504 | if (track->arrays[i].robj == NULL) { | ||
| 3505 | DRM_ERROR("(PW %u) Vertex array %u no buffer " | ||
| 3506 | "bound\n", prim_walk, i); | ||
| 3507 | return -EINVAL; | ||
| 3508 | } | ||
| 3509 | if (size > radeon_bo_size(track->arrays[i].robj)) { | ||
| 3510 | dev_err(rdev->dev, "(PW %u) Vertex array %u " | ||
| 3511 | "need %lu dwords have %lu dwords\n", | ||
| 3512 | prim_walk, i, size >> 2, | ||
| 3513 | radeon_bo_size(track->arrays[i].robj) | ||
| 3514 | >> 2); | ||
| 3515 | DRM_ERROR("Max indices %u\n", track->max_indx); | ||
| 3516 | return -EINVAL; | ||
| 3517 | } | ||
| 3518 | } | ||
| 3519 | break; | ||
| 3520 | case 2: | ||
| 3521 | for (i = 0; i < track->num_arrays; i++) { | ||
| 3522 | size = track->arrays[i].esize * (nverts - 1) * 4; | ||
| 3523 | if (track->arrays[i].robj == NULL) { | ||
| 3524 | DRM_ERROR("(PW %u) Vertex array %u no buffer " | ||
| 3525 | "bound\n", prim_walk, i); | ||
| 3526 | return -EINVAL; | ||
| 3527 | } | ||
| 3528 | if (size > radeon_bo_size(track->arrays[i].robj)) { | ||
| 3529 | dev_err(rdev->dev, "(PW %u) Vertex array %u " | ||
| 3530 | "need %lu dwords have %lu dwords\n", | ||
| 3531 | prim_walk, i, size >> 2, | ||
| 3532 | radeon_bo_size(track->arrays[i].robj) | ||
| 3533 | >> 2); | ||
| 3534 | return -EINVAL; | ||
| 3535 | } | ||
| 3536 | } | ||
| 3537 | break; | ||
| 3538 | case 3: | ||
| 3539 | size = track->vtx_size * nverts; | ||
| 3540 | if (size != track->immd_dwords) { | ||
| 3541 | DRM_ERROR("IMMD draw %u dwors but needs %lu dwords\n", | ||
| 3542 | track->immd_dwords, size); | ||
| 3543 | DRM_ERROR("VAP_VF_CNTL.NUM_VERTICES %u, VTX_SIZE %u\n", | ||
| 3544 | nverts, track->vtx_size); | ||
| 3545 | return -EINVAL; | ||
| 3546 | } | ||
| 3547 | break; | ||
| 3548 | default: | ||
| 3549 | DRM_ERROR("[drm] Invalid primitive walk %d for VAP_VF_CNTL\n", | ||
| 3550 | prim_walk); | ||
| 3551 | return -EINVAL; | ||
| 3552 | } | ||
| 3553 | |||
| 3554 | if (track->tex_dirty) { | ||
| 3555 | track->tex_dirty = false; | ||
| 3556 | return r100_cs_track_texture_check(rdev, track); | ||
| 3557 | } | ||
| 3558 | return 0; | ||
| 3559 | } | ||
| 3560 | |||
| 3561 | void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track) | ||
| 3562 | { | ||
| 3563 | unsigned i, face; | ||
| 3564 | |||
| 3565 | track->cb_dirty = true; | ||
| 3566 | track->zb_dirty = true; | ||
| 3567 | track->tex_dirty = true; | ||
| 3568 | track->aa_dirty = true; | ||
| 3569 | |||
| 3570 | if (rdev->family < CHIP_R300) { | ||
| 3571 | track->num_cb = 1; | ||
| 3572 | if (rdev->family <= CHIP_RS200) | ||
| 3573 | track->num_texture = 3; | ||
| 3574 | else | ||
| 3575 | track->num_texture = 6; | ||
| 3576 | track->maxy = 2048; | ||
| 3577 | track->separate_cube = 1; | ||
| 3578 | } else { | ||
| 3579 | track->num_cb = 4; | ||
| 3580 | track->num_texture = 16; | ||
| 3581 | track->maxy = 4096; | ||
| 3582 | track->separate_cube = 0; | ||
| 3583 | track->aaresolve = false; | ||
| 3584 | track->aa.robj = NULL; | ||
| 3585 | } | ||
| 3586 | |||
| 3587 | for (i = 0; i < track->num_cb; i++) { | ||
| 3588 | track->cb[i].robj = NULL; | ||
| 3589 | track->cb[i].pitch = 8192; | ||
| 3590 | track->cb[i].cpp = 16; | ||
| 3591 | track->cb[i].offset = 0; | ||
| 3592 | } | ||
| 3593 | track->z_enabled = true; | ||
| 3594 | track->zb.robj = NULL; | ||
| 3595 | track->zb.pitch = 8192; | ||
| 3596 | track->zb.cpp = 4; | ||
| 3597 | track->zb.offset = 0; | ||
| 3598 | track->vtx_size = 0x7F; | ||
| 3599 | track->immd_dwords = 0xFFFFFFFFUL; | ||
| 3600 | track->num_arrays = 11; | ||
| 3601 | track->max_indx = 0x00FFFFFFUL; | ||
| 3602 | for (i = 0; i < track->num_arrays; i++) { | ||
| 3603 | track->arrays[i].robj = NULL; | ||
| 3604 | track->arrays[i].esize = 0x7F; | ||
| 3605 | } | ||
| 3606 | for (i = 0; i < track->num_texture; i++) { | ||
| 3607 | track->textures[i].compress_format = R100_TRACK_COMP_NONE; | ||
| 3608 | track->textures[i].pitch = 16536; | ||
| 3609 | track->textures[i].width = 16536; | ||
| 3610 | track->textures[i].height = 16536; | ||
| 3611 | track->textures[i].width_11 = 1 << 11; | ||
| 3612 | track->textures[i].height_11 = 1 << 11; | ||
| 3613 | track->textures[i].num_levels = 12; | ||
| 3614 | if (rdev->family <= CHIP_RS200) { | ||
| 3615 | track->textures[i].tex_coord_type = 0; | ||
| 3616 | track->textures[i].txdepth = 0; | ||
| 3617 | } else { | ||
| 3618 | track->textures[i].txdepth = 16; | ||
| 3619 | track->textures[i].tex_coord_type = 1; | ||
| 3620 | } | ||
| 3621 | track->textures[i].cpp = 64; | ||
| 3622 | track->textures[i].robj = NULL; | ||
| 3623 | /* CS IB emission code makes sure texture unit are disabled */ | ||
| 3624 | track->textures[i].enabled = false; | ||
| 3625 | track->textures[i].lookup_disable = false; | ||
| 3626 | track->textures[i].roundup_w = true; | ||
| 3627 | track->textures[i].roundup_h = true; | ||
| 3628 | if (track->separate_cube) | ||
| 3629 | for (face = 0; face < 5; face++) { | ||
| 3630 | track->textures[i].cube_info[face].robj = NULL; | ||
| 3631 | track->textures[i].cube_info[face].width = 16536; | ||
| 3632 | track->textures[i].cube_info[face].height = 16536; | ||
| 3633 | track->textures[i].cube_info[face].offset = 0; | ||
| 3634 | } | ||
| 3635 | } | ||
| 3636 | } | ||
| 3637 | |||
| 3638 | int r100_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) | 3750 | int r100_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) |
| 3639 | { | 3751 | { |
| 3640 | uint32_t scratch; | 3752 | uint32_t scratch; |
| @@ -3679,6 +3791,12 @@ void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) | |||
| 3679 | { | 3791 | { |
| 3680 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | 3792 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
| 3681 | 3793 | ||
| 3794 | if (ring->rptr_save_reg) { | ||
| 3795 | u32 next_rptr = ring->wptr + 2 + 3; | ||
| 3796 | radeon_ring_write(ring, PACKET0(ring->rptr_save_reg, 0)); | ||
| 3797 | radeon_ring_write(ring, next_rptr); | ||
| 3798 | } | ||
| 3799 | |||
| 3682 | radeon_ring_write(ring, PACKET0(RADEON_CP_IB_BASE, 1)); | 3800 | radeon_ring_write(ring, PACKET0(RADEON_CP_IB_BASE, 1)); |
| 3683 | radeon_ring_write(ring, ib->gpu_addr); | 3801 | radeon_ring_write(ring, ib->gpu_addr); |
| 3684 | radeon_ring_write(ring, ib->length_dw); | 3802 | radeon_ring_write(ring, ib->length_dw); |
| @@ -3711,7 +3829,7 @@ int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 3711 | ib.ptr[6] = PACKET2(0); | 3829 | ib.ptr[6] = PACKET2(0); |
| 3712 | ib.ptr[7] = PACKET2(0); | 3830 | ib.ptr[7] = PACKET2(0); |
| 3713 | ib.length_dw = 8; | 3831 | ib.length_dw = 8; |
| 3714 | r = radeon_ib_schedule(rdev, &ib); | 3832 | r = radeon_ib_schedule(rdev, &ib, NULL); |
| 3715 | if (r) { | 3833 | if (r) { |
| 3716 | radeon_scratch_free(rdev, scratch); | 3834 | radeon_scratch_free(rdev, scratch); |
| 3717 | radeon_ib_free(rdev, &ib); | 3835 | radeon_ib_free(rdev, &ib); |
| @@ -3740,12 +3858,6 @@ int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 3740 | return r; | 3858 | return r; |
| 3741 | } | 3859 | } |
| 3742 | 3860 | ||
| 3743 | void r100_ib_fini(struct radeon_device *rdev) | ||
| 3744 | { | ||
| 3745 | radeon_ib_pool_suspend(rdev); | ||
| 3746 | radeon_ib_pool_fini(rdev); | ||
| 3747 | } | ||
| 3748 | |||
| 3749 | void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save) | 3861 | void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save) |
| 3750 | { | 3862 | { |
| 3751 | /* Shutdown CP we shouldn't need to do that but better be safe than | 3863 | /* Shutdown CP we shouldn't need to do that but better be safe than |
| @@ -3905,13 +4017,11 @@ static int r100_startup(struct radeon_device *rdev) | |||
| 3905 | return r; | 4017 | return r; |
| 3906 | } | 4018 | } |
| 3907 | 4019 | ||
| 3908 | r = radeon_ib_pool_start(rdev); | 4020 | r = radeon_ib_pool_init(rdev); |
| 3909 | if (r) | 4021 | if (r) { |
| 3910 | return r; | 4022 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 3911 | |||
| 3912 | r = radeon_ib_ring_tests(rdev); | ||
| 3913 | if (r) | ||
| 3914 | return r; | 4023 | return r; |
| 4024 | } | ||
| 3915 | 4025 | ||
| 3916 | return 0; | 4026 | return 0; |
| 3917 | } | 4027 | } |
| @@ -3948,7 +4058,6 @@ int r100_resume(struct radeon_device *rdev) | |||
| 3948 | 4058 | ||
| 3949 | int r100_suspend(struct radeon_device *rdev) | 4059 | int r100_suspend(struct radeon_device *rdev) |
| 3950 | { | 4060 | { |
| 3951 | radeon_ib_pool_suspend(rdev); | ||
| 3952 | r100_cp_disable(rdev); | 4061 | r100_cp_disable(rdev); |
| 3953 | radeon_wb_disable(rdev); | 4062 | radeon_wb_disable(rdev); |
| 3954 | r100_irq_disable(rdev); | 4063 | r100_irq_disable(rdev); |
| @@ -3961,7 +4070,7 @@ void r100_fini(struct radeon_device *rdev) | |||
| 3961 | { | 4070 | { |
| 3962 | r100_cp_fini(rdev); | 4071 | r100_cp_fini(rdev); |
| 3963 | radeon_wb_fini(rdev); | 4072 | radeon_wb_fini(rdev); |
| 3964 | r100_ib_fini(rdev); | 4073 | radeon_ib_pool_fini(rdev); |
| 3965 | radeon_gem_fini(rdev); | 4074 | radeon_gem_fini(rdev); |
| 3966 | if (rdev->flags & RADEON_IS_PCI) | 4075 | if (rdev->flags & RADEON_IS_PCI) |
| 3967 | r100_pci_gart_fini(rdev); | 4076 | r100_pci_gart_fini(rdev); |
| @@ -4068,20 +4177,14 @@ int r100_init(struct radeon_device *rdev) | |||
| 4068 | } | 4177 | } |
| 4069 | r100_set_safe_registers(rdev); | 4178 | r100_set_safe_registers(rdev); |
| 4070 | 4179 | ||
| 4071 | r = radeon_ib_pool_init(rdev); | ||
| 4072 | rdev->accel_working = true; | 4180 | rdev->accel_working = true; |
| 4073 | if (r) { | ||
| 4074 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 4075 | rdev->accel_working = false; | ||
| 4076 | } | ||
| 4077 | |||
| 4078 | r = r100_startup(rdev); | 4181 | r = r100_startup(rdev); |
| 4079 | if (r) { | 4182 | if (r) { |
| 4080 | /* Somethings want wront with the accel init stop accel */ | 4183 | /* Somethings want wront with the accel init stop accel */ |
| 4081 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 4184 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
| 4082 | r100_cp_fini(rdev); | 4185 | r100_cp_fini(rdev); |
| 4083 | radeon_wb_fini(rdev); | 4186 | radeon_wb_fini(rdev); |
| 4084 | r100_ib_fini(rdev); | 4187 | radeon_ib_pool_fini(rdev); |
| 4085 | radeon_irq_kms_fini(rdev); | 4188 | radeon_irq_kms_fini(rdev); |
| 4086 | if (rdev->flags & RADEON_IS_PCI) | 4189 | if (rdev->flags & RADEON_IS_PCI) |
| 4087 | r100_pci_gart_fini(rdev); | 4190 | r100_pci_gart_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c index a26144d01207..f0889259eb08 100644 --- a/drivers/gpu/drm/radeon/r200.c +++ b/drivers/gpu/drm/radeon/r200.c | |||
| @@ -85,7 +85,7 @@ int r200_copy_dma(struct radeon_device *rdev, | |||
| 85 | uint64_t src_offset, | 85 | uint64_t src_offset, |
| 86 | uint64_t dst_offset, | 86 | uint64_t dst_offset, |
| 87 | unsigned num_gpu_pages, | 87 | unsigned num_gpu_pages, |
| 88 | struct radeon_fence *fence) | 88 | struct radeon_fence **fence) |
| 89 | { | 89 | { |
| 90 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | 90 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
| 91 | uint32_t size; | 91 | uint32_t size; |
| @@ -120,7 +120,7 @@ int r200_copy_dma(struct radeon_device *rdev, | |||
| 120 | radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); | 120 | radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); |
| 121 | radeon_ring_write(ring, RADEON_WAIT_DMA_GUI_IDLE); | 121 | radeon_ring_write(ring, RADEON_WAIT_DMA_GUI_IDLE); |
| 122 | if (fence) { | 122 | if (fence) { |
| 123 | r = radeon_fence_emit(rdev, fence); | 123 | r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX); |
| 124 | } | 124 | } |
| 125 | radeon_ring_unlock_commit(rdev, ring); | 125 | radeon_ring_unlock_commit(rdev, ring); |
| 126 | return r; | 126 | return r; |
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 97722a33e513..646a1927dda7 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c | |||
| @@ -1391,13 +1391,11 @@ static int r300_startup(struct radeon_device *rdev) | |||
| 1391 | return r; | 1391 | return r; |
| 1392 | } | 1392 | } |
| 1393 | 1393 | ||
| 1394 | r = radeon_ib_pool_start(rdev); | 1394 | r = radeon_ib_pool_init(rdev); |
| 1395 | if (r) | 1395 | if (r) { |
| 1396 | return r; | 1396 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 1397 | |||
| 1398 | r = radeon_ib_ring_tests(rdev); | ||
| 1399 | if (r) | ||
| 1400 | return r; | 1397 | return r; |
| 1398 | } | ||
| 1401 | 1399 | ||
| 1402 | return 0; | 1400 | return 0; |
| 1403 | } | 1401 | } |
| @@ -1436,7 +1434,6 @@ int r300_resume(struct radeon_device *rdev) | |||
| 1436 | 1434 | ||
| 1437 | int r300_suspend(struct radeon_device *rdev) | 1435 | int r300_suspend(struct radeon_device *rdev) |
| 1438 | { | 1436 | { |
| 1439 | radeon_ib_pool_suspend(rdev); | ||
| 1440 | r100_cp_disable(rdev); | 1437 | r100_cp_disable(rdev); |
| 1441 | radeon_wb_disable(rdev); | 1438 | radeon_wb_disable(rdev); |
| 1442 | r100_irq_disable(rdev); | 1439 | r100_irq_disable(rdev); |
| @@ -1451,7 +1448,7 @@ void r300_fini(struct radeon_device *rdev) | |||
| 1451 | { | 1448 | { |
| 1452 | r100_cp_fini(rdev); | 1449 | r100_cp_fini(rdev); |
| 1453 | radeon_wb_fini(rdev); | 1450 | radeon_wb_fini(rdev); |
| 1454 | r100_ib_fini(rdev); | 1451 | radeon_ib_pool_fini(rdev); |
| 1455 | radeon_gem_fini(rdev); | 1452 | radeon_gem_fini(rdev); |
| 1456 | if (rdev->flags & RADEON_IS_PCIE) | 1453 | if (rdev->flags & RADEON_IS_PCIE) |
| 1457 | rv370_pcie_gart_fini(rdev); | 1454 | rv370_pcie_gart_fini(rdev); |
| @@ -1538,20 +1535,14 @@ int r300_init(struct radeon_device *rdev) | |||
| 1538 | } | 1535 | } |
| 1539 | r300_set_reg_safe(rdev); | 1536 | r300_set_reg_safe(rdev); |
| 1540 | 1537 | ||
| 1541 | r = radeon_ib_pool_init(rdev); | ||
| 1542 | rdev->accel_working = true; | 1538 | rdev->accel_working = true; |
| 1543 | if (r) { | ||
| 1544 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 1545 | rdev->accel_working = false; | ||
| 1546 | } | ||
| 1547 | |||
| 1548 | r = r300_startup(rdev); | 1539 | r = r300_startup(rdev); |
| 1549 | if (r) { | 1540 | if (r) { |
| 1550 | /* Somethings want wront with the accel init stop accel */ | 1541 | /* Somethings want wront with the accel init stop accel */ |
| 1551 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 1542 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
| 1552 | r100_cp_fini(rdev); | 1543 | r100_cp_fini(rdev); |
| 1553 | radeon_wb_fini(rdev); | 1544 | radeon_wb_fini(rdev); |
| 1554 | r100_ib_fini(rdev); | 1545 | radeon_ib_pool_fini(rdev); |
| 1555 | radeon_irq_kms_fini(rdev); | 1546 | radeon_irq_kms_fini(rdev); |
| 1556 | if (rdev->flags & RADEON_IS_PCIE) | 1547 | if (rdev->flags & RADEON_IS_PCIE) |
| 1557 | rv370_pcie_gart_fini(rdev); | 1548 | rv370_pcie_gart_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 99137be7a300..f2f5bf6d339f 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c | |||
| @@ -275,13 +275,11 @@ static int r420_startup(struct radeon_device *rdev) | |||
| 275 | } | 275 | } |
| 276 | r420_cp_errata_init(rdev); | 276 | r420_cp_errata_init(rdev); |
| 277 | 277 | ||
| 278 | r = radeon_ib_pool_start(rdev); | 278 | r = radeon_ib_pool_init(rdev); |
| 279 | if (r) | 279 | if (r) { |
| 280 | return r; | 280 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 281 | |||
| 282 | r = radeon_ib_ring_tests(rdev); | ||
| 283 | if (r) | ||
| 284 | return r; | 281 | return r; |
| 282 | } | ||
| 285 | 283 | ||
| 286 | return 0; | 284 | return 0; |
| 287 | } | 285 | } |
| @@ -324,7 +322,6 @@ int r420_resume(struct radeon_device *rdev) | |||
| 324 | 322 | ||
| 325 | int r420_suspend(struct radeon_device *rdev) | 323 | int r420_suspend(struct radeon_device *rdev) |
| 326 | { | 324 | { |
| 327 | radeon_ib_pool_suspend(rdev); | ||
| 328 | r420_cp_errata_fini(rdev); | 325 | r420_cp_errata_fini(rdev); |
| 329 | r100_cp_disable(rdev); | 326 | r100_cp_disable(rdev); |
| 330 | radeon_wb_disable(rdev); | 327 | radeon_wb_disable(rdev); |
| @@ -340,7 +337,7 @@ void r420_fini(struct radeon_device *rdev) | |||
| 340 | { | 337 | { |
| 341 | r100_cp_fini(rdev); | 338 | r100_cp_fini(rdev); |
| 342 | radeon_wb_fini(rdev); | 339 | radeon_wb_fini(rdev); |
| 343 | r100_ib_fini(rdev); | 340 | radeon_ib_pool_fini(rdev); |
| 344 | radeon_gem_fini(rdev); | 341 | radeon_gem_fini(rdev); |
| 345 | if (rdev->flags & RADEON_IS_PCIE) | 342 | if (rdev->flags & RADEON_IS_PCIE) |
| 346 | rv370_pcie_gart_fini(rdev); | 343 | rv370_pcie_gart_fini(rdev); |
| @@ -438,20 +435,14 @@ int r420_init(struct radeon_device *rdev) | |||
| 438 | } | 435 | } |
| 439 | r420_set_reg_safe(rdev); | 436 | r420_set_reg_safe(rdev); |
| 440 | 437 | ||
| 441 | r = radeon_ib_pool_init(rdev); | ||
| 442 | rdev->accel_working = true; | 438 | rdev->accel_working = true; |
| 443 | if (r) { | ||
| 444 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 445 | rdev->accel_working = false; | ||
| 446 | } | ||
| 447 | |||
| 448 | r = r420_startup(rdev); | 439 | r = r420_startup(rdev); |
| 449 | if (r) { | 440 | if (r) { |
| 450 | /* Somethings want wront with the accel init stop accel */ | 441 | /* Somethings want wront with the accel init stop accel */ |
| 451 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 442 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
| 452 | r100_cp_fini(rdev); | 443 | r100_cp_fini(rdev); |
| 453 | radeon_wb_fini(rdev); | 444 | radeon_wb_fini(rdev); |
| 454 | r100_ib_fini(rdev); | 445 | radeon_ib_pool_fini(rdev); |
| 455 | radeon_irq_kms_fini(rdev); | 446 | radeon_irq_kms_fini(rdev); |
| 456 | if (rdev->flags & RADEON_IS_PCIE) | 447 | if (rdev->flags & RADEON_IS_PCIE) |
| 457 | rv370_pcie_gart_fini(rdev); | 448 | rv370_pcie_gart_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index b5cf8375cd25..079d3c52c08a 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c | |||
| @@ -203,13 +203,11 @@ static int r520_startup(struct radeon_device *rdev) | |||
| 203 | return r; | 203 | return r; |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | r = radeon_ib_pool_start(rdev); | 206 | r = radeon_ib_pool_init(rdev); |
| 207 | if (r) | 207 | if (r) { |
| 208 | return r; | 208 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 209 | |||
| 210 | r = radeon_ib_ring_tests(rdev); | ||
| 211 | if (r) | ||
| 212 | return r; | 209 | return r; |
| 210 | } | ||
| 213 | 211 | ||
| 214 | return 0; | 212 | return 0; |
| 215 | } | 213 | } |
| @@ -311,20 +309,14 @@ int r520_init(struct radeon_device *rdev) | |||
| 311 | return r; | 309 | return r; |
| 312 | rv515_set_safe_registers(rdev); | 310 | rv515_set_safe_registers(rdev); |
| 313 | 311 | ||
| 314 | r = radeon_ib_pool_init(rdev); | ||
| 315 | rdev->accel_working = true; | 312 | rdev->accel_working = true; |
| 316 | if (r) { | ||
| 317 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 318 | rdev->accel_working = false; | ||
| 319 | } | ||
| 320 | |||
| 321 | r = r520_startup(rdev); | 313 | r = r520_startup(rdev); |
| 322 | if (r) { | 314 | if (r) { |
| 323 | /* Somethings want wront with the accel init stop accel */ | 315 | /* Somethings want wront with the accel init stop accel */ |
| 324 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 316 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
| 325 | r100_cp_fini(rdev); | 317 | r100_cp_fini(rdev); |
| 326 | radeon_wb_fini(rdev); | 318 | radeon_wb_fini(rdev); |
| 327 | r100_ib_fini(rdev); | 319 | radeon_ib_pool_fini(rdev); |
| 328 | radeon_irq_kms_fini(rdev); | 320 | radeon_irq_kms_fini(rdev); |
| 329 | rv370_pcie_gart_fini(rdev); | 321 | rv370_pcie_gart_fini(rdev); |
| 330 | radeon_agp_fini(rdev); | 322 | radeon_agp_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index bff627293812..637280f541a3 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
| @@ -709,6 +709,7 @@ void r600_hpd_init(struct radeon_device *rdev) | |||
| 709 | { | 709 | { |
| 710 | struct drm_device *dev = rdev->ddev; | 710 | struct drm_device *dev = rdev->ddev; |
| 711 | struct drm_connector *connector; | 711 | struct drm_connector *connector; |
| 712 | unsigned enable = 0; | ||
| 712 | 713 | ||
| 713 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 714 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 714 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 715 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| @@ -729,28 +730,22 @@ void r600_hpd_init(struct radeon_device *rdev) | |||
| 729 | switch (radeon_connector->hpd.hpd) { | 730 | switch (radeon_connector->hpd.hpd) { |
| 730 | case RADEON_HPD_1: | 731 | case RADEON_HPD_1: |
| 731 | WREG32(DC_HPD1_CONTROL, tmp); | 732 | WREG32(DC_HPD1_CONTROL, tmp); |
| 732 | rdev->irq.hpd[0] = true; | ||
| 733 | break; | 733 | break; |
| 734 | case RADEON_HPD_2: | 734 | case RADEON_HPD_2: |
| 735 | WREG32(DC_HPD2_CONTROL, tmp); | 735 | WREG32(DC_HPD2_CONTROL, tmp); |
| 736 | rdev->irq.hpd[1] = true; | ||
| 737 | break; | 736 | break; |
| 738 | case RADEON_HPD_3: | 737 | case RADEON_HPD_3: |
| 739 | WREG32(DC_HPD3_CONTROL, tmp); | 738 | WREG32(DC_HPD3_CONTROL, tmp); |
| 740 | rdev->irq.hpd[2] = true; | ||
| 741 | break; | 739 | break; |
| 742 | case RADEON_HPD_4: | 740 | case RADEON_HPD_4: |
| 743 | WREG32(DC_HPD4_CONTROL, tmp); | 741 | WREG32(DC_HPD4_CONTROL, tmp); |
| 744 | rdev->irq.hpd[3] = true; | ||
| 745 | break; | 742 | break; |
| 746 | /* DCE 3.2 */ | 743 | /* DCE 3.2 */ |
| 747 | case RADEON_HPD_5: | 744 | case RADEON_HPD_5: |
| 748 | WREG32(DC_HPD5_CONTROL, tmp); | 745 | WREG32(DC_HPD5_CONTROL, tmp); |
| 749 | rdev->irq.hpd[4] = true; | ||
| 750 | break; | 746 | break; |
| 751 | case RADEON_HPD_6: | 747 | case RADEON_HPD_6: |
| 752 | WREG32(DC_HPD6_CONTROL, tmp); | 748 | WREG32(DC_HPD6_CONTROL, tmp); |
| 753 | rdev->irq.hpd[5] = true; | ||
| 754 | break; | 749 | break; |
| 755 | default: | 750 | default: |
| 756 | break; | 751 | break; |
| @@ -759,85 +754,73 @@ void r600_hpd_init(struct radeon_device *rdev) | |||
| 759 | switch (radeon_connector->hpd.hpd) { | 754 | switch (radeon_connector->hpd.hpd) { |
| 760 | case RADEON_HPD_1: | 755 | case RADEON_HPD_1: |
| 761 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN); | 756 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN); |
| 762 | rdev->irq.hpd[0] = true; | ||
| 763 | break; | 757 | break; |
| 764 | case RADEON_HPD_2: | 758 | case RADEON_HPD_2: |
| 765 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, DC_HOT_PLUG_DETECTx_EN); | 759 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, DC_HOT_PLUG_DETECTx_EN); |
| 766 | rdev->irq.hpd[1] = true; | ||
| 767 | break; | 760 | break; |
| 768 | case RADEON_HPD_3: | 761 | case RADEON_HPD_3: |
| 769 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, DC_HOT_PLUG_DETECTx_EN); | 762 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, DC_HOT_PLUG_DETECTx_EN); |
| 770 | rdev->irq.hpd[2] = true; | ||
| 771 | break; | 763 | break; |
| 772 | default: | 764 | default: |
| 773 | break; | 765 | break; |
| 774 | } | 766 | } |
| 775 | } | 767 | } |
| 768 | enable |= 1 << radeon_connector->hpd.hpd; | ||
| 776 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); | 769 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); |
| 777 | } | 770 | } |
| 778 | if (rdev->irq.installed) | 771 | radeon_irq_kms_enable_hpd(rdev, enable); |
| 779 | r600_irq_set(rdev); | ||
| 780 | } | 772 | } |
| 781 | 773 | ||
| 782 | void r600_hpd_fini(struct radeon_device *rdev) | 774 | void r600_hpd_fini(struct radeon_device *rdev) |
| 783 | { | 775 | { |
| 784 | struct drm_device *dev = rdev->ddev; | 776 | struct drm_device *dev = rdev->ddev; |
| 785 | struct drm_connector *connector; | 777 | struct drm_connector *connector; |
| 778 | unsigned disable = 0; | ||
| 786 | 779 | ||
| 787 | if (ASIC_IS_DCE3(rdev)) { | 780 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 788 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 781 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| 789 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 782 | if (ASIC_IS_DCE3(rdev)) { |
| 790 | switch (radeon_connector->hpd.hpd) { | 783 | switch (radeon_connector->hpd.hpd) { |
| 791 | case RADEON_HPD_1: | 784 | case RADEON_HPD_1: |
| 792 | WREG32(DC_HPD1_CONTROL, 0); | 785 | WREG32(DC_HPD1_CONTROL, 0); |
| 793 | rdev->irq.hpd[0] = false; | ||
| 794 | break; | 786 | break; |
| 795 | case RADEON_HPD_2: | 787 | case RADEON_HPD_2: |
| 796 | WREG32(DC_HPD2_CONTROL, 0); | 788 | WREG32(DC_HPD2_CONTROL, 0); |
| 797 | rdev->irq.hpd[1] = false; | ||
| 798 | break; | 789 | break; |
| 799 | case RADEON_HPD_3: | 790 | case RADEON_HPD_3: |
| 800 | WREG32(DC_HPD3_CONTROL, 0); | 791 | WREG32(DC_HPD3_CONTROL, 0); |
| 801 | rdev->irq.hpd[2] = false; | ||
| 802 | break; | 792 | break; |
| 803 | case RADEON_HPD_4: | 793 | case RADEON_HPD_4: |
| 804 | WREG32(DC_HPD4_CONTROL, 0); | 794 | WREG32(DC_HPD4_CONTROL, 0); |
| 805 | rdev->irq.hpd[3] = false; | ||
| 806 | break; | 795 | break; |
| 807 | /* DCE 3.2 */ | 796 | /* DCE 3.2 */ |
| 808 | case RADEON_HPD_5: | 797 | case RADEON_HPD_5: |
| 809 | WREG32(DC_HPD5_CONTROL, 0); | 798 | WREG32(DC_HPD5_CONTROL, 0); |
| 810 | rdev->irq.hpd[4] = false; | ||
| 811 | break; | 799 | break; |
| 812 | case RADEON_HPD_6: | 800 | case RADEON_HPD_6: |
| 813 | WREG32(DC_HPD6_CONTROL, 0); | 801 | WREG32(DC_HPD6_CONTROL, 0); |
| 814 | rdev->irq.hpd[5] = false; | ||
| 815 | break; | 802 | break; |
| 816 | default: | 803 | default: |
| 817 | break; | 804 | break; |
| 818 | } | 805 | } |
| 819 | } | 806 | } else { |
| 820 | } else { | ||
| 821 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 822 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 823 | switch (radeon_connector->hpd.hpd) { | 807 | switch (radeon_connector->hpd.hpd) { |
| 824 | case RADEON_HPD_1: | 808 | case RADEON_HPD_1: |
| 825 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, 0); | 809 | WREG32(DC_HOT_PLUG_DETECT1_CONTROL, 0); |
| 826 | rdev->irq.hpd[0] = false; | ||
| 827 | break; | 810 | break; |
| 828 | case RADEON_HPD_2: | 811 | case RADEON_HPD_2: |
| 829 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, 0); | 812 | WREG32(DC_HOT_PLUG_DETECT2_CONTROL, 0); |
| 830 | rdev->irq.hpd[1] = false; | ||
| 831 | break; | 813 | break; |
| 832 | case RADEON_HPD_3: | 814 | case RADEON_HPD_3: |
| 833 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, 0); | 815 | WREG32(DC_HOT_PLUG_DETECT3_CONTROL, 0); |
| 834 | rdev->irq.hpd[2] = false; | ||
| 835 | break; | 816 | break; |
| 836 | default: | 817 | default: |
| 837 | break; | 818 | break; |
| 838 | } | 819 | } |
| 839 | } | 820 | } |
| 821 | disable |= 1 << radeon_connector->hpd.hpd; | ||
| 840 | } | 822 | } |
| 823 | radeon_irq_kms_disable_hpd(rdev, disable); | ||
| 841 | } | 824 | } |
| 842 | 825 | ||
| 843 | /* | 826 | /* |
| @@ -1306,6 +1289,14 @@ int r600_gpu_soft_reset(struct radeon_device *rdev) | |||
| 1306 | RREG32(R_008014_GRBM_STATUS2)); | 1289 | RREG32(R_008014_GRBM_STATUS2)); |
| 1307 | dev_info(rdev->dev, " R_000E50_SRBM_STATUS=0x%08X\n", | 1290 | dev_info(rdev->dev, " R_000E50_SRBM_STATUS=0x%08X\n", |
| 1308 | RREG32(R_000E50_SRBM_STATUS)); | 1291 | RREG32(R_000E50_SRBM_STATUS)); |
| 1292 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", | ||
| 1293 | RREG32(CP_STALLED_STAT1)); | ||
| 1294 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", | ||
| 1295 | RREG32(CP_STALLED_STAT2)); | ||
| 1296 | dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", | ||
| 1297 | RREG32(CP_BUSY_STAT)); | ||
| 1298 | dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", | ||
| 1299 | RREG32(CP_STAT)); | ||
| 1309 | rv515_mc_stop(rdev, &save); | 1300 | rv515_mc_stop(rdev, &save); |
| 1310 | if (r600_mc_wait_for_idle(rdev)) { | 1301 | if (r600_mc_wait_for_idle(rdev)) { |
| 1311 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); | 1302 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); |
| @@ -1349,6 +1340,14 @@ int r600_gpu_soft_reset(struct radeon_device *rdev) | |||
| 1349 | RREG32(R_008014_GRBM_STATUS2)); | 1340 | RREG32(R_008014_GRBM_STATUS2)); |
| 1350 | dev_info(rdev->dev, " R_000E50_SRBM_STATUS=0x%08X\n", | 1341 | dev_info(rdev->dev, " R_000E50_SRBM_STATUS=0x%08X\n", |
| 1351 | RREG32(R_000E50_SRBM_STATUS)); | 1342 | RREG32(R_000E50_SRBM_STATUS)); |
| 1343 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", | ||
| 1344 | RREG32(CP_STALLED_STAT1)); | ||
| 1345 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", | ||
| 1346 | RREG32(CP_STALLED_STAT2)); | ||
| 1347 | dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", | ||
| 1348 | RREG32(CP_BUSY_STAT)); | ||
| 1349 | dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", | ||
| 1350 | RREG32(CP_STAT)); | ||
| 1352 | rv515_mc_resume(rdev, &save); | 1351 | rv515_mc_resume(rdev, &save); |
| 1353 | return 0; | 1352 | return 0; |
| 1354 | } | 1353 | } |
| @@ -2172,18 +2171,29 @@ int r600_cp_resume(struct radeon_device *rdev) | |||
| 2172 | void r600_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size) | 2171 | void r600_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size) |
| 2173 | { | 2172 | { |
| 2174 | u32 rb_bufsz; | 2173 | u32 rb_bufsz; |
| 2174 | int r; | ||
| 2175 | 2175 | ||
| 2176 | /* Align ring size */ | 2176 | /* Align ring size */ |
| 2177 | rb_bufsz = drm_order(ring_size / 8); | 2177 | rb_bufsz = drm_order(ring_size / 8); |
| 2178 | ring_size = (1 << (rb_bufsz + 1)) * 4; | 2178 | ring_size = (1 << (rb_bufsz + 1)) * 4; |
| 2179 | ring->ring_size = ring_size; | 2179 | ring->ring_size = ring_size; |
| 2180 | ring->align_mask = 16 - 1; | 2180 | ring->align_mask = 16 - 1; |
| 2181 | |||
| 2182 | if (radeon_ring_supports_scratch_reg(rdev, ring)) { | ||
| 2183 | r = radeon_scratch_get(rdev, &ring->rptr_save_reg); | ||
| 2184 | if (r) { | ||
| 2185 | DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r); | ||
| 2186 | ring->rptr_save_reg = 0; | ||
| 2187 | } | ||
| 2188 | } | ||
| 2181 | } | 2189 | } |
| 2182 | 2190 | ||
| 2183 | void r600_cp_fini(struct radeon_device *rdev) | 2191 | void r600_cp_fini(struct radeon_device *rdev) |
| 2184 | { | 2192 | { |
| 2193 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | ||
| 2185 | r600_cp_stop(rdev); | 2194 | r600_cp_stop(rdev); |
| 2186 | radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); | 2195 | radeon_ring_fini(rdev, ring); |
| 2196 | radeon_scratch_free(rdev, ring->rptr_save_reg); | ||
| 2187 | } | 2197 | } |
| 2188 | 2198 | ||
| 2189 | 2199 | ||
| @@ -2206,7 +2216,7 @@ int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 2206 | { | 2216 | { |
| 2207 | uint32_t scratch; | 2217 | uint32_t scratch; |
| 2208 | uint32_t tmp = 0; | 2218 | uint32_t tmp = 0; |
| 2209 | unsigned i, ridx = radeon_ring_index(rdev, ring); | 2219 | unsigned i; |
| 2210 | int r; | 2220 | int r; |
| 2211 | 2221 | ||
| 2212 | r = radeon_scratch_get(rdev, &scratch); | 2222 | r = radeon_scratch_get(rdev, &scratch); |
| @@ -2217,7 +2227,7 @@ int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 2217 | WREG32(scratch, 0xCAFEDEAD); | 2227 | WREG32(scratch, 0xCAFEDEAD); |
| 2218 | r = radeon_ring_lock(rdev, ring, 3); | 2228 | r = radeon_ring_lock(rdev, ring, 3); |
| 2219 | if (r) { | 2229 | if (r) { |
| 2220 | DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n", ridx, r); | 2230 | DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n", ring->idx, r); |
| 2221 | radeon_scratch_free(rdev, scratch); | 2231 | radeon_scratch_free(rdev, scratch); |
| 2222 | return r; | 2232 | return r; |
| 2223 | } | 2233 | } |
| @@ -2232,10 +2242,10 @@ int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 2232 | DRM_UDELAY(1); | 2242 | DRM_UDELAY(1); |
| 2233 | } | 2243 | } |
| 2234 | if (i < rdev->usec_timeout) { | 2244 | if (i < rdev->usec_timeout) { |
| 2235 | DRM_INFO("ring test on %d succeeded in %d usecs\n", ridx, i); | 2245 | DRM_INFO("ring test on %d succeeded in %d usecs\n", ring->idx, i); |
| 2236 | } else { | 2246 | } else { |
| 2237 | DRM_ERROR("radeon: ring %d test failed (scratch(0x%04X)=0x%08X)\n", | 2247 | DRM_ERROR("radeon: ring %d test failed (scratch(0x%04X)=0x%08X)\n", |
| 2238 | ridx, scratch, tmp); | 2248 | ring->idx, scratch, tmp); |
| 2239 | r = -EINVAL; | 2249 | r = -EINVAL; |
| 2240 | } | 2250 | } |
| 2241 | radeon_scratch_free(rdev, scratch); | 2251 | radeon_scratch_free(rdev, scratch); |
| @@ -2309,34 +2319,21 @@ int r600_copy_blit(struct radeon_device *rdev, | |||
| 2309 | uint64_t src_offset, | 2319 | uint64_t src_offset, |
| 2310 | uint64_t dst_offset, | 2320 | uint64_t dst_offset, |
| 2311 | unsigned num_gpu_pages, | 2321 | unsigned num_gpu_pages, |
| 2312 | struct radeon_fence *fence) | 2322 | struct radeon_fence **fence) |
| 2313 | { | 2323 | { |
| 2324 | struct radeon_semaphore *sem = NULL; | ||
| 2314 | struct radeon_sa_bo *vb = NULL; | 2325 | struct radeon_sa_bo *vb = NULL; |
| 2315 | int r; | 2326 | int r; |
| 2316 | 2327 | ||
| 2317 | r = r600_blit_prepare_copy(rdev, num_gpu_pages, &vb); | 2328 | r = r600_blit_prepare_copy(rdev, num_gpu_pages, fence, &vb, &sem); |
| 2318 | if (r) { | 2329 | if (r) { |
| 2319 | return r; | 2330 | return r; |
| 2320 | } | 2331 | } |
| 2321 | r600_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages, vb); | 2332 | r600_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages, vb); |
| 2322 | r600_blit_done_copy(rdev, fence, vb); | 2333 | r600_blit_done_copy(rdev, fence, vb, sem); |
| 2323 | return 0; | 2334 | return 0; |
| 2324 | } | 2335 | } |
| 2325 | 2336 | ||
| 2326 | void r600_blit_suspend(struct radeon_device *rdev) | ||
| 2327 | { | ||
| 2328 | int r; | ||
| 2329 | |||
| 2330 | /* unpin shaders bo */ | ||
| 2331 | if (rdev->r600_blit.shader_obj) { | ||
| 2332 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | ||
| 2333 | if (!r) { | ||
| 2334 | radeon_bo_unpin(rdev->r600_blit.shader_obj); | ||
| 2335 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
| 2336 | } | ||
| 2337 | } | ||
| 2338 | } | ||
| 2339 | |||
| 2340 | int r600_set_surface_reg(struct radeon_device *rdev, int reg, | 2337 | int r600_set_surface_reg(struct radeon_device *rdev, int reg, |
| 2341 | uint32_t tiling_flags, uint32_t pitch, | 2338 | uint32_t tiling_flags, uint32_t pitch, |
| 2342 | uint32_t offset, uint32_t obj_size) | 2339 | uint32_t offset, uint32_t obj_size) |
| @@ -2419,13 +2416,11 @@ int r600_startup(struct radeon_device *rdev) | |||
| 2419 | if (r) | 2416 | if (r) |
| 2420 | return r; | 2417 | return r; |
| 2421 | 2418 | ||
| 2422 | r = radeon_ib_pool_start(rdev); | 2419 | r = radeon_ib_pool_init(rdev); |
| 2423 | if (r) | 2420 | if (r) { |
| 2424 | return r; | 2421 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 2425 | |||
| 2426 | r = radeon_ib_ring_tests(rdev); | ||
| 2427 | if (r) | ||
| 2428 | return r; | 2422 | return r; |
| 2423 | } | ||
| 2429 | 2424 | ||
| 2430 | r = r600_audio_init(rdev); | 2425 | r = r600_audio_init(rdev); |
| 2431 | if (r) { | 2426 | if (r) { |
| @@ -2475,9 +2470,6 @@ int r600_resume(struct radeon_device *rdev) | |||
| 2475 | int r600_suspend(struct radeon_device *rdev) | 2470 | int r600_suspend(struct radeon_device *rdev) |
| 2476 | { | 2471 | { |
| 2477 | r600_audio_fini(rdev); | 2472 | r600_audio_fini(rdev); |
| 2478 | radeon_ib_pool_suspend(rdev); | ||
| 2479 | r600_blit_suspend(rdev); | ||
| 2480 | /* FIXME: we should wait for ring to be empty */ | ||
| 2481 | r600_cp_stop(rdev); | 2473 | r600_cp_stop(rdev); |
| 2482 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; | 2474 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; |
| 2483 | r600_irq_suspend(rdev); | 2475 | r600_irq_suspend(rdev); |
| @@ -2559,20 +2551,14 @@ int r600_init(struct radeon_device *rdev) | |||
| 2559 | if (r) | 2551 | if (r) |
| 2560 | return r; | 2552 | return r; |
| 2561 | 2553 | ||
| 2562 | r = radeon_ib_pool_init(rdev); | ||
| 2563 | rdev->accel_working = true; | 2554 | rdev->accel_working = true; |
| 2564 | if (r) { | ||
| 2565 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 2566 | rdev->accel_working = false; | ||
| 2567 | } | ||
| 2568 | |||
| 2569 | r = r600_startup(rdev); | 2555 | r = r600_startup(rdev); |
| 2570 | if (r) { | 2556 | if (r) { |
| 2571 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | 2557 | dev_err(rdev->dev, "disabling GPU acceleration\n"); |
| 2572 | r600_cp_fini(rdev); | 2558 | r600_cp_fini(rdev); |
| 2573 | r600_irq_fini(rdev); | 2559 | r600_irq_fini(rdev); |
| 2574 | radeon_wb_fini(rdev); | 2560 | radeon_wb_fini(rdev); |
| 2575 | r100_ib_fini(rdev); | 2561 | radeon_ib_pool_fini(rdev); |
| 2576 | radeon_irq_kms_fini(rdev); | 2562 | radeon_irq_kms_fini(rdev); |
| 2577 | r600_pcie_gart_fini(rdev); | 2563 | r600_pcie_gart_fini(rdev); |
| 2578 | rdev->accel_working = false; | 2564 | rdev->accel_working = false; |
| @@ -2588,7 +2574,7 @@ void r600_fini(struct radeon_device *rdev) | |||
| 2588 | r600_cp_fini(rdev); | 2574 | r600_cp_fini(rdev); |
| 2589 | r600_irq_fini(rdev); | 2575 | r600_irq_fini(rdev); |
| 2590 | radeon_wb_fini(rdev); | 2576 | radeon_wb_fini(rdev); |
| 2591 | r100_ib_fini(rdev); | 2577 | radeon_ib_pool_fini(rdev); |
| 2592 | radeon_irq_kms_fini(rdev); | 2578 | radeon_irq_kms_fini(rdev); |
| 2593 | r600_pcie_gart_fini(rdev); | 2579 | r600_pcie_gart_fini(rdev); |
| 2594 | r600_vram_scratch_fini(rdev); | 2580 | r600_vram_scratch_fini(rdev); |
| @@ -2607,9 +2593,24 @@ void r600_fini(struct radeon_device *rdev) | |||
| 2607 | */ | 2593 | */ |
| 2608 | void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) | 2594 | void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) |
| 2609 | { | 2595 | { |
| 2610 | struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; | 2596 | struct radeon_ring *ring = &rdev->ring[ib->ring]; |
| 2597 | u32 next_rptr; | ||
| 2598 | |||
| 2599 | if (ring->rptr_save_reg) { | ||
| 2600 | next_rptr = ring->wptr + 3 + 4; | ||
| 2601 | radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | ||
| 2602 | radeon_ring_write(ring, ((ring->rptr_save_reg - | ||
| 2603 | PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); | ||
| 2604 | radeon_ring_write(ring, next_rptr); | ||
| 2605 | } else if (rdev->wb.enabled) { | ||
| 2606 | next_rptr = ring->wptr + 5 + 4; | ||
| 2607 | radeon_ring_write(ring, PACKET3(PACKET3_MEM_WRITE, 3)); | ||
| 2608 | radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); | ||
| 2609 | radeon_ring_write(ring, (upper_32_bits(ring->next_rptr_gpu_addr) & 0xff) | (1 << 18)); | ||
| 2610 | radeon_ring_write(ring, next_rptr); | ||
| 2611 | radeon_ring_write(ring, 0); | ||
| 2612 | } | ||
| 2611 | 2613 | ||
| 2612 | /* FIXME: implement */ | ||
| 2613 | radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); | 2614 | radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); |
| 2614 | radeon_ring_write(ring, | 2615 | radeon_ring_write(ring, |
| 2615 | #ifdef __BIG_ENDIAN | 2616 | #ifdef __BIG_ENDIAN |
| @@ -2627,7 +2628,6 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 2627 | uint32_t tmp = 0; | 2628 | uint32_t tmp = 0; |
| 2628 | unsigned i; | 2629 | unsigned i; |
| 2629 | int r; | 2630 | int r; |
| 2630 | int ring_index = radeon_ring_index(rdev, ring); | ||
| 2631 | 2631 | ||
| 2632 | r = radeon_scratch_get(rdev, &scratch); | 2632 | r = radeon_scratch_get(rdev, &scratch); |
| 2633 | if (r) { | 2633 | if (r) { |
| @@ -2635,7 +2635,7 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 2635 | return r; | 2635 | return r; |
| 2636 | } | 2636 | } |
| 2637 | WREG32(scratch, 0xCAFEDEAD); | 2637 | WREG32(scratch, 0xCAFEDEAD); |
| 2638 | r = radeon_ib_get(rdev, ring_index, &ib, 256); | 2638 | r = radeon_ib_get(rdev, ring->idx, &ib, 256); |
| 2639 | if (r) { | 2639 | if (r) { |
| 2640 | DRM_ERROR("radeon: failed to get ib (%d).\n", r); | 2640 | DRM_ERROR("radeon: failed to get ib (%d).\n", r); |
| 2641 | return r; | 2641 | return r; |
| @@ -2644,7 +2644,7 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 2644 | ib.ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); | 2644 | ib.ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); |
| 2645 | ib.ptr[2] = 0xDEADBEEF; | 2645 | ib.ptr[2] = 0xDEADBEEF; |
| 2646 | ib.length_dw = 3; | 2646 | ib.length_dw = 3; |
| 2647 | r = radeon_ib_schedule(rdev, &ib); | 2647 | r = radeon_ib_schedule(rdev, &ib, NULL); |
| 2648 | if (r) { | 2648 | if (r) { |
| 2649 | radeon_scratch_free(rdev, scratch); | 2649 | radeon_scratch_free(rdev, scratch); |
| 2650 | radeon_ib_free(rdev, &ib); | 2650 | radeon_ib_free(rdev, &ib); |
| @@ -2857,7 +2857,6 @@ void r600_disable_interrupts(struct radeon_device *rdev) | |||
| 2857 | WREG32(IH_RB_RPTR, 0); | 2857 | WREG32(IH_RB_RPTR, 0); |
| 2858 | WREG32(IH_RB_WPTR, 0); | 2858 | WREG32(IH_RB_WPTR, 0); |
| 2859 | rdev->ih.enabled = false; | 2859 | rdev->ih.enabled = false; |
| 2860 | rdev->ih.wptr = 0; | ||
| 2861 | rdev->ih.rptr = 0; | 2860 | rdev->ih.rptr = 0; |
| 2862 | } | 2861 | } |
| 2863 | 2862 | ||
| @@ -3042,18 +3041,18 @@ int r600_irq_set(struct radeon_device *rdev) | |||
| 3042 | hdmi1 = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; | 3041 | hdmi1 = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; |
| 3043 | } | 3042 | } |
| 3044 | 3043 | ||
| 3045 | if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { | 3044 | if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { |
| 3046 | DRM_DEBUG("r600_irq_set: sw int\n"); | 3045 | DRM_DEBUG("r600_irq_set: sw int\n"); |
| 3047 | cp_int_cntl |= RB_INT_ENABLE; | 3046 | cp_int_cntl |= RB_INT_ENABLE; |
| 3048 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; | 3047 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; |
| 3049 | } | 3048 | } |
| 3050 | if (rdev->irq.crtc_vblank_int[0] || | 3049 | if (rdev->irq.crtc_vblank_int[0] || |
| 3051 | rdev->irq.pflip[0]) { | 3050 | atomic_read(&rdev->irq.pflip[0])) { |
| 3052 | DRM_DEBUG("r600_irq_set: vblank 0\n"); | 3051 | DRM_DEBUG("r600_irq_set: vblank 0\n"); |
| 3053 | mode_int |= D1MODE_VBLANK_INT_MASK; | 3052 | mode_int |= D1MODE_VBLANK_INT_MASK; |
| 3054 | } | 3053 | } |
| 3055 | if (rdev->irq.crtc_vblank_int[1] || | 3054 | if (rdev->irq.crtc_vblank_int[1] || |
| 3056 | rdev->irq.pflip[1]) { | 3055 | atomic_read(&rdev->irq.pflip[1])) { |
| 3057 | DRM_DEBUG("r600_irq_set: vblank 1\n"); | 3056 | DRM_DEBUG("r600_irq_set: vblank 1\n"); |
| 3058 | mode_int |= D2MODE_VBLANK_INT_MASK; | 3057 | mode_int |= D2MODE_VBLANK_INT_MASK; |
| 3059 | } | 3058 | } |
| @@ -3309,7 +3308,6 @@ int r600_irq_process(struct radeon_device *rdev) | |||
| 3309 | u32 rptr; | 3308 | u32 rptr; |
| 3310 | u32 src_id, src_data; | 3309 | u32 src_id, src_data; |
| 3311 | u32 ring_index; | 3310 | u32 ring_index; |
| 3312 | unsigned long flags; | ||
| 3313 | bool queue_hotplug = false; | 3311 | bool queue_hotplug = false; |
| 3314 | bool queue_hdmi = false; | 3312 | bool queue_hdmi = false; |
| 3315 | 3313 | ||
| @@ -3321,24 +3319,21 @@ int r600_irq_process(struct radeon_device *rdev) | |||
| 3321 | RREG32(IH_RB_WPTR); | 3319 | RREG32(IH_RB_WPTR); |
| 3322 | 3320 | ||
| 3323 | wptr = r600_get_ih_wptr(rdev); | 3321 | wptr = r600_get_ih_wptr(rdev); |
| 3324 | rptr = rdev->ih.rptr; | ||
| 3325 | DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); | ||
| 3326 | |||
| 3327 | spin_lock_irqsave(&rdev->ih.lock, flags); | ||
| 3328 | 3322 | ||
| 3329 | if (rptr == wptr) { | 3323 | restart_ih: |
| 3330 | spin_unlock_irqrestore(&rdev->ih.lock, flags); | 3324 | /* is somebody else already processing irqs? */ |
| 3325 | if (atomic_xchg(&rdev->ih.lock, 1)) | ||
| 3331 | return IRQ_NONE; | 3326 | return IRQ_NONE; |
| 3332 | } | ||
| 3333 | 3327 | ||
| 3334 | restart_ih: | 3328 | rptr = rdev->ih.rptr; |
| 3329 | DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); | ||
| 3330 | |||
| 3335 | /* Order reading of wptr vs. reading of IH ring data */ | 3331 | /* Order reading of wptr vs. reading of IH ring data */ |
| 3336 | rmb(); | 3332 | rmb(); |
| 3337 | 3333 | ||
| 3338 | /* display interrupts */ | 3334 | /* display interrupts */ |
| 3339 | r600_irq_ack(rdev); | 3335 | r600_irq_ack(rdev); |
| 3340 | 3336 | ||
| 3341 | rdev->ih.wptr = wptr; | ||
| 3342 | while (rptr != wptr) { | 3337 | while (rptr != wptr) { |
| 3343 | /* wptr/rptr are in bytes! */ | 3338 | /* wptr/rptr are in bytes! */ |
| 3344 | ring_index = rptr / 4; | 3339 | ring_index = rptr / 4; |
| @@ -3355,7 +3350,7 @@ restart_ih: | |||
| 3355 | rdev->pm.vblank_sync = true; | 3350 | rdev->pm.vblank_sync = true; |
| 3356 | wake_up(&rdev->irq.vblank_queue); | 3351 | wake_up(&rdev->irq.vblank_queue); |
| 3357 | } | 3352 | } |
| 3358 | if (rdev->irq.pflip[0]) | 3353 | if (atomic_read(&rdev->irq.pflip[0])) |
| 3359 | radeon_crtc_handle_flip(rdev, 0); | 3354 | radeon_crtc_handle_flip(rdev, 0); |
| 3360 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; | 3355 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; |
| 3361 | DRM_DEBUG("IH: D1 vblank\n"); | 3356 | DRM_DEBUG("IH: D1 vblank\n"); |
| @@ -3381,7 +3376,7 @@ restart_ih: | |||
| 3381 | rdev->pm.vblank_sync = true; | 3376 | rdev->pm.vblank_sync = true; |
| 3382 | wake_up(&rdev->irq.vblank_queue); | 3377 | wake_up(&rdev->irq.vblank_queue); |
| 3383 | } | 3378 | } |
| 3384 | if (rdev->irq.pflip[1]) | 3379 | if (atomic_read(&rdev->irq.pflip[1])) |
| 3385 | radeon_crtc_handle_flip(rdev, 1); | 3380 | radeon_crtc_handle_flip(rdev, 1); |
| 3386 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; | 3381 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; |
| 3387 | DRM_DEBUG("IH: D2 vblank\n"); | 3382 | DRM_DEBUG("IH: D2 vblank\n"); |
| @@ -3480,7 +3475,6 @@ restart_ih: | |||
| 3480 | break; | 3475 | break; |
| 3481 | case 233: /* GUI IDLE */ | 3476 | case 233: /* GUI IDLE */ |
| 3482 | DRM_DEBUG("IH: GUI idle\n"); | 3477 | DRM_DEBUG("IH: GUI idle\n"); |
| 3483 | rdev->pm.gui_idle = true; | ||
| 3484 | wake_up(&rdev->irq.idle_queue); | 3478 | wake_up(&rdev->irq.idle_queue); |
| 3485 | break; | 3479 | break; |
| 3486 | default: | 3480 | default: |
| @@ -3492,17 +3486,19 @@ restart_ih: | |||
| 3492 | rptr += 16; | 3486 | rptr += 16; |
| 3493 | rptr &= rdev->ih.ptr_mask; | 3487 | rptr &= rdev->ih.ptr_mask; |
| 3494 | } | 3488 | } |
| 3495 | /* make sure wptr hasn't changed while processing */ | ||
| 3496 | wptr = r600_get_ih_wptr(rdev); | ||
| 3497 | if (wptr != rdev->ih.wptr) | ||
| 3498 | goto restart_ih; | ||
| 3499 | if (queue_hotplug) | 3489 | if (queue_hotplug) |
| 3500 | schedule_work(&rdev->hotplug_work); | 3490 | schedule_work(&rdev->hotplug_work); |
| 3501 | if (queue_hdmi) | 3491 | if (queue_hdmi) |
| 3502 | schedule_work(&rdev->audio_work); | 3492 | schedule_work(&rdev->audio_work); |
| 3503 | rdev->ih.rptr = rptr; | 3493 | rdev->ih.rptr = rptr; |
| 3504 | WREG32(IH_RB_RPTR, rdev->ih.rptr); | 3494 | WREG32(IH_RB_RPTR, rdev->ih.rptr); |
| 3505 | spin_unlock_irqrestore(&rdev->ih.lock, flags); | 3495 | atomic_set(&rdev->ih.lock, 0); |
| 3496 | |||
| 3497 | /* make sure wptr hasn't changed while processing */ | ||
| 3498 | wptr = r600_get_ih_wptr(rdev); | ||
| 3499 | if (wptr != rptr) | ||
| 3500 | goto restart_ih; | ||
| 3501 | |||
| 3506 | return IRQ_HANDLED; | 3502 | return IRQ_HANDLED; |
| 3507 | } | 3503 | } |
| 3508 | 3504 | ||
| @@ -3685,6 +3681,8 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev) | |||
| 3685 | { | 3681 | { |
| 3686 | u32 link_width_cntl, lanes, speed_cntl, training_cntl, tmp; | 3682 | u32 link_width_cntl, lanes, speed_cntl, training_cntl, tmp; |
| 3687 | u16 link_cntl2; | 3683 | u16 link_cntl2; |
| 3684 | u32 mask; | ||
| 3685 | int ret; | ||
| 3688 | 3686 | ||
| 3689 | if (radeon_pcie_gen2 == 0) | 3687 | if (radeon_pcie_gen2 == 0) |
| 3690 | return; | 3688 | return; |
| @@ -3703,6 +3701,15 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev) | |||
| 3703 | if (rdev->family <= CHIP_R600) | 3701 | if (rdev->family <= CHIP_R600) |
| 3704 | return; | 3702 | return; |
| 3705 | 3703 | ||
| 3704 | ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); | ||
| 3705 | if (ret != 0) | ||
| 3706 | return; | ||
| 3707 | |||
| 3708 | if (!(mask & DRM_PCIE_SPEED_50)) | ||
| 3709 | return; | ||
| 3710 | |||
| 3711 | DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); | ||
| 3712 | |||
| 3706 | /* 55 nm r6xx asics */ | 3713 | /* 55 nm r6xx asics */ |
| 3707 | if ((rdev->family == CHIP_RV670) || | 3714 | if ((rdev->family == CHIP_RV670) || |
| 3708 | (rdev->family == CHIP_RV620) || | 3715 | (rdev->family == CHIP_RV620) || |
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index 03b6e0d3d503..2bef8549ddfe 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c | |||
| @@ -512,7 +512,8 @@ int r600_blit_init(struct radeon_device *rdev) | |||
| 512 | rdev->r600_blit.primitives.draw_auto = draw_auto; | 512 | rdev->r600_blit.primitives.draw_auto = draw_auto; |
| 513 | rdev->r600_blit.primitives.set_default_state = set_default_state; | 513 | rdev->r600_blit.primitives.set_default_state = set_default_state; |
| 514 | 514 | ||
| 515 | rdev->r600_blit.ring_size_common = 40; /* shaders + def state */ | 515 | rdev->r600_blit.ring_size_common = 8; /* sync semaphore */ |
| 516 | rdev->r600_blit.ring_size_common += 40; /* shaders + def state */ | ||
| 516 | rdev->r600_blit.ring_size_common += 5; /* done copy */ | 517 | rdev->r600_blit.ring_size_common += 5; /* done copy */ |
| 517 | rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */ | 518 | rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */ |
| 518 | 519 | ||
| @@ -523,10 +524,6 @@ int r600_blit_init(struct radeon_device *rdev) | |||
| 523 | 524 | ||
| 524 | rdev->r600_blit.max_dim = 8192; | 525 | rdev->r600_blit.max_dim = 8192; |
| 525 | 526 | ||
| 526 | /* pin copy shader into vram if already initialized */ | ||
| 527 | if (rdev->r600_blit.shader_obj) | ||
| 528 | goto done; | ||
| 529 | |||
| 530 | rdev->r600_blit.state_offset = 0; | 527 | rdev->r600_blit.state_offset = 0; |
| 531 | 528 | ||
| 532 | if (rdev->family >= CHIP_RV770) | 529 | if (rdev->family >= CHIP_RV770) |
| @@ -551,11 +548,26 @@ int r600_blit_init(struct radeon_device *rdev) | |||
| 551 | obj_size += r6xx_ps_size * 4; | 548 | obj_size += r6xx_ps_size * 4; |
| 552 | obj_size = ALIGN(obj_size, 256); | 549 | obj_size = ALIGN(obj_size, 256); |
| 553 | 550 | ||
| 554 | r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, | 551 | /* pin copy shader into vram if not already initialized */ |
| 555 | NULL, &rdev->r600_blit.shader_obj); | 552 | if (rdev->r600_blit.shader_obj == NULL) { |
| 556 | if (r) { | 553 | r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, |
| 557 | DRM_ERROR("r600 failed to allocate shader\n"); | 554 | RADEON_GEM_DOMAIN_VRAM, |
| 558 | return r; | 555 | NULL, &rdev->r600_blit.shader_obj); |
| 556 | if (r) { | ||
| 557 | DRM_ERROR("r600 failed to allocate shader\n"); | ||
| 558 | return r; | ||
| 559 | } | ||
| 560 | |||
| 561 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | ||
| 562 | if (unlikely(r != 0)) | ||
| 563 | return r; | ||
| 564 | r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, | ||
| 565 | &rdev->r600_blit.shader_gpu_addr); | ||
| 566 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
| 567 | if (r) { | ||
| 568 | dev_err(rdev->dev, "(%d) pin blit object failed\n", r); | ||
| 569 | return r; | ||
| 570 | } | ||
| 559 | } | 571 | } |
| 560 | 572 | ||
| 561 | DRM_DEBUG("r6xx blit allocated bo %08x vs %08x ps %08x\n", | 573 | DRM_DEBUG("r6xx blit allocated bo %08x vs %08x ps %08x\n", |
| @@ -586,17 +598,6 @@ int r600_blit_init(struct radeon_device *rdev) | |||
| 586 | radeon_bo_kunmap(rdev->r600_blit.shader_obj); | 598 | radeon_bo_kunmap(rdev->r600_blit.shader_obj); |
| 587 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | 599 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); |
| 588 | 600 | ||
| 589 | done: | ||
| 590 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | ||
| 591 | if (unlikely(r != 0)) | ||
| 592 | return r; | ||
| 593 | r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, | ||
| 594 | &rdev->r600_blit.shader_gpu_addr); | ||
| 595 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
| 596 | if (r) { | ||
| 597 | dev_err(rdev->dev, "(%d) pin blit object failed\n", r); | ||
| 598 | return r; | ||
| 599 | } | ||
| 600 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); | 601 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); |
| 601 | return 0; | 602 | return 0; |
| 602 | } | 603 | } |
| @@ -666,7 +667,8 @@ static unsigned r600_blit_create_rect(unsigned num_gpu_pages, | |||
| 666 | 667 | ||
| 667 | 668 | ||
| 668 | int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages, | 669 | int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages, |
| 669 | struct radeon_sa_bo **vb) | 670 | struct radeon_fence **fence, struct radeon_sa_bo **vb, |
| 671 | struct radeon_semaphore **sem) | ||
| 670 | { | 672 | { |
| 671 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | 673 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
| 672 | int r; | 674 | int r; |
| @@ -689,34 +691,50 @@ int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages, | |||
| 689 | return r; | 691 | return r; |
| 690 | } | 692 | } |
| 691 | 693 | ||
| 694 | r = radeon_semaphore_create(rdev, sem); | ||
| 695 | if (r) { | ||
| 696 | radeon_sa_bo_free(rdev, vb, NULL); | ||
| 697 | return r; | ||
| 698 | } | ||
| 699 | |||
| 692 | /* calculate number of loops correctly */ | 700 | /* calculate number of loops correctly */ |
| 693 | ring_size = num_loops * dwords_per_loop; | 701 | ring_size = num_loops * dwords_per_loop; |
| 694 | ring_size += rdev->r600_blit.ring_size_common; | 702 | ring_size += rdev->r600_blit.ring_size_common; |
| 695 | r = radeon_ring_lock(rdev, ring, ring_size); | 703 | r = radeon_ring_lock(rdev, ring, ring_size); |
| 696 | if (r) { | 704 | if (r) { |
| 697 | radeon_sa_bo_free(rdev, vb, NULL); | 705 | radeon_sa_bo_free(rdev, vb, NULL); |
| 706 | radeon_semaphore_free(rdev, sem, NULL); | ||
| 698 | return r; | 707 | return r; |
| 699 | } | 708 | } |
| 700 | 709 | ||
| 710 | if (radeon_fence_need_sync(*fence, RADEON_RING_TYPE_GFX_INDEX)) { | ||
| 711 | radeon_semaphore_sync_rings(rdev, *sem, (*fence)->ring, | ||
| 712 | RADEON_RING_TYPE_GFX_INDEX); | ||
| 713 | radeon_fence_note_sync(*fence, RADEON_RING_TYPE_GFX_INDEX); | ||
| 714 | } else { | ||
| 715 | radeon_semaphore_free(rdev, sem, NULL); | ||
| 716 | } | ||
| 717 | |||
| 701 | rdev->r600_blit.primitives.set_default_state(rdev); | 718 | rdev->r600_blit.primitives.set_default_state(rdev); |
| 702 | rdev->r600_blit.primitives.set_shaders(rdev); | 719 | rdev->r600_blit.primitives.set_shaders(rdev); |
| 703 | return 0; | 720 | return 0; |
| 704 | } | 721 | } |
| 705 | 722 | ||
| 706 | void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence, | 723 | void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence **fence, |
| 707 | struct radeon_sa_bo *vb) | 724 | struct radeon_sa_bo *vb, struct radeon_semaphore *sem) |
| 708 | { | 725 | { |
| 709 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | 726 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
| 710 | int r; | 727 | int r; |
| 711 | 728 | ||
| 712 | r = radeon_fence_emit(rdev, fence); | 729 | r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX); |
| 713 | if (r) { | 730 | if (r) { |
| 714 | radeon_ring_unlock_undo(rdev, ring); | 731 | radeon_ring_unlock_undo(rdev, ring); |
| 715 | return; | 732 | return; |
| 716 | } | 733 | } |
| 717 | 734 | ||
| 718 | radeon_ring_unlock_commit(rdev, ring); | 735 | radeon_ring_unlock_commit(rdev, ring); |
| 719 | radeon_sa_bo_free(rdev, &vb, fence); | 736 | radeon_sa_bo_free(rdev, &vb, *fence); |
| 737 | radeon_semaphore_free(rdev, &sem, *fence); | ||
| 720 | } | 738 | } |
| 721 | 739 | ||
| 722 | void r600_kms_blit_copy(struct radeon_device *rdev, | 740 | void r600_kms_blit_copy(struct radeon_device *rdev, |
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 82a0a4c919c0..e3558c3ef24a 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c | |||
| @@ -519,8 +519,7 @@ void r600_hdmi_enable(struct drm_encoder *encoder) | |||
| 519 | 519 | ||
| 520 | if (rdev->irq.installed) { | 520 | if (rdev->irq.installed) { |
| 521 | /* if irq is available use it */ | 521 | /* if irq is available use it */ |
| 522 | rdev->irq.afmt[dig->afmt->id] = true; | 522 | radeon_irq_kms_enable_afmt(rdev, dig->afmt->id); |
| 523 | radeon_irq_set(rdev); | ||
| 524 | } | 523 | } |
| 525 | 524 | ||
| 526 | dig->afmt->enabled = true; | 525 | dig->afmt->enabled = true; |
| @@ -556,8 +555,7 @@ void r600_hdmi_disable(struct drm_encoder *encoder) | |||
| 556 | offset, radeon_encoder->encoder_id); | 555 | offset, radeon_encoder->encoder_id); |
| 557 | 556 | ||
| 558 | /* disable irq */ | 557 | /* disable irq */ |
| 559 | rdev->irq.afmt[dig->afmt->id] = false; | 558 | radeon_irq_kms_disable_afmt(rdev, dig->afmt->id); |
| 560 | radeon_irq_set(rdev); | ||
| 561 | 559 | ||
| 562 | /* Older chipsets not handled by AtomBIOS */ | 560 | /* Older chipsets not handled by AtomBIOS */ |
| 563 | if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) { | 561 | if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) { |
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 025fd5b6c08c..4b116ae75fc2 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h | |||
| @@ -153,6 +153,9 @@ | |||
| 153 | 153 | ||
| 154 | #define CONFIG_MEMSIZE 0x5428 | 154 | #define CONFIG_MEMSIZE 0x5428 |
| 155 | #define CONFIG_CNTL 0x5424 | 155 | #define CONFIG_CNTL 0x5424 |
| 156 | #define CP_STALLED_STAT1 0x8674 | ||
| 157 | #define CP_STALLED_STAT2 0x8678 | ||
| 158 | #define CP_BUSY_STAT 0x867C | ||
| 156 | #define CP_STAT 0x8680 | 159 | #define CP_STAT 0x8680 |
| 157 | #define CP_COHER_BASE 0x85F8 | 160 | #define CP_COHER_BASE 0x85F8 |
| 158 | #define CP_DEBUG 0xC1FC | 161 | #define CP_DEBUG 0xC1FC |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index fefcca55c1eb..5431af292408 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -113,7 +113,6 @@ extern int radeon_lockup_timeout; | |||
| 113 | 113 | ||
| 114 | /* fence seq are set to this number when signaled */ | 114 | /* fence seq are set to this number when signaled */ |
| 115 | #define RADEON_FENCE_SIGNALED_SEQ 0LL | 115 | #define RADEON_FENCE_SIGNALED_SEQ 0LL |
| 116 | #define RADEON_FENCE_NOTEMITED_SEQ (~0LL) | ||
| 117 | 116 | ||
| 118 | /* internal ring indices */ | 117 | /* internal ring indices */ |
| 119 | /* r1xx+ has gfx CP ring */ | 118 | /* r1xx+ has gfx CP ring */ |
| @@ -160,48 +159,6 @@ static inline int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len) | |||
| 160 | #endif | 159 | #endif |
| 161 | bool radeon_get_bios(struct radeon_device *rdev); | 160 | bool radeon_get_bios(struct radeon_device *rdev); |
| 162 | 161 | ||
| 163 | |||
| 164 | /* | ||
| 165 | * Mutex which allows recursive locking from the same process. | ||
| 166 | */ | ||
| 167 | struct radeon_mutex { | ||
| 168 | struct mutex mutex; | ||
| 169 | struct task_struct *owner; | ||
| 170 | int level; | ||
| 171 | }; | ||
| 172 | |||
| 173 | static inline void radeon_mutex_init(struct radeon_mutex *mutex) | ||
| 174 | { | ||
| 175 | mutex_init(&mutex->mutex); | ||
| 176 | mutex->owner = NULL; | ||
| 177 | mutex->level = 0; | ||
| 178 | } | ||
| 179 | |||
| 180 | static inline void radeon_mutex_lock(struct radeon_mutex *mutex) | ||
| 181 | { | ||
| 182 | if (mutex_trylock(&mutex->mutex)) { | ||
| 183 | /* The mutex was unlocked before, so it's ours now */ | ||
| 184 | mutex->owner = current; | ||
| 185 | } else if (mutex->owner != current) { | ||
| 186 | /* Another process locked the mutex, take it */ | ||
| 187 | mutex_lock(&mutex->mutex); | ||
| 188 | mutex->owner = current; | ||
| 189 | } | ||
| 190 | /* Otherwise the mutex was already locked by this process */ | ||
| 191 | |||
| 192 | mutex->level++; | ||
| 193 | } | ||
| 194 | |||
| 195 | static inline void radeon_mutex_unlock(struct radeon_mutex *mutex) | ||
| 196 | { | ||
| 197 | if (--mutex->level > 0) | ||
| 198 | return; | ||
| 199 | |||
| 200 | mutex->owner = NULL; | ||
| 201 | mutex_unlock(&mutex->mutex); | ||
| 202 | } | ||
| 203 | |||
| 204 | |||
| 205 | /* | 162 | /* |
| 206 | * Dummy page | 163 | * Dummy page |
| 207 | */ | 164 | */ |
| @@ -258,8 +215,8 @@ struct radeon_fence_driver { | |||
| 258 | uint32_t scratch_reg; | 215 | uint32_t scratch_reg; |
| 259 | uint64_t gpu_addr; | 216 | uint64_t gpu_addr; |
| 260 | volatile uint32_t *cpu_addr; | 217 | volatile uint32_t *cpu_addr; |
| 261 | /* seq is protected by ring emission lock */ | 218 | /* sync_seq is protected by ring emission lock */ |
| 262 | uint64_t seq; | 219 | uint64_t sync_seq[RADEON_NUM_RINGS]; |
| 263 | atomic64_t last_seq; | 220 | atomic64_t last_seq; |
| 264 | unsigned long last_activity; | 221 | unsigned long last_activity; |
| 265 | bool initialized; | 222 | bool initialized; |
| @@ -277,19 +234,39 @@ struct radeon_fence { | |||
| 277 | int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); | 234 | int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); |
| 278 | int radeon_fence_driver_init(struct radeon_device *rdev); | 235 | int radeon_fence_driver_init(struct radeon_device *rdev); |
| 279 | void radeon_fence_driver_fini(struct radeon_device *rdev); | 236 | void radeon_fence_driver_fini(struct radeon_device *rdev); |
| 280 | int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence **fence, int ring); | 237 | int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence **fence, int ring); |
| 281 | int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence); | ||
| 282 | void radeon_fence_process(struct radeon_device *rdev, int ring); | 238 | void radeon_fence_process(struct radeon_device *rdev, int ring); |
| 283 | bool radeon_fence_signaled(struct radeon_fence *fence); | 239 | bool radeon_fence_signaled(struct radeon_fence *fence); |
| 284 | int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); | 240 | int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); |
| 285 | int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring); | 241 | int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring); |
| 286 | int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring); | 242 | void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring); |
| 287 | int radeon_fence_wait_any(struct radeon_device *rdev, | 243 | int radeon_fence_wait_any(struct radeon_device *rdev, |
| 288 | struct radeon_fence **fences, | 244 | struct radeon_fence **fences, |
| 289 | bool intr); | 245 | bool intr); |
| 290 | struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence); | 246 | struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence); |
| 291 | void radeon_fence_unref(struct radeon_fence **fence); | 247 | void radeon_fence_unref(struct radeon_fence **fence); |
| 292 | unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring); | 248 | unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring); |
| 249 | bool radeon_fence_need_sync(struct radeon_fence *fence, int ring); | ||
| 250 | void radeon_fence_note_sync(struct radeon_fence *fence, int ring); | ||
| 251 | static inline struct radeon_fence *radeon_fence_later(struct radeon_fence *a, | ||
| 252 | struct radeon_fence *b) | ||
| 253 | { | ||
| 254 | if (!a) { | ||
| 255 | return b; | ||
| 256 | } | ||
| 257 | |||
| 258 | if (!b) { | ||
| 259 | return a; | ||
| 260 | } | ||
| 261 | |||
| 262 | BUG_ON(a->ring != b->ring); | ||
| 263 | |||
| 264 | if (a->seq > b->seq) { | ||
| 265 | return a; | ||
| 266 | } else { | ||
| 267 | return b; | ||
| 268 | } | ||
| 269 | } | ||
| 293 | 270 | ||
| 294 | /* | 271 | /* |
| 295 | * Tiling registers | 272 | * Tiling registers |
| @@ -385,7 +362,7 @@ struct radeon_bo_list { | |||
| 385 | * alignment). | 362 | * alignment). |
| 386 | */ | 363 | */ |
| 387 | struct radeon_sa_manager { | 364 | struct radeon_sa_manager { |
| 388 | spinlock_t lock; | 365 | wait_queue_head_t wq; |
| 389 | struct radeon_bo *bo; | 366 | struct radeon_bo *bo; |
| 390 | struct list_head *hole; | 367 | struct list_head *hole; |
| 391 | struct list_head flist[RADEON_NUM_RINGS]; | 368 | struct list_head flist[RADEON_NUM_RINGS]; |
| @@ -451,10 +428,9 @@ void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, | |||
| 451 | struct radeon_semaphore *semaphore); | 428 | struct radeon_semaphore *semaphore); |
| 452 | int radeon_semaphore_sync_rings(struct radeon_device *rdev, | 429 | int radeon_semaphore_sync_rings(struct radeon_device *rdev, |
| 453 | struct radeon_semaphore *semaphore, | 430 | struct radeon_semaphore *semaphore, |
| 454 | bool sync_to[RADEON_NUM_RINGS], | 431 | int signaler, int waiter); |
| 455 | int dst_ring); | ||
| 456 | void radeon_semaphore_free(struct radeon_device *rdev, | 432 | void radeon_semaphore_free(struct radeon_device *rdev, |
| 457 | struct radeon_semaphore *semaphore, | 433 | struct radeon_semaphore **semaphore, |
| 458 | struct radeon_fence *fence); | 434 | struct radeon_fence *fence); |
| 459 | 435 | ||
| 460 | /* | 436 | /* |
| @@ -597,21 +573,18 @@ union radeon_irq_stat_regs { | |||
| 597 | #define RADEON_MAX_AFMT_BLOCKS 6 | 573 | #define RADEON_MAX_AFMT_BLOCKS 6 |
| 598 | 574 | ||
| 599 | struct radeon_irq { | 575 | struct radeon_irq { |
| 600 | bool installed; | 576 | bool installed; |
| 601 | bool sw_int[RADEON_NUM_RINGS]; | 577 | spinlock_t lock; |
| 602 | bool crtc_vblank_int[RADEON_MAX_CRTCS]; | 578 | atomic_t ring_int[RADEON_NUM_RINGS]; |
| 603 | bool pflip[RADEON_MAX_CRTCS]; | 579 | bool crtc_vblank_int[RADEON_MAX_CRTCS]; |
| 604 | wait_queue_head_t vblank_queue; | 580 | atomic_t pflip[RADEON_MAX_CRTCS]; |
| 605 | bool hpd[RADEON_MAX_HPD_PINS]; | 581 | wait_queue_head_t vblank_queue; |
| 606 | bool gui_idle; | 582 | bool hpd[RADEON_MAX_HPD_PINS]; |
| 607 | bool gui_idle_acked; | 583 | bool gui_idle; |
| 608 | wait_queue_head_t idle_queue; | 584 | bool gui_idle_acked; |
| 609 | bool afmt[RADEON_MAX_AFMT_BLOCKS]; | 585 | wait_queue_head_t idle_queue; |
| 610 | spinlock_t sw_lock; | 586 | bool afmt[RADEON_MAX_AFMT_BLOCKS]; |
| 611 | int sw_refcount[RADEON_NUM_RINGS]; | 587 | union radeon_irq_stat_regs stat_regs; |
| 612 | union radeon_irq_stat_regs stat_regs; | ||
| 613 | spinlock_t pflip_lock[RADEON_MAX_CRTCS]; | ||
| 614 | int pflip_refcount[RADEON_MAX_CRTCS]; | ||
| 615 | }; | 588 | }; |
| 616 | 589 | ||
| 617 | int radeon_irq_kms_init(struct radeon_device *rdev); | 590 | int radeon_irq_kms_init(struct radeon_device *rdev); |
| @@ -620,6 +593,11 @@ void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring); | |||
| 620 | void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring); | 593 | void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring); |
| 621 | void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc); | 594 | void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc); |
| 622 | void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc); | 595 | void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc); |
| 596 | void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block); | ||
| 597 | void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block); | ||
| 598 | void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask); | ||
| 599 | void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask); | ||
| 600 | int radeon_irq_kms_wait_gui_idle(struct radeon_device *rdev); | ||
| 623 | 601 | ||
| 624 | /* | 602 | /* |
| 625 | * CP & rings. | 603 | * CP & rings. |
| @@ -630,9 +608,11 @@ struct radeon_ib { | |||
| 630 | uint32_t length_dw; | 608 | uint32_t length_dw; |
| 631 | uint64_t gpu_addr; | 609 | uint64_t gpu_addr; |
| 632 | uint32_t *ptr; | 610 | uint32_t *ptr; |
| 611 | int ring; | ||
| 633 | struct radeon_fence *fence; | 612 | struct radeon_fence *fence; |
| 634 | unsigned vm_id; | 613 | unsigned vm_id; |
| 635 | bool is_const_ib; | 614 | bool is_const_ib; |
| 615 | struct radeon_fence *sync_to[RADEON_NUM_RINGS]; | ||
| 636 | struct radeon_semaphore *semaphore; | 616 | struct radeon_semaphore *semaphore; |
| 637 | }; | 617 | }; |
| 638 | 618 | ||
| @@ -642,6 +622,9 @@ struct radeon_ring { | |||
| 642 | unsigned rptr; | 622 | unsigned rptr; |
| 643 | unsigned rptr_offs; | 623 | unsigned rptr_offs; |
| 644 | unsigned rptr_reg; | 624 | unsigned rptr_reg; |
| 625 | unsigned rptr_save_reg; | ||
| 626 | u64 next_rptr_gpu_addr; | ||
| 627 | volatile u32 *next_rptr_cpu_addr; | ||
| 645 | unsigned wptr; | 628 | unsigned wptr; |
| 646 | unsigned wptr_old; | 629 | unsigned wptr_old; |
| 647 | unsigned wptr_reg; | 630 | unsigned wptr_reg; |
| @@ -657,6 +640,7 @@ struct radeon_ring { | |||
| 657 | u32 ptr_reg_shift; | 640 | u32 ptr_reg_shift; |
| 658 | u32 ptr_reg_mask; | 641 | u32 ptr_reg_mask; |
| 659 | u32 nop; | 642 | u32 nop; |
| 643 | u32 idx; | ||
| 660 | }; | 644 | }; |
| 661 | 645 | ||
| 662 | /* | 646 | /* |
| @@ -690,6 +674,7 @@ struct radeon_vm_funcs { | |||
| 690 | }; | 674 | }; |
| 691 | 675 | ||
| 692 | struct radeon_vm_manager { | 676 | struct radeon_vm_manager { |
| 677 | struct mutex lock; | ||
| 693 | struct list_head lru_vm; | 678 | struct list_head lru_vm; |
| 694 | uint32_t use_bitmap; | 679 | uint32_t use_bitmap; |
| 695 | struct radeon_sa_manager sa_manager; | 680 | struct radeon_sa_manager sa_manager; |
| @@ -718,13 +703,10 @@ struct r600_ih { | |||
| 718 | struct radeon_bo *ring_obj; | 703 | struct radeon_bo *ring_obj; |
| 719 | volatile uint32_t *ring; | 704 | volatile uint32_t *ring; |
| 720 | unsigned rptr; | 705 | unsigned rptr; |
| 721 | unsigned rptr_offs; | ||
| 722 | unsigned wptr; | ||
| 723 | unsigned wptr_old; | ||
| 724 | unsigned ring_size; | 706 | unsigned ring_size; |
| 725 | uint64_t gpu_addr; | 707 | uint64_t gpu_addr; |
| 726 | uint32_t ptr_mask; | 708 | uint32_t ptr_mask; |
| 727 | spinlock_t lock; | 709 | atomic_t lock; |
| 728 | bool enabled; | 710 | bool enabled; |
| 729 | }; | 711 | }; |
| 730 | 712 | ||
| @@ -757,8 +739,6 @@ struct r600_blit { | |||
| 757 | u32 state_len; | 739 | u32 state_len; |
| 758 | }; | 740 | }; |
| 759 | 741 | ||
| 760 | void r600_blit_suspend(struct radeon_device *rdev); | ||
| 761 | |||
| 762 | /* | 742 | /* |
| 763 | * SI RLC stuff | 743 | * SI RLC stuff |
| 764 | */ | 744 | */ |
| @@ -774,14 +754,14 @@ struct si_rlc { | |||
| 774 | int radeon_ib_get(struct radeon_device *rdev, int ring, | 754 | int radeon_ib_get(struct radeon_device *rdev, int ring, |
| 775 | struct radeon_ib *ib, unsigned size); | 755 | struct radeon_ib *ib, unsigned size); |
| 776 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib); | 756 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib); |
| 777 | int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib); | 757 | int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, |
| 758 | struct radeon_ib *const_ib); | ||
| 778 | int radeon_ib_pool_init(struct radeon_device *rdev); | 759 | int radeon_ib_pool_init(struct radeon_device *rdev); |
| 779 | void radeon_ib_pool_fini(struct radeon_device *rdev); | 760 | void radeon_ib_pool_fini(struct radeon_device *rdev); |
| 780 | int radeon_ib_pool_start(struct radeon_device *rdev); | ||
| 781 | int radeon_ib_pool_suspend(struct radeon_device *rdev); | ||
| 782 | int radeon_ib_ring_tests(struct radeon_device *rdev); | 761 | int radeon_ib_ring_tests(struct radeon_device *rdev); |
| 783 | /* Ring access between begin & end cannot sleep */ | 762 | /* Ring access between begin & end cannot sleep */ |
| 784 | int radeon_ring_index(struct radeon_device *rdev, struct radeon_ring *cp); | 763 | bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev, |
| 764 | struct radeon_ring *ring); | ||
| 785 | void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *cp); | 765 | void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *cp); |
| 786 | int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw); | 766 | int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw); |
| 787 | int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw); | 767 | int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw); |
| @@ -793,6 +773,10 @@ int radeon_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); | |||
| 793 | void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring); | 773 | void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring); |
| 794 | void radeon_ring_lockup_update(struct radeon_ring *ring); | 774 | void radeon_ring_lockup_update(struct radeon_ring *ring); |
| 795 | bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring); | 775 | bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring); |
| 776 | unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring, | ||
| 777 | uint32_t **data); | ||
| 778 | int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring, | ||
| 779 | unsigned size, uint32_t *data); | ||
| 796 | int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ring_size, | 780 | int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ring_size, |
| 797 | unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, | 781 | unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, |
| 798 | u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop); | 782 | u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop); |
| @@ -891,6 +875,7 @@ struct radeon_wb { | |||
| 891 | }; | 875 | }; |
| 892 | 876 | ||
| 893 | #define RADEON_WB_SCRATCH_OFFSET 0 | 877 | #define RADEON_WB_SCRATCH_OFFSET 0 |
| 878 | #define RADEON_WB_RING0_NEXT_RPTR 256 | ||
| 894 | #define RADEON_WB_CP_RPTR_OFFSET 1024 | 879 | #define RADEON_WB_CP_RPTR_OFFSET 1024 |
| 895 | #define RADEON_WB_CP1_RPTR_OFFSET 1280 | 880 | #define RADEON_WB_CP1_RPTR_OFFSET 1280 |
| 896 | #define RADEON_WB_CP2_RPTR_OFFSET 1536 | 881 | #define RADEON_WB_CP2_RPTR_OFFSET 1536 |
| @@ -1039,11 +1024,12 @@ struct radeon_power_state { | |||
| 1039 | 1024 | ||
| 1040 | struct radeon_pm { | 1025 | struct radeon_pm { |
| 1041 | struct mutex mutex; | 1026 | struct mutex mutex; |
| 1027 | /* write locked while reprogramming mclk */ | ||
| 1028 | struct rw_semaphore mclk_lock; | ||
| 1042 | u32 active_crtcs; | 1029 | u32 active_crtcs; |
| 1043 | int active_crtc_count; | 1030 | int active_crtc_count; |
| 1044 | int req_vblank; | 1031 | int req_vblank; |
| 1045 | bool vblank_sync; | 1032 | bool vblank_sync; |
| 1046 | bool gui_idle; | ||
| 1047 | fixed20_12 max_bandwidth; | 1033 | fixed20_12 max_bandwidth; |
| 1048 | fixed20_12 igp_sideport_mclk; | 1034 | fixed20_12 igp_sideport_mclk; |
| 1049 | fixed20_12 igp_system_mclk; | 1035 | fixed20_12 igp_system_mclk; |
| @@ -1192,20 +1178,20 @@ struct radeon_asic { | |||
| 1192 | uint64_t src_offset, | 1178 | uint64_t src_offset, |
| 1193 | uint64_t dst_offset, | 1179 | uint64_t dst_offset, |
| 1194 | unsigned num_gpu_pages, | 1180 | unsigned num_gpu_pages, |
| 1195 | struct radeon_fence *fence); | 1181 | struct radeon_fence **fence); |
| 1196 | u32 blit_ring_index; | 1182 | u32 blit_ring_index; |
| 1197 | int (*dma)(struct radeon_device *rdev, | 1183 | int (*dma)(struct radeon_device *rdev, |
| 1198 | uint64_t src_offset, | 1184 | uint64_t src_offset, |
| 1199 | uint64_t dst_offset, | 1185 | uint64_t dst_offset, |
| 1200 | unsigned num_gpu_pages, | 1186 | unsigned num_gpu_pages, |
| 1201 | struct radeon_fence *fence); | 1187 | struct radeon_fence **fence); |
| 1202 | u32 dma_ring_index; | 1188 | u32 dma_ring_index; |
| 1203 | /* method used for bo copy */ | 1189 | /* method used for bo copy */ |
| 1204 | int (*copy)(struct radeon_device *rdev, | 1190 | int (*copy)(struct radeon_device *rdev, |
| 1205 | uint64_t src_offset, | 1191 | uint64_t src_offset, |
| 1206 | uint64_t dst_offset, | 1192 | uint64_t dst_offset, |
| 1207 | unsigned num_gpu_pages, | 1193 | unsigned num_gpu_pages, |
| 1208 | struct radeon_fence *fence); | 1194 | struct radeon_fence **fence); |
| 1209 | /* ring used for bo copies */ | 1195 | /* ring used for bo copies */ |
| 1210 | u32 copy_ring_index; | 1196 | u32 copy_ring_index; |
| 1211 | } copy; | 1197 | } copy; |
| @@ -1467,6 +1453,7 @@ struct radeon_device { | |||
| 1467 | struct device *dev; | 1453 | struct device *dev; |
| 1468 | struct drm_device *ddev; | 1454 | struct drm_device *ddev; |
| 1469 | struct pci_dev *pdev; | 1455 | struct pci_dev *pdev; |
| 1456 | struct rw_semaphore exclusive_lock; | ||
| 1470 | /* ASIC */ | 1457 | /* ASIC */ |
| 1471 | union radeon_asic_config config; | 1458 | union radeon_asic_config config; |
| 1472 | enum radeon_family family; | 1459 | enum radeon_family family; |
| @@ -1512,7 +1499,6 @@ struct radeon_device { | |||
| 1512 | struct radeon_gem gem; | 1499 | struct radeon_gem gem; |
| 1513 | struct radeon_pm pm; | 1500 | struct radeon_pm pm; |
| 1514 | uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH]; | 1501 | uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH]; |
| 1515 | struct radeon_mutex cs_mutex; | ||
| 1516 | struct radeon_wb wb; | 1502 | struct radeon_wb wb; |
| 1517 | struct radeon_dummy_page dummy_page; | 1503 | struct radeon_dummy_page dummy_page; |
| 1518 | bool shutdown; | 1504 | bool shutdown; |
| @@ -1534,7 +1520,6 @@ struct radeon_device { | |||
| 1534 | struct work_struct audio_work; | 1520 | struct work_struct audio_work; |
| 1535 | int num_crtc; /* number of crtcs */ | 1521 | int num_crtc; /* number of crtcs */ |
| 1536 | struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */ | 1522 | struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */ |
| 1537 | struct mutex vram_mutex; | ||
| 1538 | bool audio_enabled; | 1523 | bool audio_enabled; |
| 1539 | struct r600_audio audio_status; /* audio stuff */ | 1524 | struct r600_audio audio_status; /* audio stuff */ |
| 1540 | struct notifier_block acpi_nb; | 1525 | struct notifier_block acpi_nb; |
| @@ -1785,8 +1770,6 @@ extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size | |||
| 1785 | */ | 1770 | */ |
| 1786 | int radeon_vm_manager_init(struct radeon_device *rdev); | 1771 | int radeon_vm_manager_init(struct radeon_device *rdev); |
| 1787 | void radeon_vm_manager_fini(struct radeon_device *rdev); | 1772 | void radeon_vm_manager_fini(struct radeon_device *rdev); |
| 1788 | int radeon_vm_manager_start(struct radeon_device *rdev); | ||
| 1789 | int radeon_vm_manager_suspend(struct radeon_device *rdev); | ||
| 1790 | int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm); | 1773 | int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm); |
| 1791 | void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm); | 1774 | void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm); |
| 1792 | int radeon_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm); | 1775 | int radeon_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm); |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index f533df5f7d50..973417c4b014 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c | |||
| @@ -40,6 +40,16 @@ | |||
| 40 | /* | 40 | /* |
| 41 | * Registers accessors functions. | 41 | * Registers accessors functions. |
| 42 | */ | 42 | */ |
| 43 | /** | ||
| 44 | * radeon_invalid_rreg - dummy reg read function | ||
| 45 | * | ||
| 46 | * @rdev: radeon device pointer | ||
| 47 | * @reg: offset of register | ||
| 48 | * | ||
| 49 | * Dummy register read function. Used for register blocks | ||
| 50 | * that certain asics don't have (all asics). | ||
| 51 | * Returns the value in the register. | ||
| 52 | */ | ||
| 43 | static uint32_t radeon_invalid_rreg(struct radeon_device *rdev, uint32_t reg) | 53 | static uint32_t radeon_invalid_rreg(struct radeon_device *rdev, uint32_t reg) |
| 44 | { | 54 | { |
| 45 | DRM_ERROR("Invalid callback to read register 0x%04X\n", reg); | 55 | DRM_ERROR("Invalid callback to read register 0x%04X\n", reg); |
| @@ -47,6 +57,16 @@ static uint32_t radeon_invalid_rreg(struct radeon_device *rdev, uint32_t reg) | |||
| 47 | return 0; | 57 | return 0; |
| 48 | } | 58 | } |
| 49 | 59 | ||
| 60 | /** | ||
| 61 | * radeon_invalid_wreg - dummy reg write function | ||
| 62 | * | ||
| 63 | * @rdev: radeon device pointer | ||
| 64 | * @reg: offset of register | ||
| 65 | * @v: value to write to the register | ||
| 66 | * | ||
| 67 | * Dummy register read function. Used for register blocks | ||
| 68 | * that certain asics don't have (all asics). | ||
| 69 | */ | ||
| 50 | static void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) | 70 | static void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) |
| 51 | { | 71 | { |
| 52 | DRM_ERROR("Invalid callback to write register 0x%04X with 0x%08X\n", | 72 | DRM_ERROR("Invalid callback to write register 0x%04X with 0x%08X\n", |
| @@ -54,6 +74,14 @@ static void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32 | |||
| 54 | BUG_ON(1); | 74 | BUG_ON(1); |
| 55 | } | 75 | } |
| 56 | 76 | ||
| 77 | /** | ||
| 78 | * radeon_register_accessor_init - sets up the register accessor callbacks | ||
| 79 | * | ||
| 80 | * @rdev: radeon device pointer | ||
| 81 | * | ||
| 82 | * Sets up the register accessor callbacks for various register | ||
| 83 | * apertures. Not all asics have all apertures (all asics). | ||
| 84 | */ | ||
| 57 | static void radeon_register_accessor_init(struct radeon_device *rdev) | 85 | static void radeon_register_accessor_init(struct radeon_device *rdev) |
| 58 | { | 86 | { |
| 59 | rdev->mc_rreg = &radeon_invalid_rreg; | 87 | rdev->mc_rreg = &radeon_invalid_rreg; |
| @@ -102,6 +130,14 @@ static void radeon_register_accessor_init(struct radeon_device *rdev) | |||
| 102 | 130 | ||
| 103 | 131 | ||
| 104 | /* helper to disable agp */ | 132 | /* helper to disable agp */ |
| 133 | /** | ||
| 134 | * radeon_agp_disable - AGP disable helper function | ||
| 135 | * | ||
| 136 | * @rdev: radeon device pointer | ||
| 137 | * | ||
| 138 | * Removes AGP flags and changes the gart callbacks on AGP | ||
| 139 | * cards when using the internal gart rather than AGP (all asics). | ||
| 140 | */ | ||
| 105 | void radeon_agp_disable(struct radeon_device *rdev) | 141 | void radeon_agp_disable(struct radeon_device *rdev) |
| 106 | { | 142 | { |
| 107 | rdev->flags &= ~RADEON_IS_AGP; | 143 | rdev->flags &= ~RADEON_IS_AGP; |
| @@ -1608,6 +1644,16 @@ static struct radeon_asic si_asic = { | |||
| 1608 | }, | 1644 | }, |
| 1609 | }; | 1645 | }; |
| 1610 | 1646 | ||
| 1647 | /** | ||
| 1648 | * radeon_asic_init - register asic specific callbacks | ||
| 1649 | * | ||
| 1650 | * @rdev: radeon device pointer | ||
| 1651 | * | ||
| 1652 | * Registers the appropriate asic specific callbacks for each | ||
| 1653 | * chip family. Also sets other asics specific info like the number | ||
| 1654 | * of crtcs and the register aperture accessors (all asics). | ||
| 1655 | * Returns 0 for success. | ||
| 1656 | */ | ||
| 1611 | int radeon_asic_init(struct radeon_device *rdev) | 1657 | int radeon_asic_init(struct radeon_device *rdev) |
| 1612 | { | 1658 | { |
| 1613 | radeon_register_accessor_init(rdev); | 1659 | radeon_register_accessor_init(rdev); |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index e76a941ef14e..f4af24310438 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
| @@ -79,7 +79,7 @@ int r100_copy_blit(struct radeon_device *rdev, | |||
| 79 | uint64_t src_offset, | 79 | uint64_t src_offset, |
| 80 | uint64_t dst_offset, | 80 | uint64_t dst_offset, |
| 81 | unsigned num_gpu_pages, | 81 | unsigned num_gpu_pages, |
| 82 | struct radeon_fence *fence); | 82 | struct radeon_fence **fence); |
| 83 | int r100_set_surface_reg(struct radeon_device *rdev, int reg, | 83 | int r100_set_surface_reg(struct radeon_device *rdev, int reg, |
| 84 | uint32_t tiling_flags, uint32_t pitch, | 84 | uint32_t tiling_flags, uint32_t pitch, |
| 85 | uint32_t offset, uint32_t obj_size); | 85 | uint32_t offset, uint32_t obj_size); |
| @@ -103,7 +103,6 @@ int r100_pci_gart_enable(struct radeon_device *rdev); | |||
| 103 | void r100_pci_gart_disable(struct radeon_device *rdev); | 103 | void r100_pci_gart_disable(struct radeon_device *rdev); |
| 104 | int r100_debugfs_mc_info_init(struct radeon_device *rdev); | 104 | int r100_debugfs_mc_info_init(struct radeon_device *rdev); |
| 105 | int r100_gui_wait_for_idle(struct radeon_device *rdev); | 105 | int r100_gui_wait_for_idle(struct radeon_device *rdev); |
| 106 | void r100_ib_fini(struct radeon_device *rdev); | ||
| 107 | int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); | 106 | int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); |
| 108 | void r100_irq_disable(struct radeon_device *rdev); | 107 | void r100_irq_disable(struct radeon_device *rdev); |
| 109 | void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save); | 108 | void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save); |
| @@ -144,7 +143,7 @@ extern int r200_copy_dma(struct radeon_device *rdev, | |||
| 144 | uint64_t src_offset, | 143 | uint64_t src_offset, |
| 145 | uint64_t dst_offset, | 144 | uint64_t dst_offset, |
| 146 | unsigned num_gpu_pages, | 145 | unsigned num_gpu_pages, |
| 147 | struct radeon_fence *fence); | 146 | struct radeon_fence **fence); |
| 148 | void r200_set_safe_registers(struct radeon_device *rdev); | 147 | void r200_set_safe_registers(struct radeon_device *rdev); |
| 149 | 148 | ||
| 150 | /* | 149 | /* |
| @@ -318,7 +317,7 @@ void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); | |||
| 318 | int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); | 317 | int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); |
| 319 | int r600_copy_blit(struct radeon_device *rdev, | 318 | int r600_copy_blit(struct radeon_device *rdev, |
| 320 | uint64_t src_offset, uint64_t dst_offset, | 319 | uint64_t src_offset, uint64_t dst_offset, |
| 321 | unsigned num_gpu_pages, struct radeon_fence *fence); | 320 | unsigned num_gpu_pages, struct radeon_fence **fence); |
| 322 | void r600_hpd_init(struct radeon_device *rdev); | 321 | void r600_hpd_init(struct radeon_device *rdev); |
| 323 | void r600_hpd_fini(struct radeon_device *rdev); | 322 | void r600_hpd_fini(struct radeon_device *rdev); |
| 324 | bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); | 323 | bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); |
| @@ -363,9 +362,10 @@ int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); | |||
| 363 | void r600_hdmi_update_audio_settings(struct drm_encoder *encoder); | 362 | void r600_hdmi_update_audio_settings(struct drm_encoder *encoder); |
| 364 | /* r600 blit */ | 363 | /* r600 blit */ |
| 365 | int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages, | 364 | int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages, |
| 366 | struct radeon_sa_bo **vb); | 365 | struct radeon_fence **fence, struct radeon_sa_bo **vb, |
| 367 | void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence, | 366 | struct radeon_semaphore **sem); |
| 368 | struct radeon_sa_bo *vb); | 367 | void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence **fence, |
| 368 | struct radeon_sa_bo *vb, struct radeon_semaphore *sem); | ||
| 369 | void r600_kms_blit_copy(struct radeon_device *rdev, | 369 | void r600_kms_blit_copy(struct radeon_device *rdev, |
| 370 | u64 src_gpu_addr, u64 dst_gpu_addr, | 370 | u64 src_gpu_addr, u64 dst_gpu_addr, |
| 371 | unsigned num_gpu_pages, | 371 | unsigned num_gpu_pages, |
diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c index 364f5b1a04b9..bedda9caadd9 100644 --- a/drivers/gpu/drm/radeon/radeon_benchmark.c +++ b/drivers/gpu/drm/radeon/radeon_benchmark.c | |||
| @@ -45,20 +45,14 @@ static int radeon_benchmark_do_move(struct radeon_device *rdev, unsigned size, | |||
| 45 | for (i = 0; i < n; i++) { | 45 | for (i = 0; i < n; i++) { |
| 46 | switch (flag) { | 46 | switch (flag) { |
| 47 | case RADEON_BENCHMARK_COPY_DMA: | 47 | case RADEON_BENCHMARK_COPY_DMA: |
| 48 | r = radeon_fence_create(rdev, &fence, radeon_copy_dma_ring_index(rdev)); | ||
| 49 | if (r) | ||
| 50 | return r; | ||
| 51 | r = radeon_copy_dma(rdev, saddr, daddr, | 48 | r = radeon_copy_dma(rdev, saddr, daddr, |
| 52 | size / RADEON_GPU_PAGE_SIZE, | 49 | size / RADEON_GPU_PAGE_SIZE, |
| 53 | fence); | 50 | &fence); |
| 54 | break; | 51 | break; |
| 55 | case RADEON_BENCHMARK_COPY_BLIT: | 52 | case RADEON_BENCHMARK_COPY_BLIT: |
| 56 | r = radeon_fence_create(rdev, &fence, radeon_copy_blit_ring_index(rdev)); | ||
| 57 | if (r) | ||
| 58 | return r; | ||
| 59 | r = radeon_copy_blit(rdev, saddr, daddr, | 53 | r = radeon_copy_blit(rdev, saddr, daddr, |
| 60 | size / RADEON_GPU_PAGE_SIZE, | 54 | size / RADEON_GPU_PAGE_SIZE, |
| 61 | fence); | 55 | &fence); |
| 62 | break; | 56 | break; |
| 63 | default: | 57 | default: |
| 64 | DRM_ERROR("Unknown copy method\n"); | 58 | DRM_ERROR("Unknown copy method\n"); |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 2914c5761cfc..895e628b60f8 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
| @@ -64,14 +64,33 @@ void radeon_connector_hotplug(struct drm_connector *connector) | |||
| 64 | 64 | ||
| 65 | /* just deal with DP (not eDP) here. */ | 65 | /* just deal with DP (not eDP) here. */ |
| 66 | if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { | 66 | if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { |
| 67 | int saved_dpms = connector->dpms; | 67 | struct radeon_connector_atom_dig *dig_connector = |
| 68 | 68 | radeon_connector->con_priv; | |
| 69 | /* Only turn off the display it it's physically disconnected */ | 69 | |
| 70 | if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) | 70 | /* if existing sink type was not DP no need to retrain */ |
| 71 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); | 71 | if (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_DISPLAYPORT) |
| 72 | else if (radeon_dp_needs_link_train(radeon_connector)) | 72 | return; |
| 73 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); | 73 | |
| 74 | connector->dpms = saved_dpms; | 74 | /* first get sink type as it may be reset after (un)plug */ |
| 75 | dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector); | ||
| 76 | /* don't do anything if sink is not display port, i.e., | ||
| 77 | * passive dp->(dvi|hdmi) adaptor | ||
| 78 | */ | ||
| 79 | if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { | ||
| 80 | int saved_dpms = connector->dpms; | ||
| 81 | /* Only turn off the display if it's physically disconnected */ | ||
| 82 | if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { | ||
| 83 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); | ||
| 84 | } else if (radeon_dp_needs_link_train(radeon_connector)) { | ||
| 85 | /* set it to OFF so that drm_helper_connector_dpms() | ||
| 86 | * won't return immediately since the current state | ||
| 87 | * is ON at this point. | ||
| 88 | */ | ||
| 89 | connector->dpms = DRM_MODE_DPMS_OFF; | ||
| 90 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); | ||
| 91 | } | ||
| 92 | connector->dpms = saved_dpms; | ||
| 93 | } | ||
| 75 | } | 94 | } |
| 76 | } | 95 | } |
| 77 | 96 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 142f89462aa4..8a4c49ef0cc4 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c | |||
| @@ -115,36 +115,20 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority | |||
| 115 | return 0; | 115 | return 0; |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | static int radeon_cs_sync_rings(struct radeon_cs_parser *p) | 118 | static void radeon_cs_sync_rings(struct radeon_cs_parser *p) |
| 119 | { | 119 | { |
| 120 | bool sync_to_ring[RADEON_NUM_RINGS] = { }; | 120 | int i; |
| 121 | bool need_sync = false; | ||
| 122 | int i, r; | ||
| 123 | 121 | ||
| 124 | for (i = 0; i < p->nrelocs; i++) { | 122 | for (i = 0; i < p->nrelocs; i++) { |
| 125 | struct radeon_fence *fence; | 123 | struct radeon_fence *a, *b; |
| 126 | 124 | ||
| 127 | if (!p->relocs[i].robj || !p->relocs[i].robj->tbo.sync_obj) | 125 | if (!p->relocs[i].robj || !p->relocs[i].robj->tbo.sync_obj) |
| 128 | continue; | 126 | continue; |
| 129 | 127 | ||
| 130 | fence = p->relocs[i].robj->tbo.sync_obj; | 128 | a = p->relocs[i].robj->tbo.sync_obj; |
| 131 | if (fence->ring != p->ring && !radeon_fence_signaled(fence)) { | 129 | b = p->ib.sync_to[a->ring]; |
| 132 | sync_to_ring[fence->ring] = true; | 130 | p->ib.sync_to[a->ring] = radeon_fence_later(a, b); |
| 133 | need_sync = true; | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | if (!need_sync) { | ||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | |||
| 141 | r = radeon_semaphore_create(p->rdev, &p->ib.semaphore); | ||
| 142 | if (r) { | ||
| 143 | return r; | ||
| 144 | } | 131 | } |
| 145 | |||
| 146 | return radeon_semaphore_sync_rings(p->rdev, p->ib.semaphore, | ||
| 147 | sync_to_ring, p->ring); | ||
| 148 | } | 132 | } |
| 149 | 133 | ||
| 150 | /* XXX: note that this is called from the legacy UMS CS ioctl as well */ | 134 | /* XXX: note that this is called from the legacy UMS CS ioctl as well */ |
| @@ -368,16 +352,13 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev, | |||
| 368 | DRM_ERROR("Invalid command stream !\n"); | 352 | DRM_ERROR("Invalid command stream !\n"); |
| 369 | return r; | 353 | return r; |
| 370 | } | 354 | } |
| 371 | r = radeon_cs_sync_rings(parser); | 355 | radeon_cs_sync_rings(parser); |
| 372 | if (r) { | ||
| 373 | DRM_ERROR("Failed to synchronize rings !\n"); | ||
| 374 | } | ||
| 375 | parser->ib.vm_id = 0; | 356 | parser->ib.vm_id = 0; |
| 376 | r = radeon_ib_schedule(rdev, &parser->ib); | 357 | r = radeon_ib_schedule(rdev, &parser->ib, NULL); |
| 377 | if (r) { | 358 | if (r) { |
| 378 | DRM_ERROR("Failed to schedule IB !\n"); | 359 | DRM_ERROR("Failed to schedule IB !\n"); |
| 379 | } | 360 | } |
| 380 | return 0; | 361 | return r; |
| 381 | } | 362 | } |
| 382 | 363 | ||
| 383 | static int radeon_bo_vm_update_pte(struct radeon_cs_parser *parser, | 364 | static int radeon_bo_vm_update_pte(struct radeon_cs_parser *parser, |
| @@ -459,6 +440,7 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, | |||
| 459 | return r; | 440 | return r; |
| 460 | } | 441 | } |
| 461 | 442 | ||
| 443 | mutex_lock(&rdev->vm_manager.lock); | ||
| 462 | mutex_lock(&vm->mutex); | 444 | mutex_lock(&vm->mutex); |
| 463 | r = radeon_vm_bind(rdev, vm); | 445 | r = radeon_vm_bind(rdev, vm); |
| 464 | if (r) { | 446 | if (r) { |
| @@ -468,30 +450,26 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, | |||
| 468 | if (r) { | 450 | if (r) { |
| 469 | goto out; | 451 | goto out; |
| 470 | } | 452 | } |
| 471 | r = radeon_cs_sync_rings(parser); | 453 | radeon_cs_sync_rings(parser); |
| 472 | if (r) { | 454 | |
| 473 | DRM_ERROR("Failed to synchronize rings !\n"); | 455 | parser->ib.vm_id = vm->id; |
| 474 | } | 456 | /* ib pool is bind at 0 in virtual address space, |
| 457 | * so gpu_addr is the offset inside the pool bo | ||
| 458 | */ | ||
| 459 | parser->ib.gpu_addr = parser->ib.sa_bo->soffset; | ||
| 475 | 460 | ||
| 476 | if ((rdev->family >= CHIP_TAHITI) && | 461 | if ((rdev->family >= CHIP_TAHITI) && |
| 477 | (parser->chunk_const_ib_idx != -1)) { | 462 | (parser->chunk_const_ib_idx != -1)) { |
| 478 | parser->const_ib.vm_id = vm->id; | 463 | parser->const_ib.vm_id = vm->id; |
| 479 | /* ib pool is bind at 0 in virtual address space to gpu_addr is the | 464 | /* ib pool is bind at 0 in virtual address space, |
| 480 | * offset inside the pool bo | 465 | * so gpu_addr is the offset inside the pool bo |
| 481 | */ | 466 | */ |
| 482 | parser->const_ib.gpu_addr = parser->const_ib.sa_bo->soffset; | 467 | parser->const_ib.gpu_addr = parser->const_ib.sa_bo->soffset; |
| 483 | r = radeon_ib_schedule(rdev, &parser->const_ib); | 468 | r = radeon_ib_schedule(rdev, &parser->ib, &parser->const_ib); |
| 484 | if (r) | 469 | } else { |
| 485 | goto out; | 470 | r = radeon_ib_schedule(rdev, &parser->ib, NULL); |
| 486 | } | 471 | } |
| 487 | 472 | ||
| 488 | parser->ib.vm_id = vm->id; | ||
| 489 | /* ib pool is bind at 0 in virtual address space to gpu_addr is the | ||
| 490 | * offset inside the pool bo | ||
| 491 | */ | ||
| 492 | parser->ib.gpu_addr = parser->ib.sa_bo->soffset; | ||
| 493 | parser->ib.is_const_ib = false; | ||
| 494 | r = radeon_ib_schedule(rdev, &parser->ib); | ||
| 495 | out: | 473 | out: |
| 496 | if (!r) { | 474 | if (!r) { |
| 497 | if (vm->fence) { | 475 | if (vm->fence) { |
| @@ -499,7 +477,8 @@ out: | |||
| 499 | } | 477 | } |
| 500 | vm->fence = radeon_fence_ref(parser->ib.fence); | 478 | vm->fence = radeon_fence_ref(parser->ib.fence); |
| 501 | } | 479 | } |
| 502 | mutex_unlock(&fpriv->vm.mutex); | 480 | mutex_unlock(&vm->mutex); |
| 481 | mutex_unlock(&rdev->vm_manager.lock); | ||
| 503 | return r; | 482 | return r; |
| 504 | } | 483 | } |
| 505 | 484 | ||
| @@ -519,9 +498,9 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
| 519 | struct radeon_cs_parser parser; | 498 | struct radeon_cs_parser parser; |
| 520 | int r; | 499 | int r; |
| 521 | 500 | ||
| 522 | radeon_mutex_lock(&rdev->cs_mutex); | 501 | down_read(&rdev->exclusive_lock); |
| 523 | if (!rdev->accel_working) { | 502 | if (!rdev->accel_working) { |
| 524 | radeon_mutex_unlock(&rdev->cs_mutex); | 503 | up_read(&rdev->exclusive_lock); |
| 525 | return -EBUSY; | 504 | return -EBUSY; |
| 526 | } | 505 | } |
| 527 | /* initialize parser */ | 506 | /* initialize parser */ |
| @@ -534,8 +513,8 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
| 534 | if (r) { | 513 | if (r) { |
| 535 | DRM_ERROR("Failed to initialize parser !\n"); | 514 | DRM_ERROR("Failed to initialize parser !\n"); |
| 536 | radeon_cs_parser_fini(&parser, r); | 515 | radeon_cs_parser_fini(&parser, r); |
| 516 | up_read(&rdev->exclusive_lock); | ||
| 537 | r = radeon_cs_handle_lockup(rdev, r); | 517 | r = radeon_cs_handle_lockup(rdev, r); |
| 538 | radeon_mutex_unlock(&rdev->cs_mutex); | ||
| 539 | return r; | 518 | return r; |
| 540 | } | 519 | } |
| 541 | r = radeon_cs_parser_relocs(&parser); | 520 | r = radeon_cs_parser_relocs(&parser); |
| @@ -543,8 +522,8 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
| 543 | if (r != -ERESTARTSYS) | 522 | if (r != -ERESTARTSYS) |
| 544 | DRM_ERROR("Failed to parse relocation %d!\n", r); | 523 | DRM_ERROR("Failed to parse relocation %d!\n", r); |
| 545 | radeon_cs_parser_fini(&parser, r); | 524 | radeon_cs_parser_fini(&parser, r); |
| 525 | up_read(&rdev->exclusive_lock); | ||
| 546 | r = radeon_cs_handle_lockup(rdev, r); | 526 | r = radeon_cs_handle_lockup(rdev, r); |
| 547 | radeon_mutex_unlock(&rdev->cs_mutex); | ||
| 548 | return r; | 527 | return r; |
| 549 | } | 528 | } |
| 550 | r = radeon_cs_ib_chunk(rdev, &parser); | 529 | r = radeon_cs_ib_chunk(rdev, &parser); |
| @@ -557,8 +536,8 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
| 557 | } | 536 | } |
| 558 | out: | 537 | out: |
| 559 | radeon_cs_parser_fini(&parser, r); | 538 | radeon_cs_parser_fini(&parser, r); |
| 539 | up_read(&rdev->exclusive_lock); | ||
| 560 | r = radeon_cs_handle_lockup(rdev, r); | 540 | r = radeon_cs_handle_lockup(rdev, r); |
| 561 | radeon_mutex_unlock(&rdev->cs_mutex); | ||
| 562 | return r; | 541 | return r; |
| 563 | } | 542 | } |
| 564 | 543 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 42acc6449dd6..711e95ad39bf 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c | |||
| @@ -262,8 +262,14 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, | |||
| 262 | if (!(cursor_end & 0x7f)) | 262 | if (!(cursor_end & 0x7f)) |
| 263 | w--; | 263 | w--; |
| 264 | } | 264 | } |
| 265 | if (w <= 0) | 265 | if (w <= 0) { |
| 266 | w = 1; | 266 | w = 1; |
| 267 | cursor_end = x - xorigin + w; | ||
| 268 | if (!(cursor_end & 0x7f)) { | ||
| 269 | x--; | ||
| 270 | WARN_ON_ONCE(x < 0); | ||
| 271 | } | ||
| 272 | } | ||
| 267 | } | 273 | } |
| 268 | } | 274 | } |
| 269 | 275 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 066c98b888a5..742af8244e89 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
| @@ -96,8 +96,12 @@ static const char radeon_family_name[][16] = { | |||
| 96 | "LAST", | 96 | "LAST", |
| 97 | }; | 97 | }; |
| 98 | 98 | ||
| 99 | /* | 99 | /** |
| 100 | * Clear GPU surface registers. | 100 | * radeon_surface_init - Clear GPU surface registers. |
| 101 | * | ||
| 102 | * @rdev: radeon_device pointer | ||
| 103 | * | ||
| 104 | * Clear GPU surface registers (r1xx-r5xx). | ||
| 101 | */ | 105 | */ |
| 102 | void radeon_surface_init(struct radeon_device *rdev) | 106 | void radeon_surface_init(struct radeon_device *rdev) |
| 103 | { | 107 | { |
| @@ -119,6 +123,13 @@ void radeon_surface_init(struct radeon_device *rdev) | |||
| 119 | /* | 123 | /* |
| 120 | * GPU scratch registers helpers function. | 124 | * GPU scratch registers helpers function. |
| 121 | */ | 125 | */ |
| 126 | /** | ||
| 127 | * radeon_scratch_init - Init scratch register driver information. | ||
| 128 | * | ||
| 129 | * @rdev: radeon_device pointer | ||
| 130 | * | ||
| 131 | * Init CP scratch register driver information (r1xx-r5xx) | ||
| 132 | */ | ||
| 122 | void radeon_scratch_init(struct radeon_device *rdev) | 133 | void radeon_scratch_init(struct radeon_device *rdev) |
| 123 | { | 134 | { |
| 124 | int i; | 135 | int i; |
| @@ -136,6 +147,15 @@ void radeon_scratch_init(struct radeon_device *rdev) | |||
| 136 | } | 147 | } |
| 137 | } | 148 | } |
| 138 | 149 | ||
| 150 | /** | ||
| 151 | * radeon_scratch_get - Allocate a scratch register | ||
| 152 | * | ||
| 153 | * @rdev: radeon_device pointer | ||
| 154 | * @reg: scratch register mmio offset | ||
| 155 | * | ||
| 156 | * Allocate a CP scratch register for use by the driver (all asics). | ||
| 157 | * Returns 0 on success or -EINVAL on failure. | ||
| 158 | */ | ||
| 139 | int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg) | 159 | int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg) |
| 140 | { | 160 | { |
| 141 | int i; | 161 | int i; |
| @@ -150,6 +170,14 @@ int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg) | |||
| 150 | return -EINVAL; | 170 | return -EINVAL; |
| 151 | } | 171 | } |
| 152 | 172 | ||
| 173 | /** | ||
| 174 | * radeon_scratch_free - Free a scratch register | ||
| 175 | * | ||
| 176 | * @rdev: radeon_device pointer | ||
| 177 | * @reg: scratch register mmio offset | ||
| 178 | * | ||
| 179 | * Free a CP scratch register allocated for use by the driver (all asics) | ||
| 180 | */ | ||
| 153 | void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) | 181 | void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) |
| 154 | { | 182 | { |
| 155 | int i; | 183 | int i; |
| @@ -162,6 +190,20 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) | |||
| 162 | } | 190 | } |
| 163 | } | 191 | } |
| 164 | 192 | ||
| 193 | /* | ||
| 194 | * radeon_wb_*() | ||
| 195 | * Writeback is the the method by which the the GPU updates special pages | ||
| 196 | * in memory with the status of certain GPU events (fences, ring pointers, | ||
| 197 | * etc.). | ||
| 198 | */ | ||
| 199 | |||
| 200 | /** | ||
| 201 | * radeon_wb_disable - Disable Writeback | ||
| 202 | * | ||
| 203 | * @rdev: radeon_device pointer | ||
| 204 | * | ||
| 205 | * Disables Writeback (all asics). Used for suspend. | ||
| 206 | */ | ||
| 165 | void radeon_wb_disable(struct radeon_device *rdev) | 207 | void radeon_wb_disable(struct radeon_device *rdev) |
| 166 | { | 208 | { |
| 167 | int r; | 209 | int r; |
| @@ -177,6 +219,14 @@ void radeon_wb_disable(struct radeon_device *rdev) | |||
| 177 | rdev->wb.enabled = false; | 219 | rdev->wb.enabled = false; |
| 178 | } | 220 | } |
| 179 | 221 | ||
| 222 | /** | ||
| 223 | * radeon_wb_fini - Disable Writeback and free memory | ||
| 224 | * | ||
| 225 | * @rdev: radeon_device pointer | ||
| 226 | * | ||
| 227 | * Disables Writeback and frees the Writeback memory (all asics). | ||
| 228 | * Used at driver shutdown. | ||
| 229 | */ | ||
| 180 | void radeon_wb_fini(struct radeon_device *rdev) | 230 | void radeon_wb_fini(struct radeon_device *rdev) |
| 181 | { | 231 | { |
| 182 | radeon_wb_disable(rdev); | 232 | radeon_wb_disable(rdev); |
| @@ -187,6 +237,15 @@ void radeon_wb_fini(struct radeon_device *rdev) | |||
| 187 | } | 237 | } |
| 188 | } | 238 | } |
| 189 | 239 | ||
| 240 | /** | ||
| 241 | * radeon_wb_init- Init Writeback driver info and allocate memory | ||
| 242 | * | ||
| 243 | * @rdev: radeon_device pointer | ||
| 244 | * | ||
| 245 | * Disables Writeback and frees the Writeback memory (all asics). | ||
| 246 | * Used at driver startup. | ||
| 247 | * Returns 0 on success or an -error on failure. | ||
| 248 | */ | ||
| 190 | int radeon_wb_init(struct radeon_device *rdev) | 249 | int radeon_wb_init(struct radeon_device *rdev) |
| 191 | { | 250 | { |
| 192 | int r; | 251 | int r; |
| @@ -355,6 +414,15 @@ void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) | |||
| 355 | /* | 414 | /* |
| 356 | * GPU helpers function. | 415 | * GPU helpers function. |
| 357 | */ | 416 | */ |
| 417 | /** | ||
| 418 | * radeon_card_posted - check if the hw has already been initialized | ||
| 419 | * | ||
| 420 | * @rdev: radeon_device pointer | ||
| 421 | * | ||
| 422 | * Check if the asic has been initialized (all asics). | ||
| 423 | * Used at driver startup. | ||
| 424 | * Returns true if initialized or false if not. | ||
| 425 | */ | ||
| 358 | bool radeon_card_posted(struct radeon_device *rdev) | 426 | bool radeon_card_posted(struct radeon_device *rdev) |
| 359 | { | 427 | { |
| 360 | uint32_t reg; | 428 | uint32_t reg; |
| @@ -404,6 +472,14 @@ bool radeon_card_posted(struct radeon_device *rdev) | |||
| 404 | 472 | ||
| 405 | } | 473 | } |
| 406 | 474 | ||
| 475 | /** | ||
| 476 | * radeon_update_bandwidth_info - update display bandwidth params | ||
| 477 | * | ||
| 478 | * @rdev: radeon_device pointer | ||
| 479 | * | ||
| 480 | * Used when sclk/mclk are switched or display modes are set. | ||
| 481 | * params are used to calculate display watermarks (all asics) | ||
| 482 | */ | ||
| 407 | void radeon_update_bandwidth_info(struct radeon_device *rdev) | 483 | void radeon_update_bandwidth_info(struct radeon_device *rdev) |
| 408 | { | 484 | { |
| 409 | fixed20_12 a; | 485 | fixed20_12 a; |
| @@ -424,6 +500,15 @@ void radeon_update_bandwidth_info(struct radeon_device *rdev) | |||
| 424 | } | 500 | } |
| 425 | } | 501 | } |
| 426 | 502 | ||
| 503 | /** | ||
| 504 | * radeon_boot_test_post_card - check and possibly initialize the hw | ||
| 505 | * | ||
| 506 | * @rdev: radeon_device pointer | ||
| 507 | * | ||
| 508 | * Check if the asic is initialized and if not, attempt to initialize | ||
| 509 | * it (all asics). | ||
| 510 | * Returns true if initialized or false if not. | ||
| 511 | */ | ||
| 427 | bool radeon_boot_test_post_card(struct radeon_device *rdev) | 512 | bool radeon_boot_test_post_card(struct radeon_device *rdev) |
| 428 | { | 513 | { |
| 429 | if (radeon_card_posted(rdev)) | 514 | if (radeon_card_posted(rdev)) |
| @@ -442,6 +527,16 @@ bool radeon_boot_test_post_card(struct radeon_device *rdev) | |||
| 442 | } | 527 | } |
| 443 | } | 528 | } |
| 444 | 529 | ||
| 530 | /** | ||
| 531 | * radeon_dummy_page_init - init dummy page used by the driver | ||
| 532 | * | ||
| 533 | * @rdev: radeon_device pointer | ||
| 534 | * | ||
| 535 | * Allocate the dummy page used by the driver (all asics). | ||
| 536 | * This dummy page is used by the driver as a filler for gart entries | ||
| 537 | * when pages are taken out of the GART | ||
| 538 | * Returns 0 on sucess, -ENOMEM on failure. | ||
| 539 | */ | ||
| 445 | int radeon_dummy_page_init(struct radeon_device *rdev) | 540 | int radeon_dummy_page_init(struct radeon_device *rdev) |
| 446 | { | 541 | { |
| 447 | if (rdev->dummy_page.page) | 542 | if (rdev->dummy_page.page) |
| @@ -460,6 +555,13 @@ int radeon_dummy_page_init(struct radeon_device *rdev) | |||
| 460 | return 0; | 555 | return 0; |
| 461 | } | 556 | } |
| 462 | 557 | ||
| 558 | /** | ||
| 559 | * radeon_dummy_page_fini - free dummy page used by the driver | ||
| 560 | * | ||
| 561 | * @rdev: radeon_device pointer | ||
| 562 | * | ||
| 563 | * Frees the dummy page used by the driver (all asics). | ||
| 564 | */ | ||
| 463 | void radeon_dummy_page_fini(struct radeon_device *rdev) | 565 | void radeon_dummy_page_fini(struct radeon_device *rdev) |
| 464 | { | 566 | { |
| 465 | if (rdev->dummy_page.page == NULL) | 567 | if (rdev->dummy_page.page == NULL) |
| @@ -472,6 +574,23 @@ void radeon_dummy_page_fini(struct radeon_device *rdev) | |||
| 472 | 574 | ||
| 473 | 575 | ||
| 474 | /* ATOM accessor methods */ | 576 | /* ATOM accessor methods */ |
| 577 | /* | ||
| 578 | * ATOM is an interpreted byte code stored in tables in the vbios. The | ||
| 579 | * driver registers callbacks to access registers and the interpreter | ||
| 580 | * in the driver parses the tables and executes then to program specific | ||
| 581 | * actions (set display modes, asic init, etc.). See radeon_atombios.c, | ||
| 582 | * atombios.h, and atom.c | ||
| 583 | */ | ||
| 584 | |||
| 585 | /** | ||
| 586 | * cail_pll_read - read PLL register | ||
| 587 | * | ||
| 588 | * @info: atom card_info pointer | ||
| 589 | * @reg: PLL register offset | ||
| 590 | * | ||
| 591 | * Provides a PLL register accessor for the atom interpreter (r4xx+). | ||
| 592 | * Returns the value of the PLL register. | ||
| 593 | */ | ||
| 475 | static uint32_t cail_pll_read(struct card_info *info, uint32_t reg) | 594 | static uint32_t cail_pll_read(struct card_info *info, uint32_t reg) |
| 476 | { | 595 | { |
| 477 | struct radeon_device *rdev = info->dev->dev_private; | 596 | struct radeon_device *rdev = info->dev->dev_private; |
| @@ -481,6 +600,15 @@ static uint32_t cail_pll_read(struct card_info *info, uint32_t reg) | |||
| 481 | return r; | 600 | return r; |
| 482 | } | 601 | } |
| 483 | 602 | ||
| 603 | /** | ||
| 604 | * cail_pll_write - write PLL register | ||
| 605 | * | ||
| 606 | * @info: atom card_info pointer | ||
| 607 | * @reg: PLL register offset | ||
| 608 | * @val: value to write to the pll register | ||
| 609 | * | ||
| 610 | * Provides a PLL register accessor for the atom interpreter (r4xx+). | ||
| 611 | */ | ||
| 484 | static void cail_pll_write(struct card_info *info, uint32_t reg, uint32_t val) | 612 | static void cail_pll_write(struct card_info *info, uint32_t reg, uint32_t val) |
| 485 | { | 613 | { |
| 486 | struct radeon_device *rdev = info->dev->dev_private; | 614 | struct radeon_device *rdev = info->dev->dev_private; |
| @@ -488,6 +616,15 @@ static void cail_pll_write(struct card_info *info, uint32_t reg, uint32_t val) | |||
| 488 | rdev->pll_wreg(rdev, reg, val); | 616 | rdev->pll_wreg(rdev, reg, val); |
| 489 | } | 617 | } |
| 490 | 618 | ||
| 619 | /** | ||
| 620 | * cail_mc_read - read MC (Memory Controller) register | ||
| 621 | * | ||
| 622 | * @info: atom card_info pointer | ||
| 623 | * @reg: MC register offset | ||
| 624 | * | ||
| 625 | * Provides an MC register accessor for the atom interpreter (r4xx+). | ||
| 626 | * Returns the value of the MC register. | ||
| 627 | */ | ||
| 491 | static uint32_t cail_mc_read(struct card_info *info, uint32_t reg) | 628 | static uint32_t cail_mc_read(struct card_info *info, uint32_t reg) |
| 492 | { | 629 | { |
| 493 | struct radeon_device *rdev = info->dev->dev_private; | 630 | struct radeon_device *rdev = info->dev->dev_private; |
| @@ -497,6 +634,15 @@ static uint32_t cail_mc_read(struct card_info *info, uint32_t reg) | |||
| 497 | return r; | 634 | return r; |
| 498 | } | 635 | } |
| 499 | 636 | ||
| 637 | /** | ||
| 638 | * cail_mc_write - write MC (Memory Controller) register | ||
| 639 | * | ||
| 640 | * @info: atom card_info pointer | ||
| 641 | * @reg: MC register offset | ||
| 642 | * @val: value to write to the pll register | ||
| 643 | * | ||
| 644 | * Provides a MC register accessor for the atom interpreter (r4xx+). | ||
| 645 | */ | ||
| 500 | static void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val) | 646 | static void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val) |
| 501 | { | 647 | { |
| 502 | struct radeon_device *rdev = info->dev->dev_private; | 648 | struct radeon_device *rdev = info->dev->dev_private; |
| @@ -504,6 +650,15 @@ static void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val) | |||
| 504 | rdev->mc_wreg(rdev, reg, val); | 650 | rdev->mc_wreg(rdev, reg, val); |
| 505 | } | 651 | } |
| 506 | 652 | ||
| 653 | /** | ||
| 654 | * cail_reg_write - write MMIO register | ||
| 655 | * | ||
| 656 | * @info: atom card_info pointer | ||
| 657 | * @reg: MMIO register offset | ||
| 658 | * @val: value to write to the pll register | ||
| 659 | * | ||
| 660 | * Provides a MMIO register accessor for the atom interpreter (r4xx+). | ||
| 661 | */ | ||
| 507 | static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val) | 662 | static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val) |
| 508 | { | 663 | { |
| 509 | struct radeon_device *rdev = info->dev->dev_private; | 664 | struct radeon_device *rdev = info->dev->dev_private; |
| @@ -511,6 +666,15 @@ static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val) | |||
| 511 | WREG32(reg*4, val); | 666 | WREG32(reg*4, val); |
| 512 | } | 667 | } |
| 513 | 668 | ||
| 669 | /** | ||
| 670 | * cail_reg_read - read MMIO register | ||
| 671 | * | ||
| 672 | * @info: atom card_info pointer | ||
| 673 | * @reg: MMIO register offset | ||
| 674 | * | ||
| 675 | * Provides an MMIO register accessor for the atom interpreter (r4xx+). | ||
| 676 | * Returns the value of the MMIO register. | ||
| 677 | */ | ||
| 514 | static uint32_t cail_reg_read(struct card_info *info, uint32_t reg) | 678 | static uint32_t cail_reg_read(struct card_info *info, uint32_t reg) |
| 515 | { | 679 | { |
| 516 | struct radeon_device *rdev = info->dev->dev_private; | 680 | struct radeon_device *rdev = info->dev->dev_private; |
| @@ -520,6 +684,15 @@ static uint32_t cail_reg_read(struct card_info *info, uint32_t reg) | |||
| 520 | return r; | 684 | return r; |
| 521 | } | 685 | } |
| 522 | 686 | ||
| 687 | /** | ||
| 688 | * cail_ioreg_write - write IO register | ||
| 689 | * | ||
| 690 | * @info: atom card_info pointer | ||
| 691 | * @reg: IO register offset | ||
| 692 | * @val: value to write to the pll register | ||
| 693 | * | ||
| 694 | * Provides a IO register accessor for the atom interpreter (r4xx+). | ||
| 695 | */ | ||
| 523 | static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val) | 696 | static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val) |
| 524 | { | 697 | { |
| 525 | struct radeon_device *rdev = info->dev->dev_private; | 698 | struct radeon_device *rdev = info->dev->dev_private; |
| @@ -527,6 +700,15 @@ static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val) | |||
| 527 | WREG32_IO(reg*4, val); | 700 | WREG32_IO(reg*4, val); |
| 528 | } | 701 | } |
| 529 | 702 | ||
| 703 | /** | ||
| 704 | * cail_ioreg_read - read IO register | ||
| 705 | * | ||
| 706 | * @info: atom card_info pointer | ||
| 707 | * @reg: IO register offset | ||
| 708 | * | ||
| 709 | * Provides an IO register accessor for the atom interpreter (r4xx+). | ||
| 710 | * Returns the value of the IO register. | ||
| 711 | */ | ||
| 530 | static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg) | 712 | static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg) |
| 531 | { | 713 | { |
| 532 | struct radeon_device *rdev = info->dev->dev_private; | 714 | struct radeon_device *rdev = info->dev->dev_private; |
| @@ -536,6 +718,16 @@ static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg) | |||
| 536 | return r; | 718 | return r; |
| 537 | } | 719 | } |
| 538 | 720 | ||
| 721 | /** | ||
| 722 | * radeon_atombios_init - init the driver info and callbacks for atombios | ||
| 723 | * | ||
| 724 | * @rdev: radeon_device pointer | ||
| 725 | * | ||
| 726 | * Initializes the driver info and register access callbacks for the | ||
| 727 | * ATOM interpreter (r4xx+). | ||
| 728 | * Returns 0 on sucess, -ENOMEM on failure. | ||
| 729 | * Called at driver startup. | ||
| 730 | */ | ||
| 539 | int radeon_atombios_init(struct radeon_device *rdev) | 731 | int radeon_atombios_init(struct radeon_device *rdev) |
| 540 | { | 732 | { |
| 541 | struct card_info *atom_card_info = | 733 | struct card_info *atom_card_info = |
| @@ -569,6 +761,15 @@ int radeon_atombios_init(struct radeon_device *rdev) | |||
| 569 | return 0; | 761 | return 0; |
| 570 | } | 762 | } |
| 571 | 763 | ||
| 764 | /** | ||
| 765 | * radeon_atombios_fini - free the driver info and callbacks for atombios | ||
| 766 | * | ||
| 767 | * @rdev: radeon_device pointer | ||
| 768 | * | ||
| 769 | * Frees the driver info and register access callbacks for the ATOM | ||
| 770 | * interpreter (r4xx+). | ||
| 771 | * Called at driver shutdown. | ||
| 772 | */ | ||
| 572 | void radeon_atombios_fini(struct radeon_device *rdev) | 773 | void radeon_atombios_fini(struct radeon_device *rdev) |
| 573 | { | 774 | { |
| 574 | if (rdev->mode_info.atom_context) { | 775 | if (rdev->mode_info.atom_context) { |
| @@ -578,17 +779,50 @@ void radeon_atombios_fini(struct radeon_device *rdev) | |||
| 578 | kfree(rdev->mode_info.atom_card_info); | 779 | kfree(rdev->mode_info.atom_card_info); |
| 579 | } | 780 | } |
| 580 | 781 | ||
| 782 | /* COMBIOS */ | ||
| 783 | /* | ||
| 784 | * COMBIOS is the bios format prior to ATOM. It provides | ||
| 785 | * command tables similar to ATOM, but doesn't have a unified | ||
| 786 | * parser. See radeon_combios.c | ||
| 787 | */ | ||
| 788 | |||
| 789 | /** | ||
| 790 | * radeon_combios_init - init the driver info for combios | ||
| 791 | * | ||
| 792 | * @rdev: radeon_device pointer | ||
| 793 | * | ||
| 794 | * Initializes the driver info for combios (r1xx-r3xx). | ||
| 795 | * Returns 0 on sucess. | ||
| 796 | * Called at driver startup. | ||
| 797 | */ | ||
| 581 | int radeon_combios_init(struct radeon_device *rdev) | 798 | int radeon_combios_init(struct radeon_device *rdev) |
| 582 | { | 799 | { |
| 583 | radeon_combios_initialize_bios_scratch_regs(rdev->ddev); | 800 | radeon_combios_initialize_bios_scratch_regs(rdev->ddev); |
| 584 | return 0; | 801 | return 0; |
| 585 | } | 802 | } |
| 586 | 803 | ||
| 804 | /** | ||
| 805 | * radeon_combios_fini - free the driver info for combios | ||
| 806 | * | ||
| 807 | * @rdev: radeon_device pointer | ||
| 808 | * | ||
| 809 | * Frees the driver info for combios (r1xx-r3xx). | ||
| 810 | * Called at driver shutdown. | ||
| 811 | */ | ||
| 587 | void radeon_combios_fini(struct radeon_device *rdev) | 812 | void radeon_combios_fini(struct radeon_device *rdev) |
| 588 | { | 813 | { |
| 589 | } | 814 | } |
| 590 | 815 | ||
| 591 | /* if we get transitioned to only one device, tak VGA back */ | 816 | /* if we get transitioned to only one device, take VGA back */ |
| 817 | /** | ||
| 818 | * radeon_vga_set_decode - enable/disable vga decode | ||
| 819 | * | ||
| 820 | * @cookie: radeon_device pointer | ||
| 821 | * @state: enable/disable vga decode | ||
| 822 | * | ||
| 823 | * Enable/disable vga decode (all asics). | ||
| 824 | * Returns VGA resource flags. | ||
| 825 | */ | ||
| 592 | static unsigned int radeon_vga_set_decode(void *cookie, bool state) | 826 | static unsigned int radeon_vga_set_decode(void *cookie, bool state) |
| 593 | { | 827 | { |
| 594 | struct radeon_device *rdev = cookie; | 828 | struct radeon_device *rdev = cookie; |
| @@ -600,6 +834,14 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state) | |||
| 600 | return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; | 834 | return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; |
| 601 | } | 835 | } |
| 602 | 836 | ||
| 837 | /** | ||
| 838 | * radeon_check_arguments - validate module params | ||
| 839 | * | ||
| 840 | * @rdev: radeon_device pointer | ||
| 841 | * | ||
| 842 | * Validates certain module parameters and updates | ||
| 843 | * the associated values used by the driver (all asics). | ||
| 844 | */ | ||
| 603 | void radeon_check_arguments(struct radeon_device *rdev) | 845 | void radeon_check_arguments(struct radeon_device *rdev) |
| 604 | { | 846 | { |
| 605 | /* vramlimit must be a power of two */ | 847 | /* vramlimit must be a power of two */ |
| @@ -666,6 +908,15 @@ void radeon_check_arguments(struct radeon_device *rdev) | |||
| 666 | } | 908 | } |
| 667 | } | 909 | } |
| 668 | 910 | ||
| 911 | /** | ||
| 912 | * radeon_switcheroo_set_state - set switcheroo state | ||
| 913 | * | ||
| 914 | * @pdev: pci dev pointer | ||
| 915 | * @state: vga switcheroo state | ||
| 916 | * | ||
| 917 | * Callback for the switcheroo driver. Suspends or resumes the | ||
| 918 | * the asics before or after it is powered up using ACPI methods. | ||
| 919 | */ | ||
| 669 | static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) | 920 | static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) |
| 670 | { | 921 | { |
| 671 | struct drm_device *dev = pci_get_drvdata(pdev); | 922 | struct drm_device *dev = pci_get_drvdata(pdev); |
| @@ -686,6 +937,15 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero | |||
| 686 | } | 937 | } |
| 687 | } | 938 | } |
| 688 | 939 | ||
| 940 | /** | ||
| 941 | * radeon_switcheroo_can_switch - see if switcheroo state can change | ||
| 942 | * | ||
| 943 | * @pdev: pci dev pointer | ||
| 944 | * | ||
| 945 | * Callback for the switcheroo driver. Check of the switcheroo | ||
| 946 | * state can be changed. | ||
| 947 | * Returns true if the state can be changed, false if not. | ||
| 948 | */ | ||
| 689 | static bool radeon_switcheroo_can_switch(struct pci_dev *pdev) | 949 | static bool radeon_switcheroo_can_switch(struct pci_dev *pdev) |
| 690 | { | 950 | { |
| 691 | struct drm_device *dev = pci_get_drvdata(pdev); | 951 | struct drm_device *dev = pci_get_drvdata(pdev); |
| @@ -703,6 +963,18 @@ static const struct vga_switcheroo_client_ops radeon_switcheroo_ops = { | |||
| 703 | .can_switch = radeon_switcheroo_can_switch, | 963 | .can_switch = radeon_switcheroo_can_switch, |
| 704 | }; | 964 | }; |
| 705 | 965 | ||
| 966 | /** | ||
| 967 | * radeon_device_init - initialize the driver | ||
| 968 | * | ||
| 969 | * @rdev: radeon_device pointer | ||
| 970 | * @pdev: drm dev pointer | ||
| 971 | * @pdev: pci dev pointer | ||
| 972 | * @flags: driver flags | ||
| 973 | * | ||
| 974 | * Initializes the driver info and hw (all asics). | ||
| 975 | * Returns 0 for success or an error on failure. | ||
| 976 | * Called at driver startup. | ||
| 977 | */ | ||
| 706 | int radeon_device_init(struct radeon_device *rdev, | 978 | int radeon_device_init(struct radeon_device *rdev, |
| 707 | struct drm_device *ddev, | 979 | struct drm_device *ddev, |
| 708 | struct pci_dev *pdev, | 980 | struct pci_dev *pdev, |
| @@ -721,6 +993,10 @@ int radeon_device_init(struct radeon_device *rdev, | |||
| 721 | rdev->usec_timeout = RADEON_MAX_USEC_TIMEOUT; | 993 | rdev->usec_timeout = RADEON_MAX_USEC_TIMEOUT; |
| 722 | rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; | 994 | rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; |
| 723 | rdev->accel_working = false; | 995 | rdev->accel_working = false; |
| 996 | /* set up ring ids */ | ||
| 997 | for (i = 0; i < RADEON_NUM_RINGS; i++) { | ||
| 998 | rdev->ring[i].idx = i; | ||
| 999 | } | ||
| 724 | 1000 | ||
| 725 | DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n", | 1001 | DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n", |
| 726 | radeon_family_name[rdev->family], pdev->vendor, pdev->device, | 1002 | radeon_family_name[rdev->family], pdev->vendor, pdev->device, |
| @@ -728,20 +1004,20 @@ int radeon_device_init(struct radeon_device *rdev, | |||
| 728 | 1004 | ||
| 729 | /* mutex initialization are all done here so we | 1005 | /* mutex initialization are all done here so we |
| 730 | * can recall function without having locking issues */ | 1006 | * can recall function without having locking issues */ |
| 731 | radeon_mutex_init(&rdev->cs_mutex); | ||
| 732 | mutex_init(&rdev->ring_lock); | 1007 | mutex_init(&rdev->ring_lock); |
| 733 | mutex_init(&rdev->dc_hw_i2c_mutex); | 1008 | mutex_init(&rdev->dc_hw_i2c_mutex); |
| 734 | if (rdev->family >= CHIP_R600) | 1009 | atomic_set(&rdev->ih.lock, 0); |
| 735 | spin_lock_init(&rdev->ih.lock); | ||
| 736 | mutex_init(&rdev->gem.mutex); | 1010 | mutex_init(&rdev->gem.mutex); |
| 737 | mutex_init(&rdev->pm.mutex); | 1011 | mutex_init(&rdev->pm.mutex); |
| 738 | mutex_init(&rdev->vram_mutex); | 1012 | init_rwsem(&rdev->pm.mclk_lock); |
| 1013 | init_rwsem(&rdev->exclusive_lock); | ||
| 739 | init_waitqueue_head(&rdev->irq.vblank_queue); | 1014 | init_waitqueue_head(&rdev->irq.vblank_queue); |
| 740 | init_waitqueue_head(&rdev->irq.idle_queue); | 1015 | init_waitqueue_head(&rdev->irq.idle_queue); |
| 741 | r = radeon_gem_init(rdev); | 1016 | r = radeon_gem_init(rdev); |
| 742 | if (r) | 1017 | if (r) |
| 743 | return r; | 1018 | return r; |
| 744 | /* initialize vm here */ | 1019 | /* initialize vm here */ |
| 1020 | mutex_init(&rdev->vm_manager.lock); | ||
| 745 | rdev->vm_manager.use_bitmap = 1; | 1021 | rdev->vm_manager.use_bitmap = 1; |
| 746 | rdev->vm_manager.max_pfn = 1 << 20; | 1022 | rdev->vm_manager.max_pfn = 1 << 20; |
| 747 | INIT_LIST_HEAD(&rdev->vm_manager.lru_vm); | 1023 | INIT_LIST_HEAD(&rdev->vm_manager.lru_vm); |
| @@ -822,6 +1098,10 @@ int radeon_device_init(struct radeon_device *rdev, | |||
| 822 | if (r) | 1098 | if (r) |
| 823 | return r; | 1099 | return r; |
| 824 | 1100 | ||
| 1101 | r = radeon_ib_ring_tests(rdev); | ||
| 1102 | if (r) | ||
| 1103 | DRM_ERROR("ib ring test failed (%d).\n", r); | ||
| 1104 | |||
| 825 | if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) { | 1105 | if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) { |
| 826 | /* Acceleration not working on AGP card try again | 1106 | /* Acceleration not working on AGP card try again |
| 827 | * with fallback to PCI or PCIE GART | 1107 | * with fallback to PCI or PCIE GART |
| @@ -847,6 +1127,14 @@ int radeon_device_init(struct radeon_device *rdev, | |||
| 847 | 1127 | ||
| 848 | static void radeon_debugfs_remove_files(struct radeon_device *rdev); | 1128 | static void radeon_debugfs_remove_files(struct radeon_device *rdev); |
| 849 | 1129 | ||
| 1130 | /** | ||
| 1131 | * radeon_device_fini - tear down the driver | ||
| 1132 | * | ||
| 1133 | * @rdev: radeon_device pointer | ||
| 1134 | * | ||
| 1135 | * Tear down the driver info (all asics). | ||
| 1136 | * Called at driver shutdown. | ||
| 1137 | */ | ||
| 850 | void radeon_device_fini(struct radeon_device *rdev) | 1138 | void radeon_device_fini(struct radeon_device *rdev) |
| 851 | { | 1139 | { |
| 852 | DRM_INFO("radeon: finishing device.\n"); | 1140 | DRM_INFO("radeon: finishing device.\n"); |
| @@ -868,6 +1156,16 @@ void radeon_device_fini(struct radeon_device *rdev) | |||
| 868 | /* | 1156 | /* |
| 869 | * Suspend & resume. | 1157 | * Suspend & resume. |
| 870 | */ | 1158 | */ |
| 1159 | /** | ||
| 1160 | * radeon_suspend_kms - initiate device suspend | ||
| 1161 | * | ||
| 1162 | * @pdev: drm dev pointer | ||
| 1163 | * @state: suspend state | ||
| 1164 | * | ||
| 1165 | * Puts the hw in the suspend state (all asics). | ||
| 1166 | * Returns 0 for success or an error on failure. | ||
| 1167 | * Called at driver suspend. | ||
| 1168 | */ | ||
| 871 | int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | 1169 | int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) |
| 872 | { | 1170 | { |
| 873 | struct radeon_device *rdev; | 1171 | struct radeon_device *rdev; |
| @@ -942,10 +1240,20 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | |||
| 942 | return 0; | 1240 | return 0; |
| 943 | } | 1241 | } |
| 944 | 1242 | ||
| 1243 | /** | ||
| 1244 | * radeon_resume_kms - initiate device resume | ||
| 1245 | * | ||
| 1246 | * @pdev: drm dev pointer | ||
| 1247 | * | ||
| 1248 | * Bring the hw back to operating state (all asics). | ||
| 1249 | * Returns 0 for success or an error on failure. | ||
| 1250 | * Called at driver resume. | ||
| 1251 | */ | ||
| 945 | int radeon_resume_kms(struct drm_device *dev) | 1252 | int radeon_resume_kms(struct drm_device *dev) |
| 946 | { | 1253 | { |
| 947 | struct drm_connector *connector; | 1254 | struct drm_connector *connector; |
| 948 | struct radeon_device *rdev = dev->dev_private; | 1255 | struct radeon_device *rdev = dev->dev_private; |
| 1256 | int r; | ||
| 949 | 1257 | ||
| 950 | if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) | 1258 | if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) |
| 951 | return 0; | 1259 | return 0; |
| @@ -960,6 +1268,11 @@ int radeon_resume_kms(struct drm_device *dev) | |||
| 960 | /* resume AGP if in use */ | 1268 | /* resume AGP if in use */ |
| 961 | radeon_agp_resume(rdev); | 1269 | radeon_agp_resume(rdev); |
| 962 | radeon_resume(rdev); | 1270 | radeon_resume(rdev); |
| 1271 | |||
| 1272 | r = radeon_ib_ring_tests(rdev); | ||
| 1273 | if (r) | ||
| 1274 | DRM_ERROR("ib ring test failed (%d).\n", r); | ||
| 1275 | |||
| 963 | radeon_pm_resume(rdev); | 1276 | radeon_pm_resume(rdev); |
| 964 | radeon_restore_bios_scratch_regs(rdev); | 1277 | radeon_restore_bios_scratch_regs(rdev); |
| 965 | 1278 | ||
| @@ -984,30 +1297,77 @@ int radeon_resume_kms(struct drm_device *dev) | |||
| 984 | return 0; | 1297 | return 0; |
| 985 | } | 1298 | } |
| 986 | 1299 | ||
| 1300 | /** | ||
| 1301 | * radeon_gpu_reset - reset the asic | ||
| 1302 | * | ||
| 1303 | * @rdev: radeon device pointer | ||
| 1304 | * | ||
| 1305 | * Attempt the reset the GPU if it has hung (all asics). | ||
| 1306 | * Returns 0 for success or an error on failure. | ||
| 1307 | */ | ||
| 987 | int radeon_gpu_reset(struct radeon_device *rdev) | 1308 | int radeon_gpu_reset(struct radeon_device *rdev) |
| 988 | { | 1309 | { |
| 989 | int r; | 1310 | unsigned ring_sizes[RADEON_NUM_RINGS]; |
| 1311 | uint32_t *ring_data[RADEON_NUM_RINGS]; | ||
| 1312 | |||
| 1313 | bool saved = false; | ||
| 1314 | |||
| 1315 | int i, r; | ||
| 990 | int resched; | 1316 | int resched; |
| 991 | 1317 | ||
| 1318 | down_write(&rdev->exclusive_lock); | ||
| 992 | radeon_save_bios_scratch_regs(rdev); | 1319 | radeon_save_bios_scratch_regs(rdev); |
| 993 | /* block TTM */ | 1320 | /* block TTM */ |
| 994 | resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); | 1321 | resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); |
| 995 | radeon_suspend(rdev); | 1322 | radeon_suspend(rdev); |
| 996 | 1323 | ||
| 1324 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | ||
| 1325 | ring_sizes[i] = radeon_ring_backup(rdev, &rdev->ring[i], | ||
| 1326 | &ring_data[i]); | ||
| 1327 | if (ring_sizes[i]) { | ||
| 1328 | saved = true; | ||
| 1329 | dev_info(rdev->dev, "Saved %d dwords of commands " | ||
| 1330 | "on ring %d.\n", ring_sizes[i], i); | ||
| 1331 | } | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | retry: | ||
| 997 | r = radeon_asic_reset(rdev); | 1335 | r = radeon_asic_reset(rdev); |
| 998 | if (!r) { | 1336 | if (!r) { |
| 999 | dev_info(rdev->dev, "GPU reset succeed\n"); | 1337 | dev_info(rdev->dev, "GPU reset succeeded, trying to resume\n"); |
| 1000 | radeon_resume(rdev); | 1338 | radeon_resume(rdev); |
| 1001 | radeon_restore_bios_scratch_regs(rdev); | ||
| 1002 | drm_helper_resume_force_mode(rdev->ddev); | ||
| 1003 | ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); | ||
| 1004 | } | 1339 | } |
| 1005 | 1340 | ||
| 1341 | radeon_restore_bios_scratch_regs(rdev); | ||
| 1342 | drm_helper_resume_force_mode(rdev->ddev); | ||
| 1343 | |||
| 1344 | if (!r) { | ||
| 1345 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | ||
| 1346 | radeon_ring_restore(rdev, &rdev->ring[i], | ||
| 1347 | ring_sizes[i], ring_data[i]); | ||
| 1348 | } | ||
| 1349 | |||
| 1350 | r = radeon_ib_ring_tests(rdev); | ||
| 1351 | if (r) { | ||
| 1352 | dev_err(rdev->dev, "ib ring test failed (%d).\n", r); | ||
| 1353 | if (saved) { | ||
| 1354 | radeon_suspend(rdev); | ||
| 1355 | goto retry; | ||
| 1356 | } | ||
| 1357 | } | ||
| 1358 | } else { | ||
| 1359 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | ||
| 1360 | kfree(ring_data[i]); | ||
| 1361 | } | ||
| 1362 | } | ||
| 1363 | |||
| 1364 | ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); | ||
| 1006 | if (r) { | 1365 | if (r) { |
| 1007 | /* bad news, how to tell it to userspace ? */ | 1366 | /* bad news, how to tell it to userspace ? */ |
| 1008 | dev_info(rdev->dev, "GPU reset failed\n"); | 1367 | dev_info(rdev->dev, "GPU reset failed\n"); |
| 1009 | } | 1368 | } |
| 1010 | 1369 | ||
| 1370 | up_write(&rdev->exclusive_lock); | ||
| 1011 | return r; | 1371 | return r; |
| 1012 | } | 1372 | } |
| 1013 | 1373 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 64a008d14493..7ddef8f30d0e 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
| @@ -1401,7 +1401,7 @@ void radeon_modeset_fini(struct radeon_device *rdev) | |||
| 1401 | radeon_i2c_fini(rdev); | 1401 | radeon_i2c_fini(rdev); |
| 1402 | } | 1402 | } |
| 1403 | 1403 | ||
| 1404 | static bool is_hdtv_mode(struct drm_display_mode *mode) | 1404 | static bool is_hdtv_mode(const struct drm_display_mode *mode) |
| 1405 | { | 1405 | { |
| 1406 | /* try and guess if this is a tv or a monitor */ | 1406 | /* try and guess if this is a tv or a monitor */ |
| 1407 | if ((mode->vdisplay == 480 && mode->hdisplay == 720) || /* 480p */ | 1407 | if ((mode->vdisplay == 480 && mode->hdisplay == 720) || /* 480p */ |
| @@ -1414,7 +1414,7 @@ static bool is_hdtv_mode(struct drm_display_mode *mode) | |||
| 1414 | } | 1414 | } |
| 1415 | 1415 | ||
| 1416 | bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | 1416 | bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, |
| 1417 | struct drm_display_mode *mode, | 1417 | const struct drm_display_mode *mode, |
| 1418 | struct drm_display_mode *adjusted_mode) | 1418 | struct drm_display_mode *adjusted_mode) |
| 1419 | { | 1419 | { |
| 1420 | struct drm_device *dev = crtc->dev; | 1420 | struct drm_device *dev = crtc->dev; |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 2c4d53fd20c5..dcea6f01ae4e 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
| @@ -133,7 +133,7 @@ int radeon_tv = 1; | |||
| 133 | int radeon_audio = 0; | 133 | int radeon_audio = 0; |
| 134 | int radeon_disp_priority = 0; | 134 | int radeon_disp_priority = 0; |
| 135 | int radeon_hw_i2c = 0; | 135 | int radeon_hw_i2c = 0; |
| 136 | int radeon_pcie_gen2 = 0; | 136 | int radeon_pcie_gen2 = -1; |
| 137 | int radeon_msi = -1; | 137 | int radeon_msi = -1; |
| 138 | int radeon_lockup_timeout = 10000; | 138 | int radeon_lockup_timeout = 10000; |
| 139 | 139 | ||
| @@ -179,7 +179,7 @@ module_param_named(disp_priority, radeon_disp_priority, int, 0444); | |||
| 179 | MODULE_PARM_DESC(hw_i2c, "hw i2c engine enable (0 = disable)"); | 179 | MODULE_PARM_DESC(hw_i2c, "hw i2c engine enable (0 = disable)"); |
| 180 | module_param_named(hw_i2c, radeon_hw_i2c, int, 0444); | 180 | module_param_named(hw_i2c, radeon_hw_i2c, int, 0444); |
| 181 | 181 | ||
| 182 | MODULE_PARM_DESC(pcie_gen2, "PCIE Gen2 mode (1 = enable)"); | 182 | MODULE_PARM_DESC(pcie_gen2, "PCIE Gen2 mode (-1 = auto, 0 = disable, 1 = enable)"); |
| 183 | module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444); | 183 | module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444); |
| 184 | 184 | ||
| 185 | MODULE_PARM_DESC(msi, "MSI support (1 = enable, 0 = disable, -1 = auto)"); | 185 | MODULE_PARM_DESC(msi, "MSI support (1 = enable, 0 = disable, -1 = auto)"); |
| @@ -262,7 +262,6 @@ static struct drm_driver driver_old = { | |||
| 262 | .irq_postinstall = radeon_driver_irq_postinstall, | 262 | .irq_postinstall = radeon_driver_irq_postinstall, |
| 263 | .irq_uninstall = radeon_driver_irq_uninstall, | 263 | .irq_uninstall = radeon_driver_irq_uninstall, |
| 264 | .irq_handler = radeon_driver_irq_handler, | 264 | .irq_handler = radeon_driver_irq_handler, |
| 265 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 266 | .ioctls = radeon_ioctls, | 265 | .ioctls = radeon_ioctls, |
| 267 | .dma_ioctl = radeon_cp_buffers, | 266 | .dma_ioctl = radeon_cp_buffers, |
| 268 | .fops = &radeon_driver_old_fops, | 267 | .fops = &radeon_driver_old_fops, |
| @@ -365,7 +364,6 @@ static struct drm_driver kms_driver = { | |||
| 365 | .irq_postinstall = radeon_driver_irq_postinstall_kms, | 364 | .irq_postinstall = radeon_driver_irq_postinstall_kms, |
| 366 | .irq_uninstall = radeon_driver_irq_uninstall_kms, | 365 | .irq_uninstall = radeon_driver_irq_uninstall_kms, |
| 367 | .irq_handler = radeon_driver_irq_handler_kms, | 366 | .irq_handler = radeon_driver_irq_handler_kms, |
| 368 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 369 | .ioctls = radeon_ioctls_kms, | 367 | .ioctls = radeon_ioctls_kms, |
| 370 | .gem_init_object = radeon_gem_object_init, | 368 | .gem_init_object = radeon_gem_object_init, |
| 371 | .gem_free_object = radeon_gem_object_free, | 369 | .gem_free_object = radeon_gem_object_free, |
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 11f5f402d22c..7b737b9339ad 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c | |||
| @@ -40,39 +40,95 @@ | |||
| 40 | #include "radeon.h" | 40 | #include "radeon.h" |
| 41 | #include "radeon_trace.h" | 41 | #include "radeon_trace.h" |
| 42 | 42 | ||
| 43 | /* | ||
| 44 | * Fences | ||
| 45 | * Fences mark an event in the GPUs pipeline and are used | ||
| 46 | * for GPU/CPU synchronization. When the fence is written, | ||
| 47 | * it is expected that all buffers associated with that fence | ||
| 48 | * are no longer in use by the associated ring on the GPU and | ||
| 49 | * that the the relevant GPU caches have been flushed. Whether | ||
| 50 | * we use a scratch register or memory location depends on the asic | ||
| 51 | * and whether writeback is enabled. | ||
| 52 | */ | ||
| 53 | |||
| 54 | /** | ||
| 55 | * radeon_fence_write - write a fence value | ||
| 56 | * | ||
| 57 | * @rdev: radeon_device pointer | ||
| 58 | * @seq: sequence number to write | ||
| 59 | * @ring: ring index the fence is associated with | ||
| 60 | * | ||
| 61 | * Writes a fence value to memory or a scratch register (all asics). | ||
| 62 | */ | ||
| 43 | static void radeon_fence_write(struct radeon_device *rdev, u32 seq, int ring) | 63 | static void radeon_fence_write(struct radeon_device *rdev, u32 seq, int ring) |
| 44 | { | 64 | { |
| 45 | if (rdev->wb.enabled) { | 65 | struct radeon_fence_driver *drv = &rdev->fence_drv[ring]; |
| 46 | *rdev->fence_drv[ring].cpu_addr = cpu_to_le32(seq); | 66 | if (likely(rdev->wb.enabled || !drv->scratch_reg)) { |
| 67 | *drv->cpu_addr = cpu_to_le32(seq); | ||
| 47 | } else { | 68 | } else { |
| 48 | WREG32(rdev->fence_drv[ring].scratch_reg, seq); | 69 | WREG32(drv->scratch_reg, seq); |
| 49 | } | 70 | } |
| 50 | } | 71 | } |
| 51 | 72 | ||
| 73 | /** | ||
| 74 | * radeon_fence_read - read a fence value | ||
| 75 | * | ||
| 76 | * @rdev: radeon_device pointer | ||
| 77 | * @ring: ring index the fence is associated with | ||
| 78 | * | ||
| 79 | * Reads a fence value from memory or a scratch register (all asics). | ||
| 80 | * Returns the value of the fence read from memory or register. | ||
| 81 | */ | ||
| 52 | static u32 radeon_fence_read(struct radeon_device *rdev, int ring) | 82 | static u32 radeon_fence_read(struct radeon_device *rdev, int ring) |
| 53 | { | 83 | { |
| 84 | struct radeon_fence_driver *drv = &rdev->fence_drv[ring]; | ||
| 54 | u32 seq = 0; | 85 | u32 seq = 0; |
| 55 | 86 | ||
| 56 | if (rdev->wb.enabled) { | 87 | if (likely(rdev->wb.enabled || !drv->scratch_reg)) { |
| 57 | seq = le32_to_cpu(*rdev->fence_drv[ring].cpu_addr); | 88 | seq = le32_to_cpu(*drv->cpu_addr); |
| 58 | } else { | 89 | } else { |
| 59 | seq = RREG32(rdev->fence_drv[ring].scratch_reg); | 90 | seq = RREG32(drv->scratch_reg); |
| 60 | } | 91 | } |
| 61 | return seq; | 92 | return seq; |
| 62 | } | 93 | } |
| 63 | 94 | ||
| 64 | int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) | 95 | /** |
| 96 | * radeon_fence_emit - emit a fence on the requested ring | ||
| 97 | * | ||
| 98 | * @rdev: radeon_device pointer | ||
| 99 | * @fence: radeon fence object | ||
| 100 | * @ring: ring index the fence is associated with | ||
| 101 | * | ||
| 102 | * Emits a fence command on the requested ring (all asics). | ||
| 103 | * Returns 0 on success, -ENOMEM on failure. | ||
| 104 | */ | ||
| 105 | int radeon_fence_emit(struct radeon_device *rdev, | ||
| 106 | struct radeon_fence **fence, | ||
| 107 | int ring) | ||
| 65 | { | 108 | { |
| 66 | /* we are protected by the ring emission mutex */ | 109 | /* we are protected by the ring emission mutex */ |
| 67 | if (fence->seq && fence->seq < RADEON_FENCE_NOTEMITED_SEQ) { | 110 | *fence = kmalloc(sizeof(struct radeon_fence), GFP_KERNEL); |
| 68 | return 0; | 111 | if ((*fence) == NULL) { |
| 112 | return -ENOMEM; | ||
| 69 | } | 113 | } |
| 70 | fence->seq = ++rdev->fence_drv[fence->ring].seq; | 114 | kref_init(&((*fence)->kref)); |
| 71 | radeon_fence_ring_emit(rdev, fence->ring, fence); | 115 | (*fence)->rdev = rdev; |
| 72 | trace_radeon_fence_emit(rdev->ddev, fence->seq); | 116 | (*fence)->seq = ++rdev->fence_drv[ring].sync_seq[ring]; |
| 117 | (*fence)->ring = ring; | ||
| 118 | radeon_fence_ring_emit(rdev, ring, *fence); | ||
| 119 | trace_radeon_fence_emit(rdev->ddev, (*fence)->seq); | ||
| 73 | return 0; | 120 | return 0; |
| 74 | } | 121 | } |
| 75 | 122 | ||
| 123 | /** | ||
| 124 | * radeon_fence_process - process a fence | ||
| 125 | * | ||
| 126 | * @rdev: radeon_device pointer | ||
| 127 | * @ring: ring index the fence is associated with | ||
| 128 | * | ||
| 129 | * Checks the current fence value and wakes the fence queue | ||
| 130 | * if the sequence number has increased (all asics). | ||
| 131 | */ | ||
| 76 | void radeon_fence_process(struct radeon_device *rdev, int ring) | 132 | void radeon_fence_process(struct radeon_device *rdev, int ring) |
| 77 | { | 133 | { |
| 78 | uint64_t seq, last_seq; | 134 | uint64_t seq, last_seq; |
| @@ -133,30 +189,35 @@ void radeon_fence_process(struct radeon_device *rdev, int ring) | |||
| 133 | } | 189 | } |
| 134 | } | 190 | } |
| 135 | 191 | ||
| 192 | /** | ||
| 193 | * radeon_fence_destroy - destroy a fence | ||
| 194 | * | ||
| 195 | * @kref: fence kref | ||
| 196 | * | ||
| 197 | * Frees the fence object (all asics). | ||
| 198 | */ | ||
| 136 | static void radeon_fence_destroy(struct kref *kref) | 199 | static void radeon_fence_destroy(struct kref *kref) |
| 137 | { | 200 | { |
| 138 | struct radeon_fence *fence; | 201 | struct radeon_fence *fence; |
| 139 | 202 | ||
| 140 | fence = container_of(kref, struct radeon_fence, kref); | 203 | fence = container_of(kref, struct radeon_fence, kref); |
| 141 | fence->seq = RADEON_FENCE_NOTEMITED_SEQ; | ||
| 142 | kfree(fence); | 204 | kfree(fence); |
| 143 | } | 205 | } |
| 144 | 206 | ||
| 145 | int radeon_fence_create(struct radeon_device *rdev, | 207 | /** |
| 146 | struct radeon_fence **fence, | 208 | * radeon_fence_seq_signaled - check if a fence sequeuce number has signaled |
| 147 | int ring) | 209 | * |
| 148 | { | 210 | * @rdev: radeon device pointer |
| 149 | *fence = kmalloc(sizeof(struct radeon_fence), GFP_KERNEL); | 211 | * @seq: sequence number |
| 150 | if ((*fence) == NULL) { | 212 | * @ring: ring index the fence is associated with |
| 151 | return -ENOMEM; | 213 | * |
| 152 | } | 214 | * Check if the last singled fence sequnce number is >= the requested |
| 153 | kref_init(&((*fence)->kref)); | 215 | * sequence number (all asics). |
| 154 | (*fence)->rdev = rdev; | 216 | * Returns true if the fence has signaled (current fence value |
| 155 | (*fence)->seq = RADEON_FENCE_NOTEMITED_SEQ; | 217 | * is >= requested value) or false if it has not (current fence |
| 156 | (*fence)->ring = ring; | 218 | * value is < the requested value. Helper function for |
| 157 | return 0; | 219 | * radeon_fence_signaled(). |
| 158 | } | 220 | */ |
| 159 | |||
| 160 | static bool radeon_fence_seq_signaled(struct radeon_device *rdev, | 221 | static bool radeon_fence_seq_signaled(struct radeon_device *rdev, |
| 161 | u64 seq, unsigned ring) | 222 | u64 seq, unsigned ring) |
| 162 | { | 223 | { |
| @@ -171,15 +232,19 @@ static bool radeon_fence_seq_signaled(struct radeon_device *rdev, | |||
| 171 | return false; | 232 | return false; |
| 172 | } | 233 | } |
| 173 | 234 | ||
| 235 | /** | ||
| 236 | * radeon_fence_signaled - check if a fence has signaled | ||
| 237 | * | ||
| 238 | * @fence: radeon fence object | ||
| 239 | * | ||
| 240 | * Check if the requested fence has signaled (all asics). | ||
| 241 | * Returns true if the fence has signaled or false if it has not. | ||
| 242 | */ | ||
| 174 | bool radeon_fence_signaled(struct radeon_fence *fence) | 243 | bool radeon_fence_signaled(struct radeon_fence *fence) |
| 175 | { | 244 | { |
| 176 | if (!fence) { | 245 | if (!fence) { |
| 177 | return true; | 246 | return true; |
| 178 | } | 247 | } |
| 179 | if (fence->seq == RADEON_FENCE_NOTEMITED_SEQ) { | ||
| 180 | WARN(1, "Querying an unemitted fence : %p !\n", fence); | ||
| 181 | return true; | ||
| 182 | } | ||
| 183 | if (fence->seq == RADEON_FENCE_SIGNALED_SEQ) { | 248 | if (fence->seq == RADEON_FENCE_SIGNALED_SEQ) { |
| 184 | return true; | 249 | return true; |
| 185 | } | 250 | } |
| @@ -190,6 +255,24 @@ bool radeon_fence_signaled(struct radeon_fence *fence) | |||
| 190 | return false; | 255 | return false; |
| 191 | } | 256 | } |
| 192 | 257 | ||
| 258 | /** | ||
| 259 | * radeon_fence_wait_seq - wait for a specific sequence number | ||
| 260 | * | ||
| 261 | * @rdev: radeon device pointer | ||
| 262 | * @target_seq: sequence number we want to wait for | ||
| 263 | * @ring: ring index the fence is associated with | ||
| 264 | * @intr: use interruptable sleep | ||
| 265 | * @lock_ring: whether the ring should be locked or not | ||
| 266 | * | ||
| 267 | * Wait for the requested sequence number to be written (all asics). | ||
| 268 | * @intr selects whether to use interruptable (true) or non-interruptable | ||
| 269 | * (false) sleep when waiting for the sequence number. Helper function | ||
| 270 | * for radeon_fence_wait(), et al. | ||
| 271 | * Returns 0 if the sequence number has passed, error for all other cases. | ||
| 272 | * -EDEADLK is returned when a GPU lockup has been detected and the ring is | ||
| 273 | * marked as not ready so no further jobs get scheduled until a successful | ||
| 274 | * reset. | ||
| 275 | */ | ||
| 193 | static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq, | 276 | static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq, |
| 194 | unsigned ring, bool intr, bool lock_ring) | 277 | unsigned ring, bool intr, bool lock_ring) |
| 195 | { | 278 | { |
| @@ -285,6 +368,17 @@ static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq, | |||
| 285 | return 0; | 368 | return 0; |
| 286 | } | 369 | } |
| 287 | 370 | ||
| 371 | /** | ||
| 372 | * radeon_fence_wait - wait for a fence to signal | ||
| 373 | * | ||
| 374 | * @fence: radeon fence object | ||
| 375 | * @intr: use interruptable sleep | ||
| 376 | * | ||
| 377 | * Wait for the requested fence to signal (all asics). | ||
| 378 | * @intr selects whether to use interruptable (true) or non-interruptable | ||
| 379 | * (false) sleep when waiting for the fence. | ||
| 380 | * Returns 0 if the fence has passed, error for all other cases. | ||
| 381 | */ | ||
| 288 | int radeon_fence_wait(struct radeon_fence *fence, bool intr) | 382 | int radeon_fence_wait(struct radeon_fence *fence, bool intr) |
| 289 | { | 383 | { |
| 290 | int r; | 384 | int r; |
| @@ -315,6 +409,20 @@ bool radeon_fence_any_seq_signaled(struct radeon_device *rdev, u64 *seq) | |||
| 315 | return false; | 409 | return false; |
| 316 | } | 410 | } |
| 317 | 411 | ||
| 412 | /** | ||
| 413 | * radeon_fence_wait_any_seq - wait for a sequence number on any ring | ||
| 414 | * | ||
| 415 | * @rdev: radeon device pointer | ||
| 416 | * @target_seq: sequence number(s) we want to wait for | ||
| 417 | * @intr: use interruptable sleep | ||
| 418 | * | ||
| 419 | * Wait for the requested sequence number(s) to be written by any ring | ||
| 420 | * (all asics). Sequnce number array is indexed by ring id. | ||
| 421 | * @intr selects whether to use interruptable (true) or non-interruptable | ||
| 422 | * (false) sleep when waiting for the sequence number. Helper function | ||
| 423 | * for radeon_fence_wait_any(), et al. | ||
| 424 | * Returns 0 if the sequence number has passed, error for all other cases. | ||
| 425 | */ | ||
| 318 | static int radeon_fence_wait_any_seq(struct radeon_device *rdev, | 426 | static int radeon_fence_wait_any_seq(struct radeon_device *rdev, |
| 319 | u64 *target_seq, bool intr) | 427 | u64 *target_seq, bool intr) |
| 320 | { | 428 | { |
| @@ -343,7 +451,7 @@ static int radeon_fence_wait_any_seq(struct radeon_device *rdev, | |||
| 343 | 451 | ||
| 344 | /* nothing to wait for ? */ | 452 | /* nothing to wait for ? */ |
| 345 | if (ring == RADEON_NUM_RINGS) { | 453 | if (ring == RADEON_NUM_RINGS) { |
| 346 | return 0; | 454 | return -ENOENT; |
| 347 | } | 455 | } |
| 348 | 456 | ||
| 349 | while (!radeon_fence_any_seq_signaled(rdev, target_seq)) { | 457 | while (!radeon_fence_any_seq_signaled(rdev, target_seq)) { |
| @@ -424,6 +532,19 @@ static int radeon_fence_wait_any_seq(struct radeon_device *rdev, | |||
| 424 | return 0; | 532 | return 0; |
| 425 | } | 533 | } |
| 426 | 534 | ||
| 535 | /** | ||
| 536 | * radeon_fence_wait_any - wait for a fence to signal on any ring | ||
| 537 | * | ||
| 538 | * @rdev: radeon device pointer | ||
| 539 | * @fences: radeon fence object(s) | ||
| 540 | * @intr: use interruptable sleep | ||
| 541 | * | ||
| 542 | * Wait for any requested fence to signal (all asics). Fence | ||
| 543 | * array is indexed by ring id. @intr selects whether to use | ||
| 544 | * interruptable (true) or non-interruptable (false) sleep when | ||
| 545 | * waiting for the fences. Used by the suballocator. | ||
| 546 | * Returns 0 if any fence has passed, error for all other cases. | ||
| 547 | */ | ||
| 427 | int radeon_fence_wait_any(struct radeon_device *rdev, | 548 | int radeon_fence_wait_any(struct radeon_device *rdev, |
| 428 | struct radeon_fence **fences, | 549 | struct radeon_fence **fences, |
| 429 | bool intr) | 550 | bool intr) |
| @@ -444,9 +565,7 @@ int radeon_fence_wait_any(struct radeon_device *rdev, | |||
| 444 | return 0; | 565 | return 0; |
| 445 | } | 566 | } |
| 446 | 567 | ||
| 447 | if (fences[i]->seq < RADEON_FENCE_NOTEMITED_SEQ) { | 568 | seq[i] = fences[i]->seq; |
| 448 | seq[i] = fences[i]->seq; | ||
| 449 | } | ||
| 450 | } | 569 | } |
| 451 | 570 | ||
| 452 | r = radeon_fence_wait_any_seq(rdev, seq, intr); | 571 | r = radeon_fence_wait_any_seq(rdev, seq, intr); |
| @@ -456,16 +575,22 @@ int radeon_fence_wait_any(struct radeon_device *rdev, | |||
| 456 | return 0; | 575 | return 0; |
| 457 | } | 576 | } |
| 458 | 577 | ||
| 578 | /** | ||
| 579 | * radeon_fence_wait_next_locked - wait for the next fence to signal | ||
| 580 | * | ||
| 581 | * @rdev: radeon device pointer | ||
| 582 | * @ring: ring index the fence is associated with | ||
| 583 | * | ||
| 584 | * Wait for the next fence on the requested ring to signal (all asics). | ||
| 585 | * Returns 0 if the next fence has passed, error for all other cases. | ||
| 586 | * Caller must hold ring lock. | ||
| 587 | */ | ||
| 459 | int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring) | 588 | int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring) |
| 460 | { | 589 | { |
| 461 | uint64_t seq; | 590 | uint64_t seq; |
| 462 | 591 | ||
| 463 | /* We are not protected by ring lock when reading current seq but | ||
| 464 | * it's ok as worst case is we return to early while we could have | ||
| 465 | * wait. | ||
| 466 | */ | ||
| 467 | seq = atomic64_read(&rdev->fence_drv[ring].last_seq) + 1ULL; | 592 | seq = atomic64_read(&rdev->fence_drv[ring].last_seq) + 1ULL; |
| 468 | if (seq >= rdev->fence_drv[ring].seq) { | 593 | if (seq >= rdev->fence_drv[ring].sync_seq[ring]) { |
| 469 | /* nothing to wait for, last_seq is | 594 | /* nothing to wait for, last_seq is |
| 470 | already the last emited fence */ | 595 | already the last emited fence */ |
| 471 | return -ENOENT; | 596 | return -ENOENT; |
| @@ -473,23 +598,59 @@ int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring) | |||
| 473 | return radeon_fence_wait_seq(rdev, seq, ring, false, false); | 598 | return radeon_fence_wait_seq(rdev, seq, ring, false, false); |
| 474 | } | 599 | } |
| 475 | 600 | ||
| 476 | int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) | 601 | /** |
| 602 | * radeon_fence_wait_empty_locked - wait for all fences to signal | ||
| 603 | * | ||
| 604 | * @rdev: radeon device pointer | ||
| 605 | * @ring: ring index the fence is associated with | ||
| 606 | * | ||
| 607 | * Wait for all fences on the requested ring to signal (all asics). | ||
| 608 | * Returns 0 if the fences have passed, error for all other cases. | ||
| 609 | * Caller must hold ring lock. | ||
| 610 | */ | ||
| 611 | void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) | ||
| 477 | { | 612 | { |
| 478 | /* We are not protected by ring lock when reading current seq | 613 | uint64_t seq = rdev->fence_drv[ring].sync_seq[ring]; |
| 479 | * but it's ok as wait empty is call from place where no more | 614 | |
| 480 | * activity can be scheduled so there won't be concurrent access | 615 | while(1) { |
| 481 | * to seq value. | 616 | int r; |
| 482 | */ | 617 | r = radeon_fence_wait_seq(rdev, seq, ring, false, false); |
| 483 | return radeon_fence_wait_seq(rdev, rdev->fence_drv[ring].seq, | 618 | if (r == -EDEADLK) { |
| 484 | ring, false, false); | 619 | mutex_unlock(&rdev->ring_lock); |
| 620 | r = radeon_gpu_reset(rdev); | ||
| 621 | mutex_lock(&rdev->ring_lock); | ||
| 622 | if (!r) | ||
| 623 | continue; | ||
| 624 | } | ||
| 625 | if (r) { | ||
| 626 | dev_err(rdev->dev, "error waiting for ring to become" | ||
| 627 | " idle (%d)\n", r); | ||
| 628 | } | ||
| 629 | return; | ||
| 630 | } | ||
| 485 | } | 631 | } |
| 486 | 632 | ||
| 633 | /** | ||
| 634 | * radeon_fence_ref - take a ref on a fence | ||
| 635 | * | ||
| 636 | * @fence: radeon fence object | ||
| 637 | * | ||
| 638 | * Take a reference on a fence (all asics). | ||
| 639 | * Returns the fence. | ||
| 640 | */ | ||
| 487 | struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence) | 641 | struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence) |
| 488 | { | 642 | { |
| 489 | kref_get(&fence->kref); | 643 | kref_get(&fence->kref); |
| 490 | return fence; | 644 | return fence; |
| 491 | } | 645 | } |
| 492 | 646 | ||
| 647 | /** | ||
| 648 | * radeon_fence_unref - remove a ref on a fence | ||
| 649 | * | ||
| 650 | * @fence: radeon fence object | ||
| 651 | * | ||
| 652 | * Remove a reference on a fence (all asics). | ||
| 653 | */ | ||
| 493 | void radeon_fence_unref(struct radeon_fence **fence) | 654 | void radeon_fence_unref(struct radeon_fence **fence) |
| 494 | { | 655 | { |
| 495 | struct radeon_fence *tmp = *fence; | 656 | struct radeon_fence *tmp = *fence; |
| @@ -500,6 +661,16 @@ void radeon_fence_unref(struct radeon_fence **fence) | |||
| 500 | } | 661 | } |
| 501 | } | 662 | } |
| 502 | 663 | ||
| 664 | /** | ||
| 665 | * radeon_fence_count_emitted - get the count of emitted fences | ||
| 666 | * | ||
| 667 | * @rdev: radeon device pointer | ||
| 668 | * @ring: ring index the fence is associated with | ||
| 669 | * | ||
| 670 | * Get the number of fences emitted on the requested ring (all asics). | ||
| 671 | * Returns the number of emitted fences on the ring. Used by the | ||
| 672 | * dynpm code to ring track activity. | ||
| 673 | */ | ||
| 503 | unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring) | 674 | unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring) |
| 504 | { | 675 | { |
| 505 | uint64_t emitted; | 676 | uint64_t emitted; |
| @@ -508,7 +679,8 @@ unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring) | |||
| 508 | * but it's ok to report slightly wrong fence count here. | 679 | * but it's ok to report slightly wrong fence count here. |
| 509 | */ | 680 | */ |
| 510 | radeon_fence_process(rdev, ring); | 681 | radeon_fence_process(rdev, ring); |
| 511 | emitted = rdev->fence_drv[ring].seq - atomic64_read(&rdev->fence_drv[ring].last_seq); | 682 | emitted = rdev->fence_drv[ring].sync_seq[ring] |
| 683 | - atomic64_read(&rdev->fence_drv[ring].last_seq); | ||
| 512 | /* to avoid 32bits warp around */ | 684 | /* to avoid 32bits warp around */ |
| 513 | if (emitted > 0x10000000) { | 685 | if (emitted > 0x10000000) { |
| 514 | emitted = 0x10000000; | 686 | emitted = 0x10000000; |
| @@ -516,6 +688,83 @@ unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring) | |||
| 516 | return (unsigned)emitted; | 688 | return (unsigned)emitted; |
| 517 | } | 689 | } |
| 518 | 690 | ||
| 691 | /** | ||
| 692 | * radeon_fence_need_sync - do we need a semaphore | ||
| 693 | * | ||
| 694 | * @fence: radeon fence object | ||
| 695 | * @dst_ring: which ring to check against | ||
| 696 | * | ||
| 697 | * Check if the fence needs to be synced against another ring | ||
| 698 | * (all asics). If so, we need to emit a semaphore. | ||
| 699 | * Returns true if we need to sync with another ring, false if | ||
| 700 | * not. | ||
| 701 | */ | ||
| 702 | bool radeon_fence_need_sync(struct radeon_fence *fence, int dst_ring) | ||
| 703 | { | ||
| 704 | struct radeon_fence_driver *fdrv; | ||
| 705 | |||
| 706 | if (!fence) { | ||
| 707 | return false; | ||
| 708 | } | ||
| 709 | |||
| 710 | if (fence->ring == dst_ring) { | ||
| 711 | return false; | ||
| 712 | } | ||
| 713 | |||
| 714 | /* we are protected by the ring mutex */ | ||
| 715 | fdrv = &fence->rdev->fence_drv[dst_ring]; | ||
| 716 | if (fence->seq <= fdrv->sync_seq[fence->ring]) { | ||
| 717 | return false; | ||
| 718 | } | ||
| 719 | |||
| 720 | return true; | ||
| 721 | } | ||
| 722 | |||
| 723 | /** | ||
| 724 | * radeon_fence_note_sync - record the sync point | ||
| 725 | * | ||
| 726 | * @fence: radeon fence object | ||
| 727 | * @dst_ring: which ring to check against | ||
| 728 | * | ||
| 729 | * Note the sequence number at which point the fence will | ||
| 730 | * be synced with the requested ring (all asics). | ||
| 731 | */ | ||
| 732 | void radeon_fence_note_sync(struct radeon_fence *fence, int dst_ring) | ||
| 733 | { | ||
| 734 | struct radeon_fence_driver *dst, *src; | ||
| 735 | unsigned i; | ||
| 736 | |||
| 737 | if (!fence) { | ||
| 738 | return; | ||
| 739 | } | ||
| 740 | |||
| 741 | if (fence->ring == dst_ring) { | ||
| 742 | return; | ||
| 743 | } | ||
| 744 | |||
| 745 | /* we are protected by the ring mutex */ | ||
| 746 | src = &fence->rdev->fence_drv[fence->ring]; | ||
| 747 | dst = &fence->rdev->fence_drv[dst_ring]; | ||
| 748 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | ||
| 749 | if (i == dst_ring) { | ||
| 750 | continue; | ||
| 751 | } | ||
| 752 | dst->sync_seq[i] = max(dst->sync_seq[i], src->sync_seq[i]); | ||
| 753 | } | ||
| 754 | } | ||
| 755 | |||
| 756 | /** | ||
| 757 | * radeon_fence_driver_start_ring - make the fence driver | ||
| 758 | * ready for use on the requested ring. | ||
| 759 | * | ||
| 760 | * @rdev: radeon device pointer | ||
| 761 | * @ring: ring index to start the fence driver on | ||
| 762 | * | ||
| 763 | * Make the fence driver ready for processing (all asics). | ||
| 764 | * Not all asics have all rings, so each asic will only | ||
| 765 | * start the fence driver on the rings it has. | ||
| 766 | * Returns 0 for success, errors for failure. | ||
| 767 | */ | ||
| 519 | int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) | 768 | int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) |
| 520 | { | 769 | { |
| 521 | uint64_t index; | 770 | uint64_t index; |
| @@ -537,24 +786,49 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) | |||
| 537 | } | 786 | } |
| 538 | rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4]; | 787 | rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4]; |
| 539 | rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr + index; | 788 | rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr + index; |
| 540 | radeon_fence_write(rdev, rdev->fence_drv[ring].seq, ring); | 789 | radeon_fence_write(rdev, atomic64_read(&rdev->fence_drv[ring].last_seq), ring); |
| 541 | rdev->fence_drv[ring].initialized = true; | 790 | rdev->fence_drv[ring].initialized = true; |
| 542 | dev_info(rdev->dev, "fence driver on ring %d use gpu addr 0x%016llx and cpu addr 0x%p\n", | 791 | dev_info(rdev->dev, "fence driver on ring %d use gpu addr 0x%016llx and cpu addr 0x%p\n", |
| 543 | ring, rdev->fence_drv[ring].gpu_addr, rdev->fence_drv[ring].cpu_addr); | 792 | ring, rdev->fence_drv[ring].gpu_addr, rdev->fence_drv[ring].cpu_addr); |
| 544 | return 0; | 793 | return 0; |
| 545 | } | 794 | } |
| 546 | 795 | ||
| 796 | /** | ||
| 797 | * radeon_fence_driver_init_ring - init the fence driver | ||
| 798 | * for the requested ring. | ||
| 799 | * | ||
| 800 | * @rdev: radeon device pointer | ||
| 801 | * @ring: ring index to start the fence driver on | ||
| 802 | * | ||
| 803 | * Init the fence driver for the requested ring (all asics). | ||
| 804 | * Helper function for radeon_fence_driver_init(). | ||
| 805 | */ | ||
| 547 | static void radeon_fence_driver_init_ring(struct radeon_device *rdev, int ring) | 806 | static void radeon_fence_driver_init_ring(struct radeon_device *rdev, int ring) |
| 548 | { | 807 | { |
| 808 | int i; | ||
| 809 | |||
| 549 | rdev->fence_drv[ring].scratch_reg = -1; | 810 | rdev->fence_drv[ring].scratch_reg = -1; |
| 550 | rdev->fence_drv[ring].cpu_addr = NULL; | 811 | rdev->fence_drv[ring].cpu_addr = NULL; |
| 551 | rdev->fence_drv[ring].gpu_addr = 0; | 812 | rdev->fence_drv[ring].gpu_addr = 0; |
| 552 | rdev->fence_drv[ring].seq = 0; | 813 | for (i = 0; i < RADEON_NUM_RINGS; ++i) |
| 814 | rdev->fence_drv[ring].sync_seq[i] = 0; | ||
| 553 | atomic64_set(&rdev->fence_drv[ring].last_seq, 0); | 815 | atomic64_set(&rdev->fence_drv[ring].last_seq, 0); |
| 554 | rdev->fence_drv[ring].last_activity = jiffies; | 816 | rdev->fence_drv[ring].last_activity = jiffies; |
| 555 | rdev->fence_drv[ring].initialized = false; | 817 | rdev->fence_drv[ring].initialized = false; |
| 556 | } | 818 | } |
| 557 | 819 | ||
| 820 | /** | ||
| 821 | * radeon_fence_driver_init - init the fence driver | ||
| 822 | * for all possible rings. | ||
| 823 | * | ||
| 824 | * @rdev: radeon device pointer | ||
| 825 | * | ||
| 826 | * Init the fence driver for all possible rings (all asics). | ||
| 827 | * Not all asics have all rings, so each asic will only | ||
| 828 | * start the fence driver on the rings it has using | ||
| 829 | * radeon_fence_driver_start_ring(). | ||
| 830 | * Returns 0 for success. | ||
| 831 | */ | ||
| 558 | int radeon_fence_driver_init(struct radeon_device *rdev) | 832 | int radeon_fence_driver_init(struct radeon_device *rdev) |
| 559 | { | 833 | { |
| 560 | int ring; | 834 | int ring; |
| @@ -569,6 +843,14 @@ int radeon_fence_driver_init(struct radeon_device *rdev) | |||
| 569 | return 0; | 843 | return 0; |
| 570 | } | 844 | } |
| 571 | 845 | ||
| 846 | /** | ||
| 847 | * radeon_fence_driver_fini - tear down the fence driver | ||
| 848 | * for all possible rings. | ||
| 849 | * | ||
| 850 | * @rdev: radeon device pointer | ||
| 851 | * | ||
| 852 | * Tear down the fence driver for all possible rings (all asics). | ||
| 853 | */ | ||
| 572 | void radeon_fence_driver_fini(struct radeon_device *rdev) | 854 | void radeon_fence_driver_fini(struct radeon_device *rdev) |
| 573 | { | 855 | { |
| 574 | int ring; | 856 | int ring; |
| @@ -595,7 +877,7 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data) | |||
| 595 | struct drm_info_node *node = (struct drm_info_node *)m->private; | 877 | struct drm_info_node *node = (struct drm_info_node *)m->private; |
| 596 | struct drm_device *dev = node->minor->dev; | 878 | struct drm_device *dev = node->minor->dev; |
| 597 | struct radeon_device *rdev = dev->dev_private; | 879 | struct radeon_device *rdev = dev->dev_private; |
| 598 | int i; | 880 | int i, j; |
| 599 | 881 | ||
| 600 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | 882 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
| 601 | if (!rdev->fence_drv[i].initialized) | 883 | if (!rdev->fence_drv[i].initialized) |
| @@ -604,8 +886,14 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data) | |||
| 604 | seq_printf(m, "--- ring %d ---\n", i); | 886 | seq_printf(m, "--- ring %d ---\n", i); |
| 605 | seq_printf(m, "Last signaled fence 0x%016llx\n", | 887 | seq_printf(m, "Last signaled fence 0x%016llx\n", |
| 606 | (unsigned long long)atomic64_read(&rdev->fence_drv[i].last_seq)); | 888 | (unsigned long long)atomic64_read(&rdev->fence_drv[i].last_seq)); |
| 607 | seq_printf(m, "Last emitted 0x%016llx\n", | 889 | seq_printf(m, "Last emitted 0x%016llx\n", |
| 608 | rdev->fence_drv[i].seq); | 890 | rdev->fence_drv[i].sync_seq[i]); |
| 891 | |||
| 892 | for (j = 0; j < RADEON_NUM_RINGS; ++j) { | ||
| 893 | if (i != j && rdev->fence_drv[j].initialized) | ||
| 894 | seq_printf(m, "Last sync to ring %d 0x%016llx\n", | ||
| 895 | j, rdev->fence_drv[i].sync_seq[j]); | ||
| 896 | } | ||
| 609 | } | 897 | } |
| 610 | return 0; | 898 | return 0; |
| 611 | } | 899 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 84b648a7ddd8..b3720054614d 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c | |||
| @@ -31,8 +31,38 @@ | |||
| 31 | #include "radeon_reg.h" | 31 | #include "radeon_reg.h" |
| 32 | 32 | ||
| 33 | /* | 33 | /* |
| 34 | * GART | ||
| 35 | * The GART (Graphics Aperture Remapping Table) is an aperture | ||
| 36 | * in the GPU's address space. System pages can be mapped into | ||
| 37 | * the aperture and look like contiguous pages from the GPU's | ||
| 38 | * perspective. A page table maps the pages in the aperture | ||
| 39 | * to the actual backing pages in system memory. | ||
| 40 | * | ||
| 41 | * Radeon GPUs support both an internal GART, as described above, | ||
| 42 | * and AGP. AGP works similarly, but the GART table is configured | ||
| 43 | * and maintained by the northbridge rather than the driver. | ||
| 44 | * Radeon hw has a separate AGP aperture that is programmed to | ||
| 45 | * point to the AGP aperture provided by the northbridge and the | ||
| 46 | * requests are passed through to the northbridge aperture. | ||
| 47 | * Both AGP and internal GART can be used at the same time, however | ||
| 48 | * that is not currently supported by the driver. | ||
| 49 | * | ||
| 50 | * This file handles the common internal GART management. | ||
| 51 | */ | ||
| 52 | |||
| 53 | /* | ||
| 34 | * Common GART table functions. | 54 | * Common GART table functions. |
| 35 | */ | 55 | */ |
| 56 | /** | ||
| 57 | * radeon_gart_table_ram_alloc - allocate system ram for gart page table | ||
| 58 | * | ||
| 59 | * @rdev: radeon_device pointer | ||
| 60 | * | ||
| 61 | * Allocate system memory for GART page table | ||
| 62 | * (r1xx-r3xx, non-pcie r4xx, rs400). These asics require the | ||
| 63 | * gart table to be in system memory. | ||
| 64 | * Returns 0 for success, -ENOMEM for failure. | ||
| 65 | */ | ||
| 36 | int radeon_gart_table_ram_alloc(struct radeon_device *rdev) | 66 | int radeon_gart_table_ram_alloc(struct radeon_device *rdev) |
| 37 | { | 67 | { |
| 38 | void *ptr; | 68 | void *ptr; |
| @@ -54,6 +84,15 @@ int radeon_gart_table_ram_alloc(struct radeon_device *rdev) | |||
| 54 | return 0; | 84 | return 0; |
| 55 | } | 85 | } |
| 56 | 86 | ||
| 87 | /** | ||
| 88 | * radeon_gart_table_ram_free - free system ram for gart page table | ||
| 89 | * | ||
| 90 | * @rdev: radeon_device pointer | ||
| 91 | * | ||
| 92 | * Free system memory for GART page table | ||
| 93 | * (r1xx-r3xx, non-pcie r4xx, rs400). These asics require the | ||
| 94 | * gart table to be in system memory. | ||
| 95 | */ | ||
| 57 | void radeon_gart_table_ram_free(struct radeon_device *rdev) | 96 | void radeon_gart_table_ram_free(struct radeon_device *rdev) |
| 58 | { | 97 | { |
| 59 | if (rdev->gart.ptr == NULL) { | 98 | if (rdev->gart.ptr == NULL) { |
| @@ -73,6 +112,16 @@ void radeon_gart_table_ram_free(struct radeon_device *rdev) | |||
| 73 | rdev->gart.table_addr = 0; | 112 | rdev->gart.table_addr = 0; |
| 74 | } | 113 | } |
| 75 | 114 | ||
| 115 | /** | ||
| 116 | * radeon_gart_table_vram_alloc - allocate vram for gart page table | ||
| 117 | * | ||
| 118 | * @rdev: radeon_device pointer | ||
| 119 | * | ||
| 120 | * Allocate video memory for GART page table | ||
| 121 | * (pcie r4xx, r5xx+). These asics require the | ||
| 122 | * gart table to be in video memory. | ||
| 123 | * Returns 0 for success, error for failure. | ||
| 124 | */ | ||
| 76 | int radeon_gart_table_vram_alloc(struct radeon_device *rdev) | 125 | int radeon_gart_table_vram_alloc(struct radeon_device *rdev) |
| 77 | { | 126 | { |
| 78 | int r; | 127 | int r; |
| @@ -88,6 +137,16 @@ int radeon_gart_table_vram_alloc(struct radeon_device *rdev) | |||
| 88 | return 0; | 137 | return 0; |
| 89 | } | 138 | } |
| 90 | 139 | ||
| 140 | /** | ||
| 141 | * radeon_gart_table_vram_pin - pin gart page table in vram | ||
| 142 | * | ||
| 143 | * @rdev: radeon_device pointer | ||
| 144 | * | ||
| 145 | * Pin the GART page table in vram so it will not be moved | ||
| 146 | * by the memory manager (pcie r4xx, r5xx+). These asics require the | ||
| 147 | * gart table to be in video memory. | ||
| 148 | * Returns 0 for success, error for failure. | ||
| 149 | */ | ||
| 91 | int radeon_gart_table_vram_pin(struct radeon_device *rdev) | 150 | int radeon_gart_table_vram_pin(struct radeon_device *rdev) |
| 92 | { | 151 | { |
| 93 | uint64_t gpu_addr; | 152 | uint64_t gpu_addr; |
| @@ -110,6 +169,14 @@ int radeon_gart_table_vram_pin(struct radeon_device *rdev) | |||
| 110 | return r; | 169 | return r; |
| 111 | } | 170 | } |
| 112 | 171 | ||
| 172 | /** | ||
| 173 | * radeon_gart_table_vram_unpin - unpin gart page table in vram | ||
| 174 | * | ||
| 175 | * @rdev: radeon_device pointer | ||
| 176 | * | ||
| 177 | * Unpin the GART page table in vram (pcie r4xx, r5xx+). | ||
| 178 | * These asics require the gart table to be in video memory. | ||
| 179 | */ | ||
| 113 | void radeon_gart_table_vram_unpin(struct radeon_device *rdev) | 180 | void radeon_gart_table_vram_unpin(struct radeon_device *rdev) |
| 114 | { | 181 | { |
| 115 | int r; | 182 | int r; |
| @@ -126,6 +193,15 @@ void radeon_gart_table_vram_unpin(struct radeon_device *rdev) | |||
| 126 | } | 193 | } |
| 127 | } | 194 | } |
| 128 | 195 | ||
| 196 | /** | ||
| 197 | * radeon_gart_table_vram_free - free gart page table vram | ||
| 198 | * | ||
| 199 | * @rdev: radeon_device pointer | ||
| 200 | * | ||
| 201 | * Free the video memory used for the GART page table | ||
| 202 | * (pcie r4xx, r5xx+). These asics require the gart table to | ||
| 203 | * be in video memory. | ||
| 204 | */ | ||
| 129 | void radeon_gart_table_vram_free(struct radeon_device *rdev) | 205 | void radeon_gart_table_vram_free(struct radeon_device *rdev) |
| 130 | { | 206 | { |
| 131 | if (rdev->gart.robj == NULL) { | 207 | if (rdev->gart.robj == NULL) { |
| @@ -135,12 +211,19 @@ void radeon_gart_table_vram_free(struct radeon_device *rdev) | |||
| 135 | radeon_bo_unref(&rdev->gart.robj); | 211 | radeon_bo_unref(&rdev->gart.robj); |
| 136 | } | 212 | } |
| 137 | 213 | ||
| 138 | |||
| 139 | |||
| 140 | |||
| 141 | /* | 214 | /* |
| 142 | * Common gart functions. | 215 | * Common gart functions. |
| 143 | */ | 216 | */ |
| 217 | /** | ||
| 218 | * radeon_gart_unbind - unbind pages from the gart page table | ||
| 219 | * | ||
| 220 | * @rdev: radeon_device pointer | ||
| 221 | * @offset: offset into the GPU's gart aperture | ||
| 222 | * @pages: number of pages to unbind | ||
| 223 | * | ||
| 224 | * Unbinds the requested pages from the gart page table and | ||
| 225 | * replaces them with the dummy page (all asics). | ||
| 226 | */ | ||
| 144 | void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, | 227 | void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, |
| 145 | int pages) | 228 | int pages) |
| 146 | { | 229 | { |
| @@ -172,6 +255,19 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, | |||
| 172 | radeon_gart_tlb_flush(rdev); | 255 | radeon_gart_tlb_flush(rdev); |
| 173 | } | 256 | } |
| 174 | 257 | ||
| 258 | /** | ||
| 259 | * radeon_gart_bind - bind pages into the gart page table | ||
| 260 | * | ||
| 261 | * @rdev: radeon_device pointer | ||
| 262 | * @offset: offset into the GPU's gart aperture | ||
| 263 | * @pages: number of pages to bind | ||
| 264 | * @pagelist: pages to bind | ||
| 265 | * @dma_addr: DMA addresses of pages | ||
| 266 | * | ||
| 267 | * Binds the requested pages to the gart page table | ||
| 268 | * (all asics). | ||
| 269 | * Returns 0 for success, -EINVAL for failure. | ||
| 270 | */ | ||
| 175 | int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, | 271 | int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, |
| 176 | int pages, struct page **pagelist, dma_addr_t *dma_addr) | 272 | int pages, struct page **pagelist, dma_addr_t *dma_addr) |
| 177 | { | 273 | { |
| @@ -203,6 +299,14 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, | |||
| 203 | return 0; | 299 | return 0; |
| 204 | } | 300 | } |
| 205 | 301 | ||
| 302 | /** | ||
| 303 | * radeon_gart_restore - bind all pages in the gart page table | ||
| 304 | * | ||
| 305 | * @rdev: radeon_device pointer | ||
| 306 | * | ||
| 307 | * Binds all pages in the gart page table (all asics). | ||
| 308 | * Used to rebuild the gart table on device startup or resume. | ||
| 309 | */ | ||
| 206 | void radeon_gart_restore(struct radeon_device *rdev) | 310 | void radeon_gart_restore(struct radeon_device *rdev) |
| 207 | { | 311 | { |
| 208 | int i, j, t; | 312 | int i, j, t; |
| @@ -222,6 +326,14 @@ void radeon_gart_restore(struct radeon_device *rdev) | |||
| 222 | radeon_gart_tlb_flush(rdev); | 326 | radeon_gart_tlb_flush(rdev); |
| 223 | } | 327 | } |
| 224 | 328 | ||
| 329 | /** | ||
| 330 | * radeon_gart_init - init the driver info for managing the gart | ||
| 331 | * | ||
| 332 | * @rdev: radeon_device pointer | ||
| 333 | * | ||
| 334 | * Allocate the dummy page and init the gart driver info (all asics). | ||
| 335 | * Returns 0 for success, error for failure. | ||
| 336 | */ | ||
| 225 | int radeon_gart_init(struct radeon_device *rdev) | 337 | int radeon_gart_init(struct radeon_device *rdev) |
| 226 | { | 338 | { |
| 227 | int r, i; | 339 | int r, i; |
| @@ -262,6 +374,13 @@ int radeon_gart_init(struct radeon_device *rdev) | |||
| 262 | return 0; | 374 | return 0; |
| 263 | } | 375 | } |
| 264 | 376 | ||
| 377 | /** | ||
| 378 | * radeon_gart_fini - tear down the driver info for managing the gart | ||
| 379 | * | ||
| 380 | * @rdev: radeon_device pointer | ||
| 381 | * | ||
| 382 | * Tear down the gart driver info and free the dummy page (all asics). | ||
| 383 | */ | ||
| 265 | void radeon_gart_fini(struct radeon_device *rdev) | 384 | void radeon_gart_fini(struct radeon_device *rdev) |
| 266 | { | 385 | { |
| 267 | if (rdev->gart.pages && rdev->gart.pages_addr && rdev->gart.ready) { | 386 | if (rdev->gart.pages && rdev->gart.pages_addr && rdev->gart.ready) { |
| @@ -278,35 +397,104 @@ void radeon_gart_fini(struct radeon_device *rdev) | |||
| 278 | } | 397 | } |
| 279 | 398 | ||
| 280 | /* | 399 | /* |
| 400 | * GPUVM | ||
| 401 | * GPUVM is similar to the legacy gart on older asics, however | ||
| 402 | * rather than there being a single global gart table | ||
| 403 | * for the entire GPU, there are multiple VM page tables active | ||
| 404 | * at any given time. The VM page tables can contain a mix | ||
| 405 | * vram pages and system memory pages and system memory pages | ||
| 406 | * can be mapped as snooped (cached system pages) or unsnooped | ||
| 407 | * (uncached system pages). | ||
| 408 | * Each VM has an ID associated with it and there is a page table | ||
| 409 | * associated with each VMID. When execting a command buffer, | ||
| 410 | * the kernel tells the the ring what VMID to use for that command | ||
| 411 | * buffer. VMIDs are allocated dynamically as commands are submitted. | ||
| 412 | * The userspace drivers maintain their own address space and the kernel | ||
| 413 | * sets up their pages tables accordingly when they submit their | ||
| 414 | * command buffers and a VMID is assigned. | ||
| 415 | * Cayman/Trinity support up to 8 active VMs at any given time; | ||
| 416 | * SI supports 16. | ||
| 417 | */ | ||
| 418 | |||
| 419 | /* | ||
| 281 | * vm helpers | 420 | * vm helpers |
| 282 | * | 421 | * |
| 283 | * TODO bind a default page at vm initialization for default address | 422 | * TODO bind a default page at vm initialization for default address |
| 284 | */ | 423 | */ |
| 424 | |||
| 425 | /** | ||
| 426 | * radeon_vm_manager_init - init the vm manager | ||
| 427 | * | ||
| 428 | * @rdev: radeon_device pointer | ||
| 429 | * | ||
| 430 | * Init the vm manager (cayman+). | ||
| 431 | * Returns 0 for success, error for failure. | ||
| 432 | */ | ||
| 285 | int radeon_vm_manager_init(struct radeon_device *rdev) | 433 | int radeon_vm_manager_init(struct radeon_device *rdev) |
| 286 | { | 434 | { |
| 435 | struct radeon_vm *vm; | ||
| 436 | struct radeon_bo_va *bo_va; | ||
| 287 | int r; | 437 | int r; |
| 288 | 438 | ||
| 289 | rdev->vm_manager.enabled = false; | 439 | if (!rdev->vm_manager.enabled) { |
| 440 | /* mark first vm as always in use, it's the system one */ | ||
| 441 | /* allocate enough for 2 full VM pts */ | ||
| 442 | r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager, | ||
| 443 | rdev->vm_manager.max_pfn * 8 * 2, | ||
| 444 | RADEON_GEM_DOMAIN_VRAM); | ||
| 445 | if (r) { | ||
| 446 | dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n", | ||
| 447 | (rdev->vm_manager.max_pfn * 8) >> 10); | ||
| 448 | return r; | ||
| 449 | } | ||
| 290 | 450 | ||
| 291 | /* mark first vm as always in use, it's the system one */ | 451 | r = rdev->vm_manager.funcs->init(rdev); |
| 292 | /* allocate enough for 2 full VM pts */ | 452 | if (r) |
| 293 | r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager, | 453 | return r; |
| 294 | rdev->vm_manager.max_pfn * 8 * 2, | 454 | |
| 295 | RADEON_GEM_DOMAIN_VRAM); | 455 | rdev->vm_manager.enabled = true; |
| 296 | if (r) { | 456 | |
| 297 | dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n", | 457 | r = radeon_sa_bo_manager_start(rdev, &rdev->vm_manager.sa_manager); |
| 298 | (rdev->vm_manager.max_pfn * 8) >> 10); | 458 | if (r) |
| 299 | return r; | 459 | return r; |
| 300 | } | 460 | } |
| 301 | 461 | ||
| 302 | r = rdev->vm_manager.funcs->init(rdev); | 462 | /* restore page table */ |
| 303 | if (r == 0) | 463 | list_for_each_entry(vm, &rdev->vm_manager.lru_vm, list) { |
| 304 | rdev->vm_manager.enabled = true; | 464 | if (vm->id == -1) |
| 465 | continue; | ||
| 305 | 466 | ||
| 306 | return r; | 467 | list_for_each_entry(bo_va, &vm->va, vm_list) { |
| 468 | struct ttm_mem_reg *mem = NULL; | ||
| 469 | if (bo_va->valid) | ||
| 470 | mem = &bo_va->bo->tbo.mem; | ||
| 471 | |||
| 472 | bo_va->valid = false; | ||
| 473 | r = radeon_vm_bo_update_pte(rdev, vm, bo_va->bo, mem); | ||
| 474 | if (r) { | ||
| 475 | DRM_ERROR("Failed to update pte for vm %d!\n", vm->id); | ||
| 476 | } | ||
| 477 | } | ||
| 478 | |||
| 479 | r = rdev->vm_manager.funcs->bind(rdev, vm, vm->id); | ||
| 480 | if (r) { | ||
| 481 | DRM_ERROR("Failed to bind vm %d!\n", vm->id); | ||
| 482 | } | ||
| 483 | } | ||
| 484 | return 0; | ||
| 307 | } | 485 | } |
| 308 | 486 | ||
| 309 | /* cs mutex must be lock */ | 487 | /* global mutex must be lock */ |
| 488 | /** | ||
| 489 | * radeon_vm_unbind_locked - unbind a specific vm | ||
| 490 | * | ||
| 491 | * @rdev: radeon_device pointer | ||
| 492 | * @vm: vm to unbind | ||
| 493 | * | ||
| 494 | * Unbind the requested vm (cayman+). | ||
| 495 | * Wait for use of the VM to finish, then unbind the page table, | ||
| 496 | * and free the page table memory. | ||
| 497 | */ | ||
| 310 | static void radeon_vm_unbind_locked(struct radeon_device *rdev, | 498 | static void radeon_vm_unbind_locked(struct radeon_device *rdev, |
| 311 | struct radeon_vm *vm) | 499 | struct radeon_vm *vm) |
| 312 | { | 500 | { |
| @@ -317,10 +505,21 @@ static void radeon_vm_unbind_locked(struct radeon_device *rdev, | |||
| 317 | } | 505 | } |
| 318 | 506 | ||
| 319 | /* wait for vm use to end */ | 507 | /* wait for vm use to end */ |
| 320 | if (vm->fence) { | 508 | while (vm->fence) { |
| 321 | radeon_fence_wait(vm->fence, false); | 509 | int r; |
| 322 | radeon_fence_unref(&vm->fence); | 510 | r = radeon_fence_wait(vm->fence, false); |
| 511 | if (r) | ||
| 512 | DRM_ERROR("error while waiting for fence: %d\n", r); | ||
| 513 | if (r == -EDEADLK) { | ||
| 514 | mutex_unlock(&rdev->vm_manager.lock); | ||
| 515 | r = radeon_gpu_reset(rdev); | ||
| 516 | mutex_lock(&rdev->vm_manager.lock); | ||
| 517 | if (!r) | ||
| 518 | continue; | ||
| 519 | } | ||
| 520 | break; | ||
| 323 | } | 521 | } |
| 522 | radeon_fence_unref(&vm->fence); | ||
| 324 | 523 | ||
| 325 | /* hw unbind */ | 524 | /* hw unbind */ |
| 326 | rdev->vm_manager.funcs->unbind(rdev, vm); | 525 | rdev->vm_manager.funcs->unbind(rdev, vm); |
| @@ -335,39 +534,42 @@ static void radeon_vm_unbind_locked(struct radeon_device *rdev, | |||
| 335 | } | 534 | } |
| 336 | } | 535 | } |
| 337 | 536 | ||
| 537 | /** | ||
| 538 | * radeon_vm_manager_fini - tear down the vm manager | ||
| 539 | * | ||
| 540 | * @rdev: radeon_device pointer | ||
| 541 | * | ||
| 542 | * Tear down the VM manager (cayman+). | ||
| 543 | */ | ||
| 338 | void radeon_vm_manager_fini(struct radeon_device *rdev) | 544 | void radeon_vm_manager_fini(struct radeon_device *rdev) |
| 339 | { | 545 | { |
| 340 | if (rdev->vm_manager.sa_manager.bo == NULL) | ||
| 341 | return; | ||
| 342 | radeon_vm_manager_suspend(rdev); | ||
| 343 | rdev->vm_manager.funcs->fini(rdev); | ||
| 344 | radeon_sa_bo_manager_fini(rdev, &rdev->vm_manager.sa_manager); | ||
| 345 | rdev->vm_manager.enabled = false; | ||
| 346 | } | ||
| 347 | |||
| 348 | int radeon_vm_manager_start(struct radeon_device *rdev) | ||
| 349 | { | ||
| 350 | if (rdev->vm_manager.sa_manager.bo == NULL) { | ||
| 351 | return -EINVAL; | ||
| 352 | } | ||
| 353 | return radeon_sa_bo_manager_start(rdev, &rdev->vm_manager.sa_manager); | ||
| 354 | } | ||
| 355 | |||
| 356 | int radeon_vm_manager_suspend(struct radeon_device *rdev) | ||
| 357 | { | ||
| 358 | struct radeon_vm *vm, *tmp; | 546 | struct radeon_vm *vm, *tmp; |
| 359 | 547 | ||
| 360 | radeon_mutex_lock(&rdev->cs_mutex); | 548 | if (!rdev->vm_manager.enabled) |
| 549 | return; | ||
| 550 | |||
| 551 | mutex_lock(&rdev->vm_manager.lock); | ||
| 361 | /* unbind all active vm */ | 552 | /* unbind all active vm */ |
| 362 | list_for_each_entry_safe(vm, tmp, &rdev->vm_manager.lru_vm, list) { | 553 | list_for_each_entry_safe(vm, tmp, &rdev->vm_manager.lru_vm, list) { |
| 363 | radeon_vm_unbind_locked(rdev, vm); | 554 | radeon_vm_unbind_locked(rdev, vm); |
| 364 | } | 555 | } |
| 365 | rdev->vm_manager.funcs->fini(rdev); | 556 | rdev->vm_manager.funcs->fini(rdev); |
| 366 | radeon_mutex_unlock(&rdev->cs_mutex); | 557 | mutex_unlock(&rdev->vm_manager.lock); |
| 367 | return radeon_sa_bo_manager_suspend(rdev, &rdev->vm_manager.sa_manager); | 558 | |
| 559 | radeon_sa_bo_manager_suspend(rdev, &rdev->vm_manager.sa_manager); | ||
| 560 | radeon_sa_bo_manager_fini(rdev, &rdev->vm_manager.sa_manager); | ||
| 561 | rdev->vm_manager.enabled = false; | ||
| 368 | } | 562 | } |
| 369 | 563 | ||
| 370 | /* cs mutex must be lock */ | 564 | /* global mutex must be locked */ |
| 565 | /** | ||
| 566 | * radeon_vm_unbind - locked version of unbind | ||
| 567 | * | ||
| 568 | * @rdev: radeon_device pointer | ||
| 569 | * @vm: vm to unbind | ||
| 570 | * | ||
| 571 | * Locked version that wraps radeon_vm_unbind_locked (cayman+). | ||
| 572 | */ | ||
| 371 | void radeon_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm) | 573 | void radeon_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm) |
| 372 | { | 574 | { |
| 373 | mutex_lock(&vm->mutex); | 575 | mutex_lock(&vm->mutex); |
| @@ -375,7 +577,19 @@ void radeon_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm) | |||
| 375 | mutex_unlock(&vm->mutex); | 577 | mutex_unlock(&vm->mutex); |
| 376 | } | 578 | } |
| 377 | 579 | ||
| 378 | /* cs mutex must be lock & vm mutex must be lock */ | 580 | /* global and local mutex must be locked */ |
| 581 | /** | ||
| 582 | * radeon_vm_bind - bind a page table to a VMID | ||
| 583 | * | ||
| 584 | * @rdev: radeon_device pointer | ||
| 585 | * @vm: vm to bind | ||
| 586 | * | ||
| 587 | * Bind the requested vm (cayman+). | ||
| 588 | * Suballocate memory for the page table, allocate a VMID | ||
| 589 | * and bind the page table to it, and finally start to populate | ||
| 590 | * the page table. | ||
| 591 | * Returns 0 for success, error for failure. | ||
| 592 | */ | ||
| 379 | int radeon_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm) | 593 | int radeon_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm) |
| 380 | { | 594 | { |
| 381 | struct radeon_vm *vm_evict; | 595 | struct radeon_vm *vm_evict; |
| @@ -438,6 +652,20 @@ retry_id: | |||
| 438 | } | 652 | } |
| 439 | 653 | ||
| 440 | /* object have to be reserved */ | 654 | /* object have to be reserved */ |
| 655 | /** | ||
| 656 | * radeon_vm_bo_add - add a bo to a specific vm | ||
| 657 | * | ||
| 658 | * @rdev: radeon_device pointer | ||
| 659 | * @vm: requested vm | ||
| 660 | * @bo: radeon buffer object | ||
| 661 | * @offset: requested offset of the buffer in the VM address space | ||
| 662 | * @flags: attributes of pages (read/write/valid/etc.) | ||
| 663 | * | ||
| 664 | * Add @bo into the requested vm (cayman+). | ||
| 665 | * Add @bo to the list of bos associated with the vm and validate | ||
| 666 | * the offset requested within the vm address space. | ||
| 667 | * Returns 0 for success, error for failure. | ||
| 668 | */ | ||
| 441 | int radeon_vm_bo_add(struct radeon_device *rdev, | 669 | int radeon_vm_bo_add(struct radeon_device *rdev, |
| 442 | struct radeon_vm *vm, | 670 | struct radeon_vm *vm, |
| 443 | struct radeon_bo *bo, | 671 | struct radeon_bo *bo, |
| @@ -479,7 +707,7 @@ int radeon_vm_bo_add(struct radeon_device *rdev, | |||
| 479 | if (last_pfn > vm->last_pfn) { | 707 | if (last_pfn > vm->last_pfn) { |
| 480 | /* release mutex and lock in right order */ | 708 | /* release mutex and lock in right order */ |
| 481 | mutex_unlock(&vm->mutex); | 709 | mutex_unlock(&vm->mutex); |
| 482 | radeon_mutex_lock(&rdev->cs_mutex); | 710 | mutex_lock(&rdev->vm_manager.lock); |
| 483 | mutex_lock(&vm->mutex); | 711 | mutex_lock(&vm->mutex); |
| 484 | /* and check again */ | 712 | /* and check again */ |
| 485 | if (last_pfn > vm->last_pfn) { | 713 | if (last_pfn > vm->last_pfn) { |
| @@ -488,7 +716,7 @@ int radeon_vm_bo_add(struct radeon_device *rdev, | |||
| 488 | radeon_vm_unbind_locked(rdev, vm); | 716 | radeon_vm_unbind_locked(rdev, vm); |
| 489 | vm->last_pfn = (last_pfn + align) & ~align; | 717 | vm->last_pfn = (last_pfn + align) & ~align; |
| 490 | } | 718 | } |
| 491 | radeon_mutex_unlock(&rdev->cs_mutex); | 719 | mutex_unlock(&rdev->vm_manager.lock); |
| 492 | } | 720 | } |
| 493 | head = &vm->va; | 721 | head = &vm->va; |
| 494 | last_offset = 0; | 722 | last_offset = 0; |
| @@ -515,6 +743,17 @@ int radeon_vm_bo_add(struct radeon_device *rdev, | |||
| 515 | return 0; | 743 | return 0; |
| 516 | } | 744 | } |
| 517 | 745 | ||
| 746 | /** | ||
| 747 | * radeon_vm_get_addr - get the physical address of the page | ||
| 748 | * | ||
| 749 | * @rdev: radeon_device pointer | ||
| 750 | * @mem: ttm mem | ||
| 751 | * @pfn: pfn | ||
| 752 | * | ||
| 753 | * Look up the physical address of the page that the pte resolves | ||
| 754 | * to (cayman+). | ||
| 755 | * Returns the physical address of the page. | ||
| 756 | */ | ||
| 518 | static u64 radeon_vm_get_addr(struct radeon_device *rdev, | 757 | static u64 radeon_vm_get_addr(struct radeon_device *rdev, |
| 519 | struct ttm_mem_reg *mem, | 758 | struct ttm_mem_reg *mem, |
| 520 | unsigned pfn) | 759 | unsigned pfn) |
| @@ -543,7 +782,18 @@ static u64 radeon_vm_get_addr(struct radeon_device *rdev, | |||
| 543 | return addr; | 782 | return addr; |
| 544 | } | 783 | } |
| 545 | 784 | ||
| 546 | /* object have to be reserved & cs mutex took & vm mutex took */ | 785 | /* object have to be reserved & global and local mutex must be locked */ |
| 786 | /** | ||
| 787 | * radeon_vm_bo_update_pte - map a bo into the vm page table | ||
| 788 | * | ||
| 789 | * @rdev: radeon_device pointer | ||
| 790 | * @vm: requested vm | ||
| 791 | * @bo: radeon buffer object | ||
| 792 | * @mem: ttm mem | ||
| 793 | * | ||
| 794 | * Fill in the page table entries for @bo (cayman+). | ||
| 795 | * Returns 0 for success, -EINVAL for failure. | ||
| 796 | */ | ||
| 547 | int radeon_vm_bo_update_pte(struct radeon_device *rdev, | 797 | int radeon_vm_bo_update_pte(struct radeon_device *rdev, |
| 548 | struct radeon_vm *vm, | 798 | struct radeon_vm *vm, |
| 549 | struct radeon_bo *bo, | 799 | struct radeon_bo *bo, |
| @@ -592,6 +842,18 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev, | |||
| 592 | } | 842 | } |
| 593 | 843 | ||
| 594 | /* object have to be reserved */ | 844 | /* object have to be reserved */ |
| 845 | /** | ||
| 846 | * radeon_vm_bo_rmv - remove a bo to a specific vm | ||
| 847 | * | ||
| 848 | * @rdev: radeon_device pointer | ||
| 849 | * @vm: requested vm | ||
| 850 | * @bo: radeon buffer object | ||
| 851 | * | ||
| 852 | * Remove @bo from the requested vm (cayman+). | ||
| 853 | * Remove @bo from the list of bos associated with the vm and | ||
| 854 | * remove the ptes for @bo in the page table. | ||
| 855 | * Returns 0 for success. | ||
| 856 | */ | ||
| 595 | int radeon_vm_bo_rmv(struct radeon_device *rdev, | 857 | int radeon_vm_bo_rmv(struct radeon_device *rdev, |
| 596 | struct radeon_vm *vm, | 858 | struct radeon_vm *vm, |
| 597 | struct radeon_bo *bo) | 859 | struct radeon_bo *bo) |
| @@ -602,10 +864,10 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev, | |||
| 602 | if (bo_va == NULL) | 864 | if (bo_va == NULL) |
| 603 | return 0; | 865 | return 0; |
| 604 | 866 | ||
| 605 | radeon_mutex_lock(&rdev->cs_mutex); | 867 | mutex_lock(&rdev->vm_manager.lock); |
| 606 | mutex_lock(&vm->mutex); | 868 | mutex_lock(&vm->mutex); |
| 607 | radeon_vm_bo_update_pte(rdev, vm, bo, NULL); | 869 | radeon_vm_bo_update_pte(rdev, vm, bo, NULL); |
| 608 | radeon_mutex_unlock(&rdev->cs_mutex); | 870 | mutex_unlock(&rdev->vm_manager.lock); |
| 609 | list_del(&bo_va->vm_list); | 871 | list_del(&bo_va->vm_list); |
| 610 | mutex_unlock(&vm->mutex); | 872 | mutex_unlock(&vm->mutex); |
| 611 | list_del(&bo_va->bo_list); | 873 | list_del(&bo_va->bo_list); |
| @@ -614,6 +876,15 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev, | |||
| 614 | return 0; | 876 | return 0; |
| 615 | } | 877 | } |
| 616 | 878 | ||
| 879 | /** | ||
| 880 | * radeon_vm_bo_invalidate - mark the bo as invalid | ||
| 881 | * | ||
| 882 | * @rdev: radeon_device pointer | ||
| 883 | * @vm: requested vm | ||
| 884 | * @bo: radeon buffer object | ||
| 885 | * | ||
| 886 | * Mark @bo as invalid (cayman+). | ||
| 887 | */ | ||
| 617 | void radeon_vm_bo_invalidate(struct radeon_device *rdev, | 888 | void radeon_vm_bo_invalidate(struct radeon_device *rdev, |
| 618 | struct radeon_bo *bo) | 889 | struct radeon_bo *bo) |
| 619 | { | 890 | { |
| @@ -625,6 +896,17 @@ void radeon_vm_bo_invalidate(struct radeon_device *rdev, | |||
| 625 | } | 896 | } |
| 626 | } | 897 | } |
| 627 | 898 | ||
| 899 | /** | ||
| 900 | * radeon_vm_init - initialize a vm instance | ||
| 901 | * | ||
| 902 | * @rdev: radeon_device pointer | ||
| 903 | * @vm: requested vm | ||
| 904 | * | ||
| 905 | * Init @vm (cayman+). | ||
| 906 | * Map the IB pool and any other shared objects into the VM | ||
| 907 | * by default as it's used by all VMs. | ||
| 908 | * Returns 0 for success, error for failure. | ||
| 909 | */ | ||
| 628 | int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) | 910 | int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) |
| 629 | { | 911 | { |
| 630 | int r; | 912 | int r; |
| @@ -651,15 +933,24 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) | |||
| 651 | return r; | 933 | return r; |
| 652 | } | 934 | } |
| 653 | 935 | ||
| 936 | /** | ||
| 937 | * radeon_vm_init - tear down a vm instance | ||
| 938 | * | ||
| 939 | * @rdev: radeon_device pointer | ||
| 940 | * @vm: requested vm | ||
| 941 | * | ||
| 942 | * Tear down @vm (cayman+). | ||
| 943 | * Unbind the VM and remove all bos from the vm bo list | ||
| 944 | */ | ||
| 654 | void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) | 945 | void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) |
| 655 | { | 946 | { |
| 656 | struct radeon_bo_va *bo_va, *tmp; | 947 | struct radeon_bo_va *bo_va, *tmp; |
| 657 | int r; | 948 | int r; |
| 658 | 949 | ||
| 659 | radeon_mutex_lock(&rdev->cs_mutex); | 950 | mutex_lock(&rdev->vm_manager.lock); |
| 660 | mutex_lock(&vm->mutex); | 951 | mutex_lock(&vm->mutex); |
| 661 | radeon_vm_unbind_locked(rdev, vm); | 952 | radeon_vm_unbind_locked(rdev, vm); |
| 662 | radeon_mutex_unlock(&rdev->cs_mutex); | 953 | mutex_unlock(&rdev->vm_manager.lock); |
| 663 | 954 | ||
| 664 | /* remove all bo */ | 955 | /* remove all bo */ |
| 665 | r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); | 956 | r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); |
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 21ec9f5653ce..84d045245739 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c | |||
| @@ -159,11 +159,9 @@ void radeon_gem_object_close(struct drm_gem_object *obj, | |||
| 159 | static int radeon_gem_handle_lockup(struct radeon_device *rdev, int r) | 159 | static int radeon_gem_handle_lockup(struct radeon_device *rdev, int r) |
| 160 | { | 160 | { |
| 161 | if (r == -EDEADLK) { | 161 | if (r == -EDEADLK) { |
| 162 | radeon_mutex_lock(&rdev->cs_mutex); | ||
| 163 | r = radeon_gpu_reset(rdev); | 162 | r = radeon_gpu_reset(rdev); |
| 164 | if (!r) | 163 | if (!r) |
| 165 | r = -EAGAIN; | 164 | r = -EAGAIN; |
| 166 | radeon_mutex_unlock(&rdev->cs_mutex); | ||
| 167 | } | 165 | } |
| 168 | return r; | 166 | return r; |
| 169 | } | 167 | } |
| @@ -217,12 +215,14 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data, | |||
| 217 | uint32_t handle; | 215 | uint32_t handle; |
| 218 | int r; | 216 | int r; |
| 219 | 217 | ||
| 218 | down_read(&rdev->exclusive_lock); | ||
| 220 | /* create a gem object to contain this object in */ | 219 | /* create a gem object to contain this object in */ |
| 221 | args->size = roundup(args->size, PAGE_SIZE); | 220 | args->size = roundup(args->size, PAGE_SIZE); |
| 222 | r = radeon_gem_object_create(rdev, args->size, args->alignment, | 221 | r = radeon_gem_object_create(rdev, args->size, args->alignment, |
| 223 | args->initial_domain, false, | 222 | args->initial_domain, false, |
| 224 | false, &gobj); | 223 | false, &gobj); |
| 225 | if (r) { | 224 | if (r) { |
| 225 | up_read(&rdev->exclusive_lock); | ||
| 226 | r = radeon_gem_handle_lockup(rdev, r); | 226 | r = radeon_gem_handle_lockup(rdev, r); |
| 227 | return r; | 227 | return r; |
| 228 | } | 228 | } |
| @@ -230,10 +230,12 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data, | |||
| 230 | /* drop reference from allocate - handle holds it now */ | 230 | /* drop reference from allocate - handle holds it now */ |
| 231 | drm_gem_object_unreference_unlocked(gobj); | 231 | drm_gem_object_unreference_unlocked(gobj); |
| 232 | if (r) { | 232 | if (r) { |
| 233 | up_read(&rdev->exclusive_lock); | ||
| 233 | r = radeon_gem_handle_lockup(rdev, r); | 234 | r = radeon_gem_handle_lockup(rdev, r); |
| 234 | return r; | 235 | return r; |
| 235 | } | 236 | } |
| 236 | args->handle = handle; | 237 | args->handle = handle; |
| 238 | up_read(&rdev->exclusive_lock); | ||
| 237 | return 0; | 239 | return 0; |
| 238 | } | 240 | } |
| 239 | 241 | ||
| @@ -242,6 +244,7 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
| 242 | { | 244 | { |
| 243 | /* transition the BO to a domain - | 245 | /* transition the BO to a domain - |
| 244 | * just validate the BO into a certain domain */ | 246 | * just validate the BO into a certain domain */ |
| 247 | struct radeon_device *rdev = dev->dev_private; | ||
| 245 | struct drm_radeon_gem_set_domain *args = data; | 248 | struct drm_radeon_gem_set_domain *args = data; |
| 246 | struct drm_gem_object *gobj; | 249 | struct drm_gem_object *gobj; |
| 247 | struct radeon_bo *robj; | 250 | struct radeon_bo *robj; |
| @@ -249,10 +252,12 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
| 249 | 252 | ||
| 250 | /* for now if someone requests domain CPU - | 253 | /* for now if someone requests domain CPU - |
| 251 | * just make sure the buffer is finished with */ | 254 | * just make sure the buffer is finished with */ |
| 255 | down_read(&rdev->exclusive_lock); | ||
| 252 | 256 | ||
| 253 | /* just do a BO wait for now */ | 257 | /* just do a BO wait for now */ |
| 254 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | 258 | gobj = drm_gem_object_lookup(dev, filp, args->handle); |
| 255 | if (gobj == NULL) { | 259 | if (gobj == NULL) { |
| 260 | up_read(&rdev->exclusive_lock); | ||
| 256 | return -ENOENT; | 261 | return -ENOENT; |
| 257 | } | 262 | } |
| 258 | robj = gem_to_radeon_bo(gobj); | 263 | robj = gem_to_radeon_bo(gobj); |
| @@ -260,6 +265,7 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
| 260 | r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain); | 265 | r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain); |
| 261 | 266 | ||
| 262 | drm_gem_object_unreference_unlocked(gobj); | 267 | drm_gem_object_unreference_unlocked(gobj); |
| 268 | up_read(&rdev->exclusive_lock); | ||
| 263 | r = radeon_gem_handle_lockup(robj->rdev, r); | 269 | r = radeon_gem_handle_lockup(robj->rdev, r); |
| 264 | return r; | 270 | return r; |
| 265 | } | 271 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 5df58d1aba06..afaa1727abd2 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c | |||
| @@ -32,6 +32,17 @@ | |||
| 32 | #include "radeon.h" | 32 | #include "radeon.h" |
| 33 | #include "atom.h" | 33 | #include "atom.h" |
| 34 | 34 | ||
| 35 | #define RADEON_WAIT_IDLE_TIMEOUT 200 | ||
| 36 | |||
| 37 | /** | ||
| 38 | * radeon_driver_irq_handler_kms - irq handler for KMS | ||
| 39 | * | ||
| 40 | * @DRM_IRQ_ARGS: args | ||
| 41 | * | ||
| 42 | * This is the irq handler for the radeon KMS driver (all asics). | ||
| 43 | * radeon_irq_process is a macro that points to the per-asic | ||
| 44 | * irq handler callback. | ||
| 45 | */ | ||
| 35 | irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) | 46 | irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) |
| 36 | { | 47 | { |
| 37 | struct drm_device *dev = (struct drm_device *) arg; | 48 | struct drm_device *dev = (struct drm_device *) arg; |
| @@ -43,6 +54,17 @@ irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) | |||
| 43 | /* | 54 | /* |
| 44 | * Handle hotplug events outside the interrupt handler proper. | 55 | * Handle hotplug events outside the interrupt handler proper. |
| 45 | */ | 56 | */ |
| 57 | /** | ||
| 58 | * radeon_hotplug_work_func - display hotplug work handler | ||
| 59 | * | ||
| 60 | * @work: work struct | ||
| 61 | * | ||
| 62 | * This is the hot plug event work handler (all asics). | ||
| 63 | * The work gets scheduled from the irq handler if there | ||
| 64 | * was a hot plug interrupt. It walks the connector table | ||
| 65 | * and calls the hotplug handler for each one, then sends | ||
| 66 | * a drm hotplug event to alert userspace. | ||
| 67 | */ | ||
| 46 | static void radeon_hotplug_work_func(struct work_struct *work) | 68 | static void radeon_hotplug_work_func(struct work_struct *work) |
| 47 | { | 69 | { |
| 48 | struct radeon_device *rdev = container_of(work, struct radeon_device, | 70 | struct radeon_device *rdev = container_of(work, struct radeon_device, |
| @@ -59,61 +81,94 @@ static void radeon_hotplug_work_func(struct work_struct *work) | |||
| 59 | drm_helper_hpd_irq_event(dev); | 81 | drm_helper_hpd_irq_event(dev); |
| 60 | } | 82 | } |
| 61 | 83 | ||
| 84 | /** | ||
| 85 | * radeon_driver_irq_preinstall_kms - drm irq preinstall callback | ||
| 86 | * | ||
| 87 | * @dev: drm dev pointer | ||
| 88 | * | ||
| 89 | * Gets the hw ready to enable irqs (all asics). | ||
| 90 | * This function disables all interrupt sources on the GPU. | ||
| 91 | */ | ||
| 62 | void radeon_driver_irq_preinstall_kms(struct drm_device *dev) | 92 | void radeon_driver_irq_preinstall_kms(struct drm_device *dev) |
| 63 | { | 93 | { |
| 64 | struct radeon_device *rdev = dev->dev_private; | 94 | struct radeon_device *rdev = dev->dev_private; |
| 95 | unsigned long irqflags; | ||
| 65 | unsigned i; | 96 | unsigned i; |
| 66 | 97 | ||
| 98 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 67 | /* Disable *all* interrupts */ | 99 | /* Disable *all* interrupts */ |
| 68 | for (i = 0; i < RADEON_NUM_RINGS; i++) | 100 | for (i = 0; i < RADEON_NUM_RINGS; i++) |
| 69 | rdev->irq.sw_int[i] = false; | 101 | atomic_set(&rdev->irq.ring_int[i], 0); |
| 70 | rdev->irq.gui_idle = false; | 102 | rdev->irq.gui_idle = false; |
| 71 | for (i = 0; i < RADEON_MAX_HPD_PINS; i++) | 103 | for (i = 0; i < RADEON_MAX_HPD_PINS; i++) |
| 72 | rdev->irq.hpd[i] = false; | 104 | rdev->irq.hpd[i] = false; |
| 73 | for (i = 0; i < RADEON_MAX_CRTCS; i++) { | 105 | for (i = 0; i < RADEON_MAX_CRTCS; i++) { |
| 74 | rdev->irq.crtc_vblank_int[i] = false; | 106 | rdev->irq.crtc_vblank_int[i] = false; |
| 75 | rdev->irq.pflip[i] = false; | 107 | atomic_set(&rdev->irq.pflip[i], 0); |
| 76 | rdev->irq.afmt[i] = false; | 108 | rdev->irq.afmt[i] = false; |
| 77 | } | 109 | } |
| 78 | radeon_irq_set(rdev); | 110 | radeon_irq_set(rdev); |
| 111 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 79 | /* Clear bits */ | 112 | /* Clear bits */ |
| 80 | radeon_irq_process(rdev); | 113 | radeon_irq_process(rdev); |
| 81 | } | 114 | } |
| 82 | 115 | ||
| 116 | /** | ||
| 117 | * radeon_driver_irq_postinstall_kms - drm irq preinstall callback | ||
| 118 | * | ||
| 119 | * @dev: drm dev pointer | ||
| 120 | * | ||
| 121 | * Handles stuff to be done after enabling irqs (all asics). | ||
| 122 | * Returns 0 on success. | ||
| 123 | */ | ||
| 83 | int radeon_driver_irq_postinstall_kms(struct drm_device *dev) | 124 | int radeon_driver_irq_postinstall_kms(struct drm_device *dev) |
| 84 | { | 125 | { |
| 85 | struct radeon_device *rdev = dev->dev_private; | ||
| 86 | unsigned i; | ||
| 87 | |||
| 88 | dev->max_vblank_count = 0x001fffff; | 126 | dev->max_vblank_count = 0x001fffff; |
| 89 | for (i = 0; i < RADEON_NUM_RINGS; i++) | ||
| 90 | rdev->irq.sw_int[i] = true; | ||
| 91 | radeon_irq_set(rdev); | ||
| 92 | return 0; | 127 | return 0; |
| 93 | } | 128 | } |
| 94 | 129 | ||
| 130 | /** | ||
| 131 | * radeon_driver_irq_uninstall_kms - drm irq uninstall callback | ||
| 132 | * | ||
| 133 | * @dev: drm dev pointer | ||
| 134 | * | ||
| 135 | * This function disables all interrupt sources on the GPU (all asics). | ||
| 136 | */ | ||
| 95 | void radeon_driver_irq_uninstall_kms(struct drm_device *dev) | 137 | void radeon_driver_irq_uninstall_kms(struct drm_device *dev) |
| 96 | { | 138 | { |
| 97 | struct radeon_device *rdev = dev->dev_private; | 139 | struct radeon_device *rdev = dev->dev_private; |
| 140 | unsigned long irqflags; | ||
| 98 | unsigned i; | 141 | unsigned i; |
| 99 | 142 | ||
| 100 | if (rdev == NULL) { | 143 | if (rdev == NULL) { |
| 101 | return; | 144 | return; |
| 102 | } | 145 | } |
| 146 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 103 | /* Disable *all* interrupts */ | 147 | /* Disable *all* interrupts */ |
| 104 | for (i = 0; i < RADEON_NUM_RINGS; i++) | 148 | for (i = 0; i < RADEON_NUM_RINGS; i++) |
| 105 | rdev->irq.sw_int[i] = false; | 149 | atomic_set(&rdev->irq.ring_int[i], 0); |
| 106 | rdev->irq.gui_idle = false; | 150 | rdev->irq.gui_idle = false; |
| 107 | for (i = 0; i < RADEON_MAX_HPD_PINS; i++) | 151 | for (i = 0; i < RADEON_MAX_HPD_PINS; i++) |
| 108 | rdev->irq.hpd[i] = false; | 152 | rdev->irq.hpd[i] = false; |
| 109 | for (i = 0; i < RADEON_MAX_CRTCS; i++) { | 153 | for (i = 0; i < RADEON_MAX_CRTCS; i++) { |
| 110 | rdev->irq.crtc_vblank_int[i] = false; | 154 | rdev->irq.crtc_vblank_int[i] = false; |
| 111 | rdev->irq.pflip[i] = false; | 155 | atomic_set(&rdev->irq.pflip[i], 0); |
| 112 | rdev->irq.afmt[i] = false; | 156 | rdev->irq.afmt[i] = false; |
| 113 | } | 157 | } |
| 114 | radeon_irq_set(rdev); | 158 | radeon_irq_set(rdev); |
| 159 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 115 | } | 160 | } |
| 116 | 161 | ||
| 162 | /** | ||
| 163 | * radeon_msi_ok - asic specific msi checks | ||
| 164 | * | ||
| 165 | * @rdev: radeon device pointer | ||
| 166 | * | ||
| 167 | * Handles asic specific MSI checks to determine if | ||
| 168 | * MSIs should be enabled on a particular chip (all asics). | ||
| 169 | * Returns true if MSIs should be enabled, false if MSIs | ||
| 170 | * should not be enabled. | ||
| 171 | */ | ||
| 117 | static bool radeon_msi_ok(struct radeon_device *rdev) | 172 | static bool radeon_msi_ok(struct radeon_device *rdev) |
| 118 | { | 173 | { |
| 119 | /* RV370/RV380 was first asic with MSI support */ | 174 | /* RV370/RV380 was first asic with MSI support */ |
| @@ -166,17 +221,22 @@ static bool radeon_msi_ok(struct radeon_device *rdev) | |||
| 166 | return true; | 221 | return true; |
| 167 | } | 222 | } |
| 168 | 223 | ||
| 224 | /** | ||
| 225 | * radeon_irq_kms_init - init driver interrupt info | ||
| 226 | * | ||
| 227 | * @rdev: radeon device pointer | ||
| 228 | * | ||
| 229 | * Sets up the work irq handlers, vblank init, MSIs, etc. (all asics). | ||
| 230 | * Returns 0 for success, error for failure. | ||
| 231 | */ | ||
| 169 | int radeon_irq_kms_init(struct radeon_device *rdev) | 232 | int radeon_irq_kms_init(struct radeon_device *rdev) |
| 170 | { | 233 | { |
| 171 | int i; | ||
| 172 | int r = 0; | 234 | int r = 0; |
| 173 | 235 | ||
| 174 | INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func); | 236 | INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func); |
| 175 | INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi); | 237 | INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi); |
| 176 | 238 | ||
| 177 | spin_lock_init(&rdev->irq.sw_lock); | 239 | spin_lock_init(&rdev->irq.lock); |
| 178 | for (i = 0; i < rdev->num_crtc; i++) | ||
| 179 | spin_lock_init(&rdev->irq.pflip_lock[i]); | ||
| 180 | r = drm_vblank_init(rdev->ddev, rdev->num_crtc); | 240 | r = drm_vblank_init(rdev->ddev, rdev->num_crtc); |
| 181 | if (r) { | 241 | if (r) { |
| 182 | return r; | 242 | return r; |
| @@ -201,6 +261,13 @@ int radeon_irq_kms_init(struct radeon_device *rdev) | |||
| 201 | return 0; | 261 | return 0; |
| 202 | } | 262 | } |
| 203 | 263 | ||
| 264 | /** | ||
| 265 | * radeon_irq_kms_fini - tear down driver interrrupt info | ||
| 266 | * | ||
| 267 | * @rdev: radeon device pointer | ||
| 268 | * | ||
| 269 | * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics). | ||
| 270 | */ | ||
| 204 | void radeon_irq_kms_fini(struct radeon_device *rdev) | 271 | void radeon_irq_kms_fini(struct radeon_device *rdev) |
| 205 | { | 272 | { |
| 206 | drm_vblank_cleanup(rdev->ddev); | 273 | drm_vblank_cleanup(rdev->ddev); |
| @@ -213,31 +280,63 @@ void radeon_irq_kms_fini(struct radeon_device *rdev) | |||
| 213 | flush_work_sync(&rdev->hotplug_work); | 280 | flush_work_sync(&rdev->hotplug_work); |
| 214 | } | 281 | } |
| 215 | 282 | ||
| 283 | /** | ||
| 284 | * radeon_irq_kms_sw_irq_get - enable software interrupt | ||
| 285 | * | ||
| 286 | * @rdev: radeon device pointer | ||
| 287 | * @ring: ring whose interrupt you want to enable | ||
| 288 | * | ||
| 289 | * Enables the software interrupt for a specific ring (all asics). | ||
| 290 | * The software interrupt is generally used to signal a fence on | ||
| 291 | * a particular ring. | ||
| 292 | */ | ||
| 216 | void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring) | 293 | void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring) |
| 217 | { | 294 | { |
| 218 | unsigned long irqflags; | 295 | unsigned long irqflags; |
| 219 | 296 | ||
| 220 | spin_lock_irqsave(&rdev->irq.sw_lock, irqflags); | 297 | if (!rdev->ddev->irq_enabled) |
| 221 | if (rdev->ddev->irq_enabled && (++rdev->irq.sw_refcount[ring] == 1)) { | 298 | return; |
| 222 | rdev->irq.sw_int[ring] = true; | 299 | |
| 300 | if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) { | ||
| 301 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 223 | radeon_irq_set(rdev); | 302 | radeon_irq_set(rdev); |
| 303 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 224 | } | 304 | } |
| 225 | spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags); | ||
| 226 | } | 305 | } |
| 227 | 306 | ||
| 307 | /** | ||
| 308 | * radeon_irq_kms_sw_irq_put - disable software interrupt | ||
| 309 | * | ||
| 310 | * @rdev: radeon device pointer | ||
| 311 | * @ring: ring whose interrupt you want to disable | ||
| 312 | * | ||
| 313 | * Disables the software interrupt for a specific ring (all asics). | ||
| 314 | * The software interrupt is generally used to signal a fence on | ||
| 315 | * a particular ring. | ||
| 316 | */ | ||
| 228 | void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring) | 317 | void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring) |
| 229 | { | 318 | { |
| 230 | unsigned long irqflags; | 319 | unsigned long irqflags; |
| 231 | 320 | ||
| 232 | spin_lock_irqsave(&rdev->irq.sw_lock, irqflags); | 321 | if (!rdev->ddev->irq_enabled) |
| 233 | BUG_ON(rdev->ddev->irq_enabled && rdev->irq.sw_refcount[ring] <= 0); | 322 | return; |
| 234 | if (rdev->ddev->irq_enabled && (--rdev->irq.sw_refcount[ring] == 0)) { | 323 | |
| 235 | rdev->irq.sw_int[ring] = false; | 324 | if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) { |
| 325 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 236 | radeon_irq_set(rdev); | 326 | radeon_irq_set(rdev); |
| 327 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 237 | } | 328 | } |
| 238 | spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags); | ||
| 239 | } | 329 | } |
| 240 | 330 | ||
| 331 | /** | ||
| 332 | * radeon_irq_kms_pflip_irq_get - enable pageflip interrupt | ||
| 333 | * | ||
| 334 | * @rdev: radeon device pointer | ||
| 335 | * @crtc: crtc whose interrupt you want to enable | ||
| 336 | * | ||
| 337 | * Enables the pageflip interrupt for a specific crtc (all asics). | ||
| 338 | * For pageflips we use the vblank interrupt source. | ||
| 339 | */ | ||
| 241 | void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) | 340 | void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) |
| 242 | { | 341 | { |
| 243 | unsigned long irqflags; | 342 | unsigned long irqflags; |
| @@ -245,14 +344,25 @@ void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) | |||
| 245 | if (crtc < 0 || crtc >= rdev->num_crtc) | 344 | if (crtc < 0 || crtc >= rdev->num_crtc) |
| 246 | return; | 345 | return; |
| 247 | 346 | ||
| 248 | spin_lock_irqsave(&rdev->irq.pflip_lock[crtc], irqflags); | 347 | if (!rdev->ddev->irq_enabled) |
| 249 | if (rdev->ddev->irq_enabled && (++rdev->irq.pflip_refcount[crtc] == 1)) { | 348 | return; |
| 250 | rdev->irq.pflip[crtc] = true; | 349 | |
| 350 | if (atomic_inc_return(&rdev->irq.pflip[crtc]) == 1) { | ||
| 351 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 251 | radeon_irq_set(rdev); | 352 | radeon_irq_set(rdev); |
| 353 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 252 | } | 354 | } |
| 253 | spin_unlock_irqrestore(&rdev->irq.pflip_lock[crtc], irqflags); | ||
| 254 | } | 355 | } |
| 255 | 356 | ||
| 357 | /** | ||
| 358 | * radeon_irq_kms_pflip_irq_put - disable pageflip interrupt | ||
| 359 | * | ||
| 360 | * @rdev: radeon device pointer | ||
| 361 | * @crtc: crtc whose interrupt you want to disable | ||
| 362 | * | ||
| 363 | * Disables the pageflip interrupt for a specific crtc (all asics). | ||
| 364 | * For pageflips we use the vblank interrupt source. | ||
| 365 | */ | ||
| 256 | void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) | 366 | void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) |
| 257 | { | 367 | { |
| 258 | unsigned long irqflags; | 368 | unsigned long irqflags; |
| @@ -260,12 +370,121 @@ void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) | |||
| 260 | if (crtc < 0 || crtc >= rdev->num_crtc) | 370 | if (crtc < 0 || crtc >= rdev->num_crtc) |
| 261 | return; | 371 | return; |
| 262 | 372 | ||
| 263 | spin_lock_irqsave(&rdev->irq.pflip_lock[crtc], irqflags); | 373 | if (!rdev->ddev->irq_enabled) |
| 264 | BUG_ON(rdev->ddev->irq_enabled && rdev->irq.pflip_refcount[crtc] <= 0); | 374 | return; |
| 265 | if (rdev->ddev->irq_enabled && (--rdev->irq.pflip_refcount[crtc] == 0)) { | 375 | |
| 266 | rdev->irq.pflip[crtc] = false; | 376 | if (atomic_dec_and_test(&rdev->irq.pflip[crtc])) { |
| 377 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 267 | radeon_irq_set(rdev); | 378 | radeon_irq_set(rdev); |
| 379 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 268 | } | 380 | } |
| 269 | spin_unlock_irqrestore(&rdev->irq.pflip_lock[crtc], irqflags); | ||
| 270 | } | 381 | } |
| 271 | 382 | ||
| 383 | /** | ||
| 384 | * radeon_irq_kms_enable_afmt - enable audio format change interrupt | ||
| 385 | * | ||
| 386 | * @rdev: radeon device pointer | ||
| 387 | * @block: afmt block whose interrupt you want to enable | ||
| 388 | * | ||
| 389 | * Enables the afmt change interrupt for a specific afmt block (all asics). | ||
| 390 | */ | ||
| 391 | void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block) | ||
| 392 | { | ||
| 393 | unsigned long irqflags; | ||
| 394 | |||
| 395 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 396 | rdev->irq.afmt[block] = true; | ||
| 397 | radeon_irq_set(rdev); | ||
| 398 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 399 | |||
| 400 | } | ||
| 401 | |||
| 402 | /** | ||
| 403 | * radeon_irq_kms_disable_afmt - disable audio format change interrupt | ||
| 404 | * | ||
| 405 | * @rdev: radeon device pointer | ||
| 406 | * @block: afmt block whose interrupt you want to disable | ||
| 407 | * | ||
| 408 | * Disables the afmt change interrupt for a specific afmt block (all asics). | ||
| 409 | */ | ||
| 410 | void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block) | ||
| 411 | { | ||
| 412 | unsigned long irqflags; | ||
| 413 | |||
| 414 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 415 | rdev->irq.afmt[block] = false; | ||
| 416 | radeon_irq_set(rdev); | ||
| 417 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 418 | } | ||
| 419 | |||
| 420 | /** | ||
| 421 | * radeon_irq_kms_enable_hpd - enable hotplug detect interrupt | ||
| 422 | * | ||
| 423 | * @rdev: radeon device pointer | ||
| 424 | * @hpd_mask: mask of hpd pins you want to enable. | ||
| 425 | * | ||
| 426 | * Enables the hotplug detect interrupt for a specific hpd pin (all asics). | ||
| 427 | */ | ||
| 428 | void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask) | ||
| 429 | { | ||
| 430 | unsigned long irqflags; | ||
| 431 | int i; | ||
| 432 | |||
| 433 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 434 | for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) | ||
| 435 | rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i)); | ||
| 436 | radeon_irq_set(rdev); | ||
| 437 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 438 | } | ||
| 439 | |||
| 440 | /** | ||
| 441 | * radeon_irq_kms_disable_hpd - disable hotplug detect interrupt | ||
| 442 | * | ||
| 443 | * @rdev: radeon device pointer | ||
| 444 | * @hpd_mask: mask of hpd pins you want to disable. | ||
| 445 | * | ||
| 446 | * Disables the hotplug detect interrupt for a specific hpd pin (all asics). | ||
| 447 | */ | ||
| 448 | void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask) | ||
| 449 | { | ||
| 450 | unsigned long irqflags; | ||
| 451 | int i; | ||
| 452 | |||
| 453 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 454 | for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) | ||
| 455 | rdev->irq.hpd[i] &= !(hpd_mask & (1 << i)); | ||
| 456 | radeon_irq_set(rdev); | ||
| 457 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 458 | } | ||
| 459 | |||
| 460 | /** | ||
| 461 | * radeon_irq_kms_wait_gui_idle - waits for drawing engine to be idle | ||
| 462 | * | ||
| 463 | * @rdev: radeon device pointer | ||
| 464 | * | ||
| 465 | * Enabled the GUI idle interrupt and waits for it to fire (r6xx+). | ||
| 466 | * This is currently used to make sure the 3D engine is idle for power | ||
| 467 | * management, but should be replaces with proper fence waits. | ||
| 468 | * GUI idle interrupts don't work very well on pre-r6xx hw and it also | ||
| 469 | * does not take into account other aspects of the chip that may be busy. | ||
| 470 | * DO NOT USE GOING FORWARD. | ||
| 471 | */ | ||
| 472 | int radeon_irq_kms_wait_gui_idle(struct radeon_device *rdev) | ||
| 473 | { | ||
| 474 | unsigned long irqflags; | ||
| 475 | int r; | ||
| 476 | |||
| 477 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 478 | rdev->irq.gui_idle = true; | ||
| 479 | radeon_irq_set(rdev); | ||
| 480 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 481 | |||
| 482 | r = wait_event_timeout(rdev->irq.idle_queue, radeon_gui_idle(rdev), | ||
| 483 | msecs_to_jiffies(RADEON_WAIT_IDLE_TIMEOUT)); | ||
| 484 | |||
| 485 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 486 | rdev->irq.gui_idle = false; | ||
| 487 | radeon_irq_set(rdev); | ||
| 488 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 489 | return r; | ||
| 490 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 5c58d7d90cb2..1d73f16b5d97 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c | |||
| @@ -33,6 +33,17 @@ | |||
| 33 | #include <linux/vga_switcheroo.h> | 33 | #include <linux/vga_switcheroo.h> |
| 34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
| 35 | 35 | ||
| 36 | /** | ||
| 37 | * radeon_driver_unload_kms - Main unload function for KMS. | ||
| 38 | * | ||
| 39 | * @dev: drm dev pointer | ||
| 40 | * | ||
| 41 | * This is the main unload function for KMS (all asics). | ||
| 42 | * It calls radeon_modeset_fini() to tear down the | ||
| 43 | * displays, and radeon_device_fini() to tear down | ||
| 44 | * the rest of the device (CP, writeback, etc.). | ||
| 45 | * Returns 0 on success. | ||
| 46 | */ | ||
| 36 | int radeon_driver_unload_kms(struct drm_device *dev) | 47 | int radeon_driver_unload_kms(struct drm_device *dev) |
| 37 | { | 48 | { |
| 38 | struct radeon_device *rdev = dev->dev_private; | 49 | struct radeon_device *rdev = dev->dev_private; |
| @@ -46,6 +57,19 @@ int radeon_driver_unload_kms(struct drm_device *dev) | |||
| 46 | return 0; | 57 | return 0; |
| 47 | } | 58 | } |
| 48 | 59 | ||
| 60 | /** | ||
| 61 | * radeon_driver_load_kms - Main load function for KMS. | ||
| 62 | * | ||
| 63 | * @dev: drm dev pointer | ||
| 64 | * @flags: device flags | ||
| 65 | * | ||
| 66 | * This is the main load function for KMS (all asics). | ||
| 67 | * It calls radeon_device_init() to set up the non-display | ||
| 68 | * parts of the chip (asic init, CP, writeback, etc.), and | ||
| 69 | * radeon_modeset_init() to set up the display parts | ||
| 70 | * (crtcs, encoders, hotplug detect, etc.). | ||
| 71 | * Returns 0 on success, error on failure. | ||
| 72 | */ | ||
| 49 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) | 73 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) |
| 50 | { | 74 | { |
| 51 | struct radeon_device *rdev; | 75 | struct radeon_device *rdev; |
| @@ -96,6 +120,16 @@ out: | |||
| 96 | return r; | 120 | return r; |
| 97 | } | 121 | } |
| 98 | 122 | ||
| 123 | /** | ||
| 124 | * radeon_set_filp_rights - Set filp right. | ||
| 125 | * | ||
| 126 | * @dev: drm dev pointer | ||
| 127 | * @owner: drm file | ||
| 128 | * @applier: drm file | ||
| 129 | * @value: value | ||
| 130 | * | ||
| 131 | * Sets the filp rights for the device (all asics). | ||
| 132 | */ | ||
| 99 | static void radeon_set_filp_rights(struct drm_device *dev, | 133 | static void radeon_set_filp_rights(struct drm_device *dev, |
| 100 | struct drm_file **owner, | 134 | struct drm_file **owner, |
| 101 | struct drm_file *applier, | 135 | struct drm_file *applier, |
| @@ -118,6 +152,18 @@ static void radeon_set_filp_rights(struct drm_device *dev, | |||
| 118 | /* | 152 | /* |
| 119 | * Userspace get information ioctl | 153 | * Userspace get information ioctl |
| 120 | */ | 154 | */ |
| 155 | /** | ||
| 156 | * radeon_info_ioctl - answer a device specific request. | ||
| 157 | * | ||
| 158 | * @rdev: radeon device pointer | ||
| 159 | * @data: request object | ||
| 160 | * @filp: drm filp | ||
| 161 | * | ||
| 162 | * This function is used to pass device specific parameters to the userspace | ||
| 163 | * drivers. Examples include: pci device id, pipeline parms, tiling params, | ||
| 164 | * etc. (all asics). | ||
| 165 | * Returns 0 on success, -EINVAL on failure. | ||
| 166 | */ | ||
| 121 | int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | 167 | int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) |
| 122 | { | 168 | { |
| 123 | struct radeon_device *rdev = dev->dev_private; | 169 | struct radeon_device *rdev = dev->dev_private; |
| @@ -301,16 +347,40 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
| 301 | /* | 347 | /* |
| 302 | * Outdated mess for old drm with Xorg being in charge (void function now). | 348 | * Outdated mess for old drm with Xorg being in charge (void function now). |
| 303 | */ | 349 | */ |
| 350 | /** | ||
| 351 | * radeon_driver_firstopen_kms - drm callback for first open | ||
| 352 | * | ||
| 353 | * @dev: drm dev pointer | ||
| 354 | * | ||
| 355 | * Nothing to be done for KMS (all asics). | ||
| 356 | * Returns 0 on success. | ||
| 357 | */ | ||
| 304 | int radeon_driver_firstopen_kms(struct drm_device *dev) | 358 | int radeon_driver_firstopen_kms(struct drm_device *dev) |
| 305 | { | 359 | { |
| 306 | return 0; | 360 | return 0; |
| 307 | } | 361 | } |
| 308 | 362 | ||
| 363 | /** | ||
| 364 | * radeon_driver_firstopen_kms - drm callback for last close | ||
| 365 | * | ||
| 366 | * @dev: drm dev pointer | ||
| 367 | * | ||
| 368 | * Switch vga switcheroo state after last close (all asics). | ||
| 369 | */ | ||
| 309 | void radeon_driver_lastclose_kms(struct drm_device *dev) | 370 | void radeon_driver_lastclose_kms(struct drm_device *dev) |
| 310 | { | 371 | { |
| 311 | vga_switcheroo_process_delayed_switch(); | 372 | vga_switcheroo_process_delayed_switch(); |
| 312 | } | 373 | } |
| 313 | 374 | ||
| 375 | /** | ||
| 376 | * radeon_driver_open_kms - drm callback for open | ||
| 377 | * | ||
| 378 | * @dev: drm dev pointer | ||
| 379 | * @file_priv: drm file | ||
| 380 | * | ||
| 381 | * On device open, init vm on cayman+ (all asics). | ||
| 382 | * Returns 0 on success, error on failure. | ||
| 383 | */ | ||
| 314 | int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) | 384 | int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) |
| 315 | { | 385 | { |
| 316 | struct radeon_device *rdev = dev->dev_private; | 386 | struct radeon_device *rdev = dev->dev_private; |
| @@ -339,6 +409,14 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) | |||
| 339 | return 0; | 409 | return 0; |
| 340 | } | 410 | } |
| 341 | 411 | ||
| 412 | /** | ||
| 413 | * radeon_driver_postclose_kms - drm callback for post close | ||
| 414 | * | ||
| 415 | * @dev: drm dev pointer | ||
| 416 | * @file_priv: drm file | ||
| 417 | * | ||
| 418 | * On device post close, tear down vm on cayman+ (all asics). | ||
| 419 | */ | ||
| 342 | void radeon_driver_postclose_kms(struct drm_device *dev, | 420 | void radeon_driver_postclose_kms(struct drm_device *dev, |
| 343 | struct drm_file *file_priv) | 421 | struct drm_file *file_priv) |
| 344 | { | 422 | { |
| @@ -354,6 +432,15 @@ void radeon_driver_postclose_kms(struct drm_device *dev, | |||
| 354 | } | 432 | } |
| 355 | } | 433 | } |
| 356 | 434 | ||
| 435 | /** | ||
| 436 | * radeon_driver_preclose_kms - drm callback for pre close | ||
| 437 | * | ||
| 438 | * @dev: drm dev pointer | ||
| 439 | * @file_priv: drm file | ||
| 440 | * | ||
| 441 | * On device pre close, tear down hyperz and cmask filps on r1xx-r5xx | ||
| 442 | * (all asics). | ||
| 443 | */ | ||
| 357 | void radeon_driver_preclose_kms(struct drm_device *dev, | 444 | void radeon_driver_preclose_kms(struct drm_device *dev, |
| 358 | struct drm_file *file_priv) | 445 | struct drm_file *file_priv) |
| 359 | { | 446 | { |
| @@ -367,6 +454,15 @@ void radeon_driver_preclose_kms(struct drm_device *dev, | |||
| 367 | /* | 454 | /* |
| 368 | * VBlank related functions. | 455 | * VBlank related functions. |
| 369 | */ | 456 | */ |
| 457 | /** | ||
| 458 | * radeon_get_vblank_counter_kms - get frame count | ||
| 459 | * | ||
| 460 | * @dev: drm dev pointer | ||
| 461 | * @crtc: crtc to get the frame count from | ||
| 462 | * | ||
| 463 | * Gets the frame count on the requested crtc (all asics). | ||
| 464 | * Returns frame count on success, -EINVAL on failure. | ||
| 465 | */ | ||
| 370 | u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) | 466 | u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) |
| 371 | { | 467 | { |
| 372 | struct radeon_device *rdev = dev->dev_private; | 468 | struct radeon_device *rdev = dev->dev_private; |
| @@ -379,34 +475,70 @@ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) | |||
| 379 | return radeon_get_vblank_counter(rdev, crtc); | 475 | return radeon_get_vblank_counter(rdev, crtc); |
| 380 | } | 476 | } |
| 381 | 477 | ||
| 478 | /** | ||
| 479 | * radeon_enable_vblank_kms - enable vblank interrupt | ||
| 480 | * | ||
| 481 | * @dev: drm dev pointer | ||
| 482 | * @crtc: crtc to enable vblank interrupt for | ||
| 483 | * | ||
| 484 | * Enable the interrupt on the requested crtc (all asics). | ||
| 485 | * Returns 0 on success, -EINVAL on failure. | ||
| 486 | */ | ||
| 382 | int radeon_enable_vblank_kms(struct drm_device *dev, int crtc) | 487 | int radeon_enable_vblank_kms(struct drm_device *dev, int crtc) |
| 383 | { | 488 | { |
| 384 | struct radeon_device *rdev = dev->dev_private; | 489 | struct radeon_device *rdev = dev->dev_private; |
| 490 | unsigned long irqflags; | ||
| 491 | int r; | ||
| 385 | 492 | ||
| 386 | if (crtc < 0 || crtc >= rdev->num_crtc) { | 493 | if (crtc < 0 || crtc >= rdev->num_crtc) { |
| 387 | DRM_ERROR("Invalid crtc %d\n", crtc); | 494 | DRM_ERROR("Invalid crtc %d\n", crtc); |
| 388 | return -EINVAL; | 495 | return -EINVAL; |
| 389 | } | 496 | } |
| 390 | 497 | ||
| 498 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 391 | rdev->irq.crtc_vblank_int[crtc] = true; | 499 | rdev->irq.crtc_vblank_int[crtc] = true; |
| 392 | 500 | r = radeon_irq_set(rdev); | |
| 393 | return radeon_irq_set(rdev); | 501 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); |
| 502 | return r; | ||
| 394 | } | 503 | } |
| 395 | 504 | ||
| 505 | /** | ||
| 506 | * radeon_disable_vblank_kms - disable vblank interrupt | ||
| 507 | * | ||
| 508 | * @dev: drm dev pointer | ||
| 509 | * @crtc: crtc to disable vblank interrupt for | ||
| 510 | * | ||
| 511 | * Disable the interrupt on the requested crtc (all asics). | ||
| 512 | */ | ||
| 396 | void radeon_disable_vblank_kms(struct drm_device *dev, int crtc) | 513 | void radeon_disable_vblank_kms(struct drm_device *dev, int crtc) |
| 397 | { | 514 | { |
| 398 | struct radeon_device *rdev = dev->dev_private; | 515 | struct radeon_device *rdev = dev->dev_private; |
| 516 | unsigned long irqflags; | ||
| 399 | 517 | ||
| 400 | if (crtc < 0 || crtc >= rdev->num_crtc) { | 518 | if (crtc < 0 || crtc >= rdev->num_crtc) { |
| 401 | DRM_ERROR("Invalid crtc %d\n", crtc); | 519 | DRM_ERROR("Invalid crtc %d\n", crtc); |
| 402 | return; | 520 | return; |
| 403 | } | 521 | } |
| 404 | 522 | ||
| 523 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | ||
| 405 | rdev->irq.crtc_vblank_int[crtc] = false; | 524 | rdev->irq.crtc_vblank_int[crtc] = false; |
| 406 | |||
| 407 | radeon_irq_set(rdev); | 525 | radeon_irq_set(rdev); |
| 526 | spin_unlock_irqrestore(&rdev->irq.lock, irqflags); | ||
| 408 | } | 527 | } |
| 409 | 528 | ||
| 529 | /** | ||
| 530 | * radeon_get_vblank_timestamp_kms - get vblank timestamp | ||
| 531 | * | ||
| 532 | * @dev: drm dev pointer | ||
| 533 | * @crtc: crtc to get the timestamp for | ||
| 534 | * @max_error: max error | ||
| 535 | * @vblank_time: time value | ||
| 536 | * @flags: flags passed to the driver | ||
| 537 | * | ||
| 538 | * Gets the timestamp on the requested crtc based on the | ||
| 539 | * scanout position. (all asics). | ||
| 540 | * Returns postive status flags on success, negative error on failure. | ||
| 541 | */ | ||
| 410 | int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, | 542 | int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, |
| 411 | int *max_error, | 543 | int *max_error, |
| 412 | struct timeval *vblank_time, | 544 | struct timeval *vblank_time, |
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 210317c7045e..d5fd615897ec 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c | |||
| @@ -990,7 +990,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
| 990 | } | 990 | } |
| 991 | 991 | ||
| 992 | static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc, | 992 | static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc, |
| 993 | struct drm_display_mode *mode, | 993 | const struct drm_display_mode *mode, |
| 994 | struct drm_display_mode *adjusted_mode) | 994 | struct drm_display_mode *adjusted_mode) |
| 995 | { | 995 | { |
| 996 | if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) | 996 | if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) |
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index a0c82229e8f0..670e9910f869 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c | |||
| @@ -244,7 +244,7 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, | |||
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder, | 246 | static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder, |
| 247 | struct drm_display_mode *mode, | 247 | const struct drm_display_mode *mode, |
| 248 | struct drm_display_mode *adjusted_mode) | 248 | struct drm_display_mode *adjusted_mode) |
| 249 | { | 249 | { |
| 250 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 250 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 5b10ffd7bb2f..f380d59c5763 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
| @@ -488,7 +488,7 @@ extern void radeon_connector_hotplug(struct drm_connector *connector); | |||
| 488 | extern int radeon_dp_mode_valid_helper(struct drm_connector *connector, | 488 | extern int radeon_dp_mode_valid_helper(struct drm_connector *connector, |
| 489 | struct drm_display_mode *mode); | 489 | struct drm_display_mode *mode); |
| 490 | extern void radeon_dp_set_link_config(struct drm_connector *connector, | 490 | extern void radeon_dp_set_link_config(struct drm_connector *connector, |
| 491 | struct drm_display_mode *mode); | 491 | const struct drm_display_mode *mode); |
| 492 | extern void radeon_dp_link_train(struct drm_encoder *encoder, | 492 | extern void radeon_dp_link_train(struct drm_encoder *encoder, |
| 493 | struct drm_connector *connector); | 493 | struct drm_connector *connector); |
| 494 | extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector); | 494 | extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector); |
| @@ -678,7 +678,7 @@ void radeon_enc_destroy(struct drm_encoder *encoder); | |||
| 678 | void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj); | 678 | void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj); |
| 679 | void radeon_combios_asic_init(struct drm_device *dev); | 679 | void radeon_combios_asic_init(struct drm_device *dev); |
| 680 | bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | 680 | bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, |
| 681 | struct drm_display_mode *mode, | 681 | const struct drm_display_mode *mode, |
| 682 | struct drm_display_mode *adjusted_mode); | 682 | struct drm_display_mode *adjusted_mode); |
| 683 | void radeon_panel_mode_fixup(struct drm_encoder *encoder, | 683 | void radeon_panel_mode_fixup(struct drm_encoder *encoder, |
| 684 | struct drm_display_mode *adjusted_mode); | 684 | struct drm_display_mode *adjusted_mode); |
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 830f1a7b486f..1f1a4c803c1d 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
| @@ -115,9 +115,7 @@ int radeon_bo_create(struct radeon_device *rdev, | |||
| 115 | 115 | ||
| 116 | size = ALIGN(size, PAGE_SIZE); | 116 | size = ALIGN(size, PAGE_SIZE); |
| 117 | 117 | ||
| 118 | if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) { | 118 | rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; |
| 119 | rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; | ||
| 120 | } | ||
| 121 | if (kernel) { | 119 | if (kernel) { |
| 122 | type = ttm_bo_type_kernel; | 120 | type = ttm_bo_type_kernel; |
| 123 | } else if (sg) { | 121 | } else if (sg) { |
| @@ -138,7 +136,6 @@ int radeon_bo_create(struct radeon_device *rdev, | |||
| 138 | acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size, | 136 | acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size, |
| 139 | sizeof(struct radeon_bo)); | 137 | sizeof(struct radeon_bo)); |
| 140 | 138 | ||
| 141 | retry: | ||
| 142 | bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); | 139 | bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); |
| 143 | if (bo == NULL) | 140 | if (bo == NULL) |
| 144 | return -ENOMEM; | 141 | return -ENOMEM; |
| @@ -152,13 +149,15 @@ retry: | |||
| 152 | bo->surface_reg = -1; | 149 | bo->surface_reg = -1; |
| 153 | INIT_LIST_HEAD(&bo->list); | 150 | INIT_LIST_HEAD(&bo->list); |
| 154 | INIT_LIST_HEAD(&bo->va); | 151 | INIT_LIST_HEAD(&bo->va); |
| 152 | |||
| 153 | retry: | ||
| 155 | radeon_ttm_placement_from_domain(bo, domain); | 154 | radeon_ttm_placement_from_domain(bo, domain); |
| 156 | /* Kernel allocation are uninterruptible */ | 155 | /* Kernel allocation are uninterruptible */ |
| 157 | mutex_lock(&rdev->vram_mutex); | 156 | down_read(&rdev->pm.mclk_lock); |
| 158 | r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type, | 157 | r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type, |
| 159 | &bo->placement, page_align, 0, !kernel, NULL, | 158 | &bo->placement, page_align, 0, !kernel, NULL, |
| 160 | acc_size, sg, &radeon_ttm_bo_destroy); | 159 | acc_size, sg, &radeon_ttm_bo_destroy); |
| 161 | mutex_unlock(&rdev->vram_mutex); | 160 | up_read(&rdev->pm.mclk_lock); |
| 162 | if (unlikely(r != 0)) { | 161 | if (unlikely(r != 0)) { |
| 163 | if (r != -ERESTARTSYS) { | 162 | if (r != -ERESTARTSYS) { |
| 164 | if (domain == RADEON_GEM_DOMAIN_VRAM) { | 163 | if (domain == RADEON_GEM_DOMAIN_VRAM) { |
| @@ -219,9 +218,9 @@ void radeon_bo_unref(struct radeon_bo **bo) | |||
| 219 | return; | 218 | return; |
| 220 | rdev = (*bo)->rdev; | 219 | rdev = (*bo)->rdev; |
| 221 | tbo = &((*bo)->tbo); | 220 | tbo = &((*bo)->tbo); |
| 222 | mutex_lock(&rdev->vram_mutex); | 221 | down_read(&rdev->pm.mclk_lock); |
| 223 | ttm_bo_unref(&tbo); | 222 | ttm_bo_unref(&tbo); |
| 224 | mutex_unlock(&rdev->vram_mutex); | 223 | up_read(&rdev->pm.mclk_lock); |
| 225 | if (tbo == NULL) | 224 | if (tbo == NULL) |
| 226 | *bo = NULL; | 225 | *bo = NULL; |
| 227 | } | 226 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 5b37e283ec38..7ae606600107 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #define RADEON_IDLE_LOOP_MS 100 | 34 | #define RADEON_IDLE_LOOP_MS 100 |
| 35 | #define RADEON_RECLOCK_DELAY_MS 200 | 35 | #define RADEON_RECLOCK_DELAY_MS 200 |
| 36 | #define RADEON_WAIT_VBLANK_TIMEOUT 200 | 36 | #define RADEON_WAIT_VBLANK_TIMEOUT 200 |
| 37 | #define RADEON_WAIT_IDLE_TIMEOUT 200 | ||
| 38 | 37 | ||
| 39 | static const char *radeon_pm_state_type_name[5] = { | 38 | static const char *radeon_pm_state_type_name[5] = { |
| 40 | "Default", | 39 | "Default", |
| @@ -251,21 +250,14 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) | |||
| 251 | return; | 250 | return; |
| 252 | 251 | ||
| 253 | mutex_lock(&rdev->ddev->struct_mutex); | 252 | mutex_lock(&rdev->ddev->struct_mutex); |
| 254 | mutex_lock(&rdev->vram_mutex); | 253 | down_write(&rdev->pm.mclk_lock); |
| 255 | mutex_lock(&rdev->ring_lock); | 254 | mutex_lock(&rdev->ring_lock); |
| 256 | 255 | ||
| 257 | /* gui idle int has issues on older chips it seems */ | 256 | /* gui idle int has issues on older chips it seems */ |
| 258 | if (rdev->family >= CHIP_R600) { | 257 | if (rdev->family >= CHIP_R600) { |
| 259 | if (rdev->irq.installed) { | 258 | if (rdev->irq.installed) { |
| 260 | /* wait for GPU idle */ | 259 | /* wait for GPU to become idle */ |
| 261 | rdev->pm.gui_idle = false; | 260 | radeon_irq_kms_wait_gui_idle(rdev); |
| 262 | rdev->irq.gui_idle = true; | ||
| 263 | radeon_irq_set(rdev); | ||
| 264 | wait_event_interruptible_timeout( | ||
| 265 | rdev->irq.idle_queue, rdev->pm.gui_idle, | ||
| 266 | msecs_to_jiffies(RADEON_WAIT_IDLE_TIMEOUT)); | ||
| 267 | rdev->irq.gui_idle = false; | ||
| 268 | radeon_irq_set(rdev); | ||
| 269 | } | 261 | } |
| 270 | } else { | 262 | } else { |
| 271 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | 263 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
| @@ -303,7 +295,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) | |||
| 303 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; | 295 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; |
| 304 | 296 | ||
| 305 | mutex_unlock(&rdev->ring_lock); | 297 | mutex_unlock(&rdev->ring_lock); |
| 306 | mutex_unlock(&rdev->vram_mutex); | 298 | up_write(&rdev->pm.mclk_lock); |
| 307 | mutex_unlock(&rdev->ddev->struct_mutex); | 299 | mutex_unlock(&rdev->ddev->struct_mutex); |
| 308 | } | 300 | } |
| 309 | 301 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 983658c91358..ec79b3750430 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c | |||
| @@ -35,47 +35,97 @@ | |||
| 35 | #include "atom.h" | 35 | #include "atom.h" |
| 36 | 36 | ||
| 37 | /* | 37 | /* |
| 38 | * IB. | 38 | * IB |
| 39 | * IBs (Indirect Buffers) and areas of GPU accessible memory where | ||
| 40 | * commands are stored. You can put a pointer to the IB in the | ||
| 41 | * command ring and the hw will fetch the commands from the IB | ||
| 42 | * and execute them. Generally userspace acceleration drivers | ||
| 43 | * produce command buffers which are send to the kernel and | ||
| 44 | * put in IBs for execution by the requested ring. | ||
| 39 | */ | 45 | */ |
| 40 | int radeon_debugfs_sa_init(struct radeon_device *rdev); | 46 | int radeon_debugfs_sa_init(struct radeon_device *rdev); |
| 41 | 47 | ||
| 48 | /** | ||
| 49 | * radeon_ib_get - request an IB (Indirect Buffer) | ||
| 50 | * | ||
| 51 | * @rdev: radeon_device pointer | ||
| 52 | * @ring: ring index the IB is associated with | ||
| 53 | * @ib: IB object returned | ||
| 54 | * @size: requested IB size | ||
| 55 | * | ||
| 56 | * Request an IB (all asics). IBs are allocated using the | ||
| 57 | * suballocator. | ||
| 58 | * Returns 0 on success, error on failure. | ||
| 59 | */ | ||
| 42 | int radeon_ib_get(struct radeon_device *rdev, int ring, | 60 | int radeon_ib_get(struct radeon_device *rdev, int ring, |
| 43 | struct radeon_ib *ib, unsigned size) | 61 | struct radeon_ib *ib, unsigned size) |
| 44 | { | 62 | { |
| 45 | int r; | 63 | int i, r; |
| 46 | 64 | ||
| 47 | r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &ib->sa_bo, size, 256, true); | 65 | r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &ib->sa_bo, size, 256, true); |
| 48 | if (r) { | 66 | if (r) { |
| 49 | dev_err(rdev->dev, "failed to get a new IB (%d)\n", r); | 67 | dev_err(rdev->dev, "failed to get a new IB (%d)\n", r); |
| 50 | return r; | 68 | return r; |
| 51 | } | 69 | } |
| 52 | r = radeon_fence_create(rdev, &ib->fence, ring); | 70 | |
| 71 | r = radeon_semaphore_create(rdev, &ib->semaphore); | ||
| 53 | if (r) { | 72 | if (r) { |
| 54 | dev_err(rdev->dev, "failed to create fence for new IB (%d)\n", r); | ||
| 55 | radeon_sa_bo_free(rdev, &ib->sa_bo, NULL); | ||
| 56 | return r; | 73 | return r; |
| 57 | } | 74 | } |
| 58 | 75 | ||
| 76 | ib->ring = ring; | ||
| 77 | ib->fence = NULL; | ||
| 59 | ib->ptr = radeon_sa_bo_cpu_addr(ib->sa_bo); | 78 | ib->ptr = radeon_sa_bo_cpu_addr(ib->sa_bo); |
| 60 | ib->gpu_addr = radeon_sa_bo_gpu_addr(ib->sa_bo); | 79 | ib->gpu_addr = radeon_sa_bo_gpu_addr(ib->sa_bo); |
| 61 | ib->vm_id = 0; | 80 | ib->vm_id = 0; |
| 62 | ib->is_const_ib = false; | 81 | ib->is_const_ib = false; |
| 63 | ib->semaphore = NULL; | 82 | for (i = 0; i < RADEON_NUM_RINGS; ++i) |
| 83 | ib->sync_to[i] = NULL; | ||
| 64 | 84 | ||
| 65 | return 0; | 85 | return 0; |
| 66 | } | 86 | } |
| 67 | 87 | ||
| 88 | /** | ||
| 89 | * radeon_ib_free - free an IB (Indirect Buffer) | ||
| 90 | * | ||
| 91 | * @rdev: radeon_device pointer | ||
| 92 | * @ib: IB object to free | ||
| 93 | * | ||
| 94 | * Free an IB (all asics). | ||
| 95 | */ | ||
| 68 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib) | 96 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib) |
| 69 | { | 97 | { |
| 70 | radeon_semaphore_free(rdev, ib->semaphore, ib->fence); | 98 | radeon_semaphore_free(rdev, &ib->semaphore, ib->fence); |
| 71 | radeon_sa_bo_free(rdev, &ib->sa_bo, ib->fence); | 99 | radeon_sa_bo_free(rdev, &ib->sa_bo, ib->fence); |
| 72 | radeon_fence_unref(&ib->fence); | 100 | radeon_fence_unref(&ib->fence); |
| 73 | } | 101 | } |
| 74 | 102 | ||
| 75 | int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) | 103 | /** |
| 104 | * radeon_ib_schedule - schedule an IB (Indirect Buffer) on the ring | ||
| 105 | * | ||
| 106 | * @rdev: radeon_device pointer | ||
| 107 | * @ib: IB object to schedule | ||
| 108 | * @const_ib: Const IB to schedule (SI only) | ||
| 109 | * | ||
| 110 | * Schedule an IB on the associated ring (all asics). | ||
| 111 | * Returns 0 on success, error on failure. | ||
| 112 | * | ||
| 113 | * On SI, there are two parallel engines fed from the primary ring, | ||
| 114 | * the CE (Constant Engine) and the DE (Drawing Engine). Since | ||
| 115 | * resource descriptors have moved to memory, the CE allows you to | ||
| 116 | * prime the caches while the DE is updating register state so that | ||
| 117 | * the resource descriptors will be already in cache when the draw is | ||
| 118 | * processed. To accomplish this, the userspace driver submits two | ||
| 119 | * IBs, one for the CE and one for the DE. If there is a CE IB (called | ||
| 120 | * a CONST_IB), it will be put on the ring prior to the DE IB. Prior | ||
| 121 | * to SI there was just a DE IB. | ||
| 122 | */ | ||
| 123 | int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, | ||
| 124 | struct radeon_ib *const_ib) | ||
| 76 | { | 125 | { |
| 77 | struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; | 126 | struct radeon_ring *ring = &rdev->ring[ib->ring]; |
| 78 | int r = 0; | 127 | bool need_sync = false; |
| 128 | int i, r = 0; | ||
| 79 | 129 | ||
| 80 | if (!ib->length_dw || !ring->ready) { | 130 | if (!ib->length_dw || !ring->ready) { |
| 81 | /* TODO: Nothings in the ib we should report. */ | 131 | /* TODO: Nothings in the ib we should report. */ |
| @@ -84,17 +134,51 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) | |||
| 84 | } | 134 | } |
| 85 | 135 | ||
| 86 | /* 64 dwords should be enough for fence too */ | 136 | /* 64 dwords should be enough for fence too */ |
| 87 | r = radeon_ring_lock(rdev, ring, 64); | 137 | r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_RINGS * 8); |
| 88 | if (r) { | 138 | if (r) { |
| 89 | dev_err(rdev->dev, "scheduling IB failed (%d).\n", r); | 139 | dev_err(rdev->dev, "scheduling IB failed (%d).\n", r); |
| 90 | return r; | 140 | return r; |
| 91 | } | 141 | } |
| 92 | radeon_ring_ib_execute(rdev, ib->fence->ring, ib); | 142 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
| 93 | radeon_fence_emit(rdev, ib->fence); | 143 | struct radeon_fence *fence = ib->sync_to[i]; |
| 144 | if (radeon_fence_need_sync(fence, ib->ring)) { | ||
| 145 | need_sync = true; | ||
| 146 | radeon_semaphore_sync_rings(rdev, ib->semaphore, | ||
| 147 | fence->ring, ib->ring); | ||
| 148 | radeon_fence_note_sync(fence, ib->ring); | ||
| 149 | } | ||
| 150 | } | ||
| 151 | /* immediately free semaphore when we don't need to sync */ | ||
| 152 | if (!need_sync) { | ||
| 153 | radeon_semaphore_free(rdev, &ib->semaphore, NULL); | ||
| 154 | } | ||
| 155 | if (const_ib) { | ||
| 156 | radeon_ring_ib_execute(rdev, const_ib->ring, const_ib); | ||
| 157 | radeon_semaphore_free(rdev, &const_ib->semaphore, NULL); | ||
| 158 | } | ||
| 159 | radeon_ring_ib_execute(rdev, ib->ring, ib); | ||
| 160 | r = radeon_fence_emit(rdev, &ib->fence, ib->ring); | ||
| 161 | if (r) { | ||
| 162 | dev_err(rdev->dev, "failed to emit fence for new IB (%d)\n", r); | ||
| 163 | radeon_ring_unlock_undo(rdev, ring); | ||
| 164 | return r; | ||
| 165 | } | ||
| 166 | if (const_ib) { | ||
| 167 | const_ib->fence = radeon_fence_ref(ib->fence); | ||
| 168 | } | ||
| 94 | radeon_ring_unlock_commit(rdev, ring); | 169 | radeon_ring_unlock_commit(rdev, ring); |
| 95 | return 0; | 170 | return 0; |
| 96 | } | 171 | } |
| 97 | 172 | ||
| 173 | /** | ||
| 174 | * radeon_ib_pool_init - Init the IB (Indirect Buffer) pool | ||
| 175 | * | ||
| 176 | * @rdev: radeon_device pointer | ||
| 177 | * | ||
| 178 | * Initialize the suballocator to manage a pool of memory | ||
| 179 | * for use as IBs (all asics). | ||
| 180 | * Returns 0 on success, error on failure. | ||
| 181 | */ | ||
| 98 | int radeon_ib_pool_init(struct radeon_device *rdev) | 182 | int radeon_ib_pool_init(struct radeon_device *rdev) |
| 99 | { | 183 | { |
| 100 | int r; | 184 | int r; |
| @@ -108,6 +192,12 @@ int radeon_ib_pool_init(struct radeon_device *rdev) | |||
| 108 | if (r) { | 192 | if (r) { |
| 109 | return r; | 193 | return r; |
| 110 | } | 194 | } |
| 195 | |||
| 196 | r = radeon_sa_bo_manager_start(rdev, &rdev->ring_tmp_bo); | ||
| 197 | if (r) { | ||
| 198 | return r; | ||
| 199 | } | ||
| 200 | |||
| 111 | rdev->ib_pool_ready = true; | 201 | rdev->ib_pool_ready = true; |
| 112 | if (radeon_debugfs_sa_init(rdev)) { | 202 | if (radeon_debugfs_sa_init(rdev)) { |
| 113 | dev_err(rdev->dev, "failed to register debugfs file for SA\n"); | 203 | dev_err(rdev->dev, "failed to register debugfs file for SA\n"); |
| @@ -115,24 +205,33 @@ int radeon_ib_pool_init(struct radeon_device *rdev) | |||
| 115 | return 0; | 205 | return 0; |
| 116 | } | 206 | } |
| 117 | 207 | ||
| 208 | /** | ||
| 209 | * radeon_ib_pool_fini - Free the IB (Indirect Buffer) pool | ||
| 210 | * | ||
| 211 | * @rdev: radeon_device pointer | ||
| 212 | * | ||
| 213 | * Tear down the suballocator managing the pool of memory | ||
| 214 | * for use as IBs (all asics). | ||
| 215 | */ | ||
| 118 | void radeon_ib_pool_fini(struct radeon_device *rdev) | 216 | void radeon_ib_pool_fini(struct radeon_device *rdev) |
| 119 | { | 217 | { |
| 120 | if (rdev->ib_pool_ready) { | 218 | if (rdev->ib_pool_ready) { |
| 219 | radeon_sa_bo_manager_suspend(rdev, &rdev->ring_tmp_bo); | ||
| 121 | radeon_sa_bo_manager_fini(rdev, &rdev->ring_tmp_bo); | 220 | radeon_sa_bo_manager_fini(rdev, &rdev->ring_tmp_bo); |
| 122 | rdev->ib_pool_ready = false; | 221 | rdev->ib_pool_ready = false; |
| 123 | } | 222 | } |
| 124 | } | 223 | } |
| 125 | 224 | ||
| 126 | int radeon_ib_pool_start(struct radeon_device *rdev) | 225 | /** |
| 127 | { | 226 | * radeon_ib_ring_tests - test IBs on the rings |
| 128 | return radeon_sa_bo_manager_start(rdev, &rdev->ring_tmp_bo); | 227 | * |
| 129 | } | 228 | * @rdev: radeon_device pointer |
| 130 | 229 | * | |
| 131 | int radeon_ib_pool_suspend(struct radeon_device *rdev) | 230 | * Test an IB (Indirect Buffer) on each ring. |
| 132 | { | 231 | * If the test fails, disable the ring. |
| 133 | return radeon_sa_bo_manager_suspend(rdev, &rdev->ring_tmp_bo); | 232 | * Returns 0 on success, error if the primary GFX ring |
| 134 | } | 233 | * IB test fails. |
| 135 | 234 | */ | |
| 136 | int radeon_ib_ring_tests(struct radeon_device *rdev) | 235 | int radeon_ib_ring_tests(struct radeon_device *rdev) |
| 137 | { | 236 | { |
| 138 | unsigned i; | 237 | unsigned i; |
| @@ -164,10 +263,28 @@ int radeon_ib_ring_tests(struct radeon_device *rdev) | |||
| 164 | } | 263 | } |
| 165 | 264 | ||
| 166 | /* | 265 | /* |
| 167 | * Ring. | 266 | * Rings |
| 267 | * Most engines on the GPU are fed via ring buffers. Ring | ||
| 268 | * buffers are areas of GPU accessible memory that the host | ||
| 269 | * writes commands into and the GPU reads commands out of. | ||
| 270 | * There is a rptr (read pointer) that determines where the | ||
| 271 | * GPU is currently reading, and a wptr (write pointer) | ||
| 272 | * which determines where the host has written. When the | ||
| 273 | * pointers are equal, the ring is idle. When the host | ||
| 274 | * writes commands to the ring buffer, it increments the | ||
| 275 | * wptr. The GPU then starts fetching commands and executes | ||
| 276 | * them until the pointers are equal again. | ||
| 168 | */ | 277 | */ |
| 169 | int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring); | 278 | int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring); |
| 170 | 279 | ||
| 280 | /** | ||
| 281 | * radeon_ring_write - write a value to the ring | ||
| 282 | * | ||
| 283 | * @ring: radeon_ring structure holding ring information | ||
| 284 | * @v: dword (dw) value to write | ||
| 285 | * | ||
| 286 | * Write a value to the requested ring buffer (all asics). | ||
| 287 | */ | ||
| 171 | void radeon_ring_write(struct radeon_ring *ring, uint32_t v) | 288 | void radeon_ring_write(struct radeon_ring *ring, uint32_t v) |
| 172 | { | 289 | { |
| 173 | #if DRM_DEBUG_CODE | 290 | #if DRM_DEBUG_CODE |
| @@ -181,21 +298,37 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v) | |||
| 181 | ring->ring_free_dw--; | 298 | ring->ring_free_dw--; |
| 182 | } | 299 | } |
| 183 | 300 | ||
| 184 | int radeon_ring_index(struct radeon_device *rdev, struct radeon_ring *ring) | 301 | /** |
| 302 | * radeon_ring_supports_scratch_reg - check if the ring supports | ||
| 303 | * writing to scratch registers | ||
| 304 | * | ||
| 305 | * @rdev: radeon_device pointer | ||
| 306 | * @ring: radeon_ring structure holding ring information | ||
| 307 | * | ||
| 308 | * Check if a specific ring supports writing to scratch registers (all asics). | ||
| 309 | * Returns true if the ring supports writing to scratch regs, false if not. | ||
| 310 | */ | ||
| 311 | bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev, | ||
| 312 | struct radeon_ring *ring) | ||
| 185 | { | 313 | { |
| 186 | /* r1xx-r5xx only has CP ring */ | 314 | switch (ring->idx) { |
| 187 | if (rdev->family < CHIP_R600) | 315 | case RADEON_RING_TYPE_GFX_INDEX: |
| 188 | return RADEON_RING_TYPE_GFX_INDEX; | 316 | case CAYMAN_RING_TYPE_CP1_INDEX: |
| 189 | 317 | case CAYMAN_RING_TYPE_CP2_INDEX: | |
| 190 | if (rdev->family >= CHIP_CAYMAN) { | 318 | return true; |
| 191 | if (ring == &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]) | 319 | default: |
| 192 | return CAYMAN_RING_TYPE_CP1_INDEX; | 320 | return false; |
| 193 | else if (ring == &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]) | ||
| 194 | return CAYMAN_RING_TYPE_CP2_INDEX; | ||
| 195 | } | 321 | } |
| 196 | return RADEON_RING_TYPE_GFX_INDEX; | ||
| 197 | } | 322 | } |
| 198 | 323 | ||
| 324 | /** | ||
| 325 | * radeon_ring_free_size - update the free size | ||
| 326 | * | ||
| 327 | * @rdev: radeon_device pointer | ||
| 328 | * @ring: radeon_ring structure holding ring information | ||
| 329 | * | ||
| 330 | * Update the free dw slots in the ring buffer (all asics). | ||
| 331 | */ | ||
| 199 | void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) | 332 | void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) |
| 200 | { | 333 | { |
| 201 | u32 rptr; | 334 | u32 rptr; |
| @@ -214,7 +347,16 @@ void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 214 | } | 347 | } |
| 215 | } | 348 | } |
| 216 | 349 | ||
| 217 | 350 | /** | |
| 351 | * radeon_ring_alloc - allocate space on the ring buffer | ||
| 352 | * | ||
| 353 | * @rdev: radeon_device pointer | ||
| 354 | * @ring: radeon_ring structure holding ring information | ||
| 355 | * @ndw: number of dwords to allocate in the ring buffer | ||
| 356 | * | ||
| 357 | * Allocate @ndw dwords in the ring buffer (all asics). | ||
| 358 | * Returns 0 on success, error on failure. | ||
| 359 | */ | ||
| 218 | int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) | 360 | int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) |
| 219 | { | 361 | { |
| 220 | int r; | 362 | int r; |
| @@ -227,7 +369,7 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi | |||
| 227 | if (ndw < ring->ring_free_dw) { | 369 | if (ndw < ring->ring_free_dw) { |
| 228 | break; | 370 | break; |
| 229 | } | 371 | } |
| 230 | r = radeon_fence_wait_next_locked(rdev, radeon_ring_index(rdev, ring)); | 372 | r = radeon_fence_wait_next_locked(rdev, ring->idx); |
| 231 | if (r) | 373 | if (r) |
| 232 | return r; | 374 | return r; |
| 233 | } | 375 | } |
| @@ -236,6 +378,17 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi | |||
| 236 | return 0; | 378 | return 0; |
| 237 | } | 379 | } |
| 238 | 380 | ||
| 381 | /** | ||
| 382 | * radeon_ring_lock - lock the ring and allocate space on it | ||
| 383 | * | ||
| 384 | * @rdev: radeon_device pointer | ||
| 385 | * @ring: radeon_ring structure holding ring information | ||
| 386 | * @ndw: number of dwords to allocate in the ring buffer | ||
| 387 | * | ||
| 388 | * Lock the ring and allocate @ndw dwords in the ring buffer | ||
| 389 | * (all asics). | ||
| 390 | * Returns 0 on success, error on failure. | ||
| 391 | */ | ||
| 239 | int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) | 392 | int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) |
| 240 | { | 393 | { |
| 241 | int r; | 394 | int r; |
| @@ -249,15 +402,20 @@ int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsig | |||
| 249 | return 0; | 402 | return 0; |
| 250 | } | 403 | } |
| 251 | 404 | ||
| 405 | /** | ||
| 406 | * radeon_ring_commit - tell the GPU to execute the new | ||
| 407 | * commands on the ring buffer | ||
| 408 | * | ||
| 409 | * @rdev: radeon_device pointer | ||
| 410 | * @ring: radeon_ring structure holding ring information | ||
| 411 | * | ||
| 412 | * Update the wptr (write pointer) to tell the GPU to | ||
| 413 | * execute new commands on the ring buffer (all asics). | ||
| 414 | */ | ||
| 252 | void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring) | 415 | void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring) |
| 253 | { | 416 | { |
| 254 | unsigned count_dw_pad; | ||
| 255 | unsigned i; | ||
| 256 | |||
| 257 | /* We pad to match fetch size */ | 417 | /* We pad to match fetch size */ |
| 258 | count_dw_pad = (ring->align_mask + 1) - | 418 | while (ring->wptr & ring->align_mask) { |
| 259 | (ring->wptr & ring->align_mask); | ||
| 260 | for (i = 0; i < count_dw_pad; i++) { | ||
| 261 | radeon_ring_write(ring, ring->nop); | 419 | radeon_ring_write(ring, ring->nop); |
| 262 | } | 420 | } |
| 263 | DRM_MEMORYBARRIER(); | 421 | DRM_MEMORYBARRIER(); |
| @@ -265,23 +423,55 @@ void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring) | |||
| 265 | (void)RREG32(ring->wptr_reg); | 423 | (void)RREG32(ring->wptr_reg); |
| 266 | } | 424 | } |
| 267 | 425 | ||
| 426 | /** | ||
| 427 | * radeon_ring_unlock_commit - tell the GPU to execute the new | ||
| 428 | * commands on the ring buffer and unlock it | ||
| 429 | * | ||
| 430 | * @rdev: radeon_device pointer | ||
| 431 | * @ring: radeon_ring structure holding ring information | ||
| 432 | * | ||
| 433 | * Call radeon_ring_commit() then unlock the ring (all asics). | ||
| 434 | */ | ||
| 268 | void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring) | 435 | void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring) |
| 269 | { | 436 | { |
| 270 | radeon_ring_commit(rdev, ring); | 437 | radeon_ring_commit(rdev, ring); |
| 271 | mutex_unlock(&rdev->ring_lock); | 438 | mutex_unlock(&rdev->ring_lock); |
| 272 | } | 439 | } |
| 273 | 440 | ||
| 441 | /** | ||
| 442 | * radeon_ring_undo - reset the wptr | ||
| 443 | * | ||
| 444 | * @ring: radeon_ring structure holding ring information | ||
| 445 | * | ||
| 446 | * Reset the driver's copy of the wtpr (all asics). | ||
| 447 | */ | ||
| 274 | void radeon_ring_undo(struct radeon_ring *ring) | 448 | void radeon_ring_undo(struct radeon_ring *ring) |
| 275 | { | 449 | { |
| 276 | ring->wptr = ring->wptr_old; | 450 | ring->wptr = ring->wptr_old; |
| 277 | } | 451 | } |
| 278 | 452 | ||
| 453 | /** | ||
| 454 | * radeon_ring_unlock_undo - reset the wptr and unlock the ring | ||
| 455 | * | ||
| 456 | * @ring: radeon_ring structure holding ring information | ||
| 457 | * | ||
| 458 | * Call radeon_ring_undo() then unlock the ring (all asics). | ||
| 459 | */ | ||
| 279 | void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *ring) | 460 | void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *ring) |
| 280 | { | 461 | { |
| 281 | radeon_ring_undo(ring); | 462 | radeon_ring_undo(ring); |
| 282 | mutex_unlock(&rdev->ring_lock); | 463 | mutex_unlock(&rdev->ring_lock); |
| 283 | } | 464 | } |
| 284 | 465 | ||
| 466 | /** | ||
| 467 | * radeon_ring_force_activity - add some nop packets to the ring | ||
| 468 | * | ||
| 469 | * @rdev: radeon_device pointer | ||
| 470 | * @ring: radeon_ring structure holding ring information | ||
| 471 | * | ||
| 472 | * Add some nop packets to the ring to force activity (all asics). | ||
| 473 | * Used for lockup detection to see if the rptr is advancing. | ||
| 474 | */ | ||
| 285 | void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring) | 475 | void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring) |
| 286 | { | 476 | { |
| 287 | int r; | 477 | int r; |
| @@ -296,6 +486,13 @@ void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring * | |||
| 296 | } | 486 | } |
| 297 | } | 487 | } |
| 298 | 488 | ||
| 489 | /** | ||
| 490 | * radeon_ring_force_activity - update lockup variables | ||
| 491 | * | ||
| 492 | * @ring: radeon_ring structure holding ring information | ||
| 493 | * | ||
| 494 | * Update the last rptr value and timestamp (all asics). | ||
| 495 | */ | ||
| 299 | void radeon_ring_lockup_update(struct radeon_ring *ring) | 496 | void radeon_ring_lockup_update(struct radeon_ring *ring) |
| 300 | { | 497 | { |
| 301 | ring->last_rptr = ring->rptr; | 498 | ring->last_rptr = ring->rptr; |
| @@ -349,6 +546,116 @@ bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *rin | |||
| 349 | return false; | 546 | return false; |
| 350 | } | 547 | } |
| 351 | 548 | ||
| 549 | /** | ||
| 550 | * radeon_ring_backup - Back up the content of a ring | ||
| 551 | * | ||
| 552 | * @rdev: radeon_device pointer | ||
| 553 | * @ring: the ring we want to back up | ||
| 554 | * | ||
| 555 | * Saves all unprocessed commits from a ring, returns the number of dwords saved. | ||
| 556 | */ | ||
| 557 | unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring, | ||
| 558 | uint32_t **data) | ||
| 559 | { | ||
| 560 | unsigned size, ptr, i; | ||
| 561 | |||
| 562 | /* just in case lock the ring */ | ||
| 563 | mutex_lock(&rdev->ring_lock); | ||
| 564 | *data = NULL; | ||
| 565 | |||
| 566 | if (ring->ring_obj == NULL) { | ||
| 567 | mutex_unlock(&rdev->ring_lock); | ||
| 568 | return 0; | ||
| 569 | } | ||
| 570 | |||
| 571 | /* it doesn't make sense to save anything if all fences are signaled */ | ||
| 572 | if (!radeon_fence_count_emitted(rdev, ring->idx)) { | ||
| 573 | mutex_unlock(&rdev->ring_lock); | ||
| 574 | return 0; | ||
| 575 | } | ||
| 576 | |||
| 577 | /* calculate the number of dw on the ring */ | ||
| 578 | if (ring->rptr_save_reg) | ||
| 579 | ptr = RREG32(ring->rptr_save_reg); | ||
| 580 | else if (rdev->wb.enabled) | ||
| 581 | ptr = le32_to_cpu(*ring->next_rptr_cpu_addr); | ||
| 582 | else { | ||
| 583 | /* no way to read back the next rptr */ | ||
| 584 | mutex_unlock(&rdev->ring_lock); | ||
| 585 | return 0; | ||
| 586 | } | ||
| 587 | |||
| 588 | size = ring->wptr + (ring->ring_size / 4); | ||
| 589 | size -= ptr; | ||
| 590 | size &= ring->ptr_mask; | ||
| 591 | if (size == 0) { | ||
| 592 | mutex_unlock(&rdev->ring_lock); | ||
| 593 | return 0; | ||
| 594 | } | ||
| 595 | |||
| 596 | /* and then save the content of the ring */ | ||
| 597 | *data = kmalloc_array(size, sizeof(uint32_t), GFP_KERNEL); | ||
| 598 | if (!*data) { | ||
| 599 | mutex_unlock(&rdev->ring_lock); | ||
| 600 | return 0; | ||
| 601 | } | ||
| 602 | for (i = 0; i < size; ++i) { | ||
| 603 | (*data)[i] = ring->ring[ptr++]; | ||
| 604 | ptr &= ring->ptr_mask; | ||
| 605 | } | ||
| 606 | |||
| 607 | mutex_unlock(&rdev->ring_lock); | ||
| 608 | return size; | ||
| 609 | } | ||
| 610 | |||
| 611 | /** | ||
| 612 | * radeon_ring_restore - append saved commands to the ring again | ||
| 613 | * | ||
| 614 | * @rdev: radeon_device pointer | ||
| 615 | * @ring: ring to append commands to | ||
| 616 | * @size: number of dwords we want to write | ||
| 617 | * @data: saved commands | ||
| 618 | * | ||
| 619 | * Allocates space on the ring and restore the previously saved commands. | ||
| 620 | */ | ||
| 621 | int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring, | ||
| 622 | unsigned size, uint32_t *data) | ||
| 623 | { | ||
| 624 | int i, r; | ||
| 625 | |||
| 626 | if (!size || !data) | ||
| 627 | return 0; | ||
| 628 | |||
| 629 | /* restore the saved ring content */ | ||
| 630 | r = radeon_ring_lock(rdev, ring, size); | ||
| 631 | if (r) | ||
| 632 | return r; | ||
| 633 | |||
| 634 | for (i = 0; i < size; ++i) { | ||
| 635 | radeon_ring_write(ring, data[i]); | ||
| 636 | } | ||
| 637 | |||
| 638 | radeon_ring_unlock_commit(rdev, ring); | ||
| 639 | kfree(data); | ||
| 640 | return 0; | ||
| 641 | } | ||
| 642 | |||
| 643 | /** | ||
| 644 | * radeon_ring_init - init driver ring struct. | ||
| 645 | * | ||
| 646 | * @rdev: radeon_device pointer | ||
| 647 | * @ring: radeon_ring structure holding ring information | ||
| 648 | * @ring_size: size of the ring | ||
| 649 | * @rptr_offs: offset of the rptr writeback location in the WB buffer | ||
| 650 | * @rptr_reg: MMIO offset of the rptr register | ||
| 651 | * @wptr_reg: MMIO offset of the wptr register | ||
| 652 | * @ptr_reg_shift: bit offset of the rptr/wptr values | ||
| 653 | * @ptr_reg_mask: bit mask of the rptr/wptr values | ||
| 654 | * @nop: nop packet for this ring | ||
| 655 | * | ||
| 656 | * Initialize the driver information for the selected ring (all asics). | ||
| 657 | * Returns 0 on success, error on failure. | ||
| 658 | */ | ||
| 352 | int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size, | 659 | int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size, |
| 353 | unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, | 660 | unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, |
| 354 | u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop) | 661 | u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop) |
| @@ -391,12 +698,25 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig | |||
| 391 | } | 698 | } |
| 392 | ring->ptr_mask = (ring->ring_size / 4) - 1; | 699 | ring->ptr_mask = (ring->ring_size / 4) - 1; |
| 393 | ring->ring_free_dw = ring->ring_size / 4; | 700 | ring->ring_free_dw = ring->ring_size / 4; |
| 701 | if (rdev->wb.enabled) { | ||
| 702 | u32 index = RADEON_WB_RING0_NEXT_RPTR + (ring->idx * 4); | ||
| 703 | ring->next_rptr_gpu_addr = rdev->wb.gpu_addr + index; | ||
| 704 | ring->next_rptr_cpu_addr = &rdev->wb.wb[index/4]; | ||
| 705 | } | ||
| 394 | if (radeon_debugfs_ring_init(rdev, ring)) { | 706 | if (radeon_debugfs_ring_init(rdev, ring)) { |
| 395 | DRM_ERROR("Failed to register debugfs file for rings !\n"); | 707 | DRM_ERROR("Failed to register debugfs file for rings !\n"); |
| 396 | } | 708 | } |
| 397 | return 0; | 709 | return 0; |
| 398 | } | 710 | } |
| 399 | 711 | ||
| 712 | /** | ||
| 713 | * radeon_ring_fini - tear down the driver ring struct. | ||
| 714 | * | ||
| 715 | * @rdev: radeon_device pointer | ||
| 716 | * @ring: radeon_ring structure holding ring information | ||
| 717 | * | ||
| 718 | * Tear down the driver information for the selected ring (all asics). | ||
| 719 | */ | ||
| 400 | void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *ring) | 720 | void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *ring) |
| 401 | { | 721 | { |
| 402 | int r; | 722 | int r; |
| @@ -438,6 +758,10 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data) | |||
| 438 | count = (ring->ring_size / 4) - ring->ring_free_dw; | 758 | count = (ring->ring_size / 4) - ring->ring_free_dw; |
| 439 | seq_printf(m, "wptr(0x%04x): 0x%08x\n", ring->wptr_reg, RREG32(ring->wptr_reg)); | 759 | seq_printf(m, "wptr(0x%04x): 0x%08x\n", ring->wptr_reg, RREG32(ring->wptr_reg)); |
| 440 | seq_printf(m, "rptr(0x%04x): 0x%08x\n", ring->rptr_reg, RREG32(ring->rptr_reg)); | 760 | seq_printf(m, "rptr(0x%04x): 0x%08x\n", ring->rptr_reg, RREG32(ring->rptr_reg)); |
| 761 | if (ring->rptr_save_reg) { | ||
| 762 | seq_printf(m, "rptr next(0x%04x): 0x%08x\n", ring->rptr_save_reg, | ||
| 763 | RREG32(ring->rptr_save_reg)); | ||
| 764 | } | ||
| 441 | seq_printf(m, "driver's copy of the wptr: 0x%08x\n", ring->wptr); | 765 | seq_printf(m, "driver's copy of the wptr: 0x%08x\n", ring->wptr); |
| 442 | seq_printf(m, "driver's copy of the rptr: 0x%08x\n", ring->rptr); | 766 | seq_printf(m, "driver's copy of the rptr: 0x%08x\n", ring->rptr); |
| 443 | seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); | 767 | seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); |
diff --git a/drivers/gpu/drm/radeon/radeon_sa.c b/drivers/gpu/drm/radeon/radeon_sa.c index 32059b745728..4e771240fdd0 100644 --- a/drivers/gpu/drm/radeon/radeon_sa.c +++ b/drivers/gpu/drm/radeon/radeon_sa.c | |||
| @@ -54,7 +54,7 @@ int radeon_sa_bo_manager_init(struct radeon_device *rdev, | |||
| 54 | { | 54 | { |
| 55 | int i, r; | 55 | int i, r; |
| 56 | 56 | ||
| 57 | spin_lock_init(&sa_manager->lock); | 57 | init_waitqueue_head(&sa_manager->wq); |
| 58 | sa_manager->bo = NULL; | 58 | sa_manager->bo = NULL; |
| 59 | sa_manager->size = size; | 59 | sa_manager->size = size; |
| 60 | sa_manager->domain = domain; | 60 | sa_manager->domain = domain; |
| @@ -211,6 +211,39 @@ static bool radeon_sa_bo_try_alloc(struct radeon_sa_manager *sa_manager, | |||
| 211 | return false; | 211 | return false; |
| 212 | } | 212 | } |
| 213 | 213 | ||
| 214 | /** | ||
| 215 | * radeon_sa_event - Check if we can stop waiting | ||
| 216 | * | ||
| 217 | * @sa_manager: pointer to the sa_manager | ||
| 218 | * @size: number of bytes we want to allocate | ||
| 219 | * @align: alignment we need to match | ||
| 220 | * | ||
| 221 | * Check if either there is a fence we can wait for or | ||
| 222 | * enough free memory to satisfy the allocation directly | ||
| 223 | */ | ||
| 224 | static bool radeon_sa_event(struct radeon_sa_manager *sa_manager, | ||
| 225 | unsigned size, unsigned align) | ||
| 226 | { | ||
| 227 | unsigned soffset, eoffset, wasted; | ||
| 228 | int i; | ||
| 229 | |||
| 230 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | ||
| 231 | if (!list_empty(&sa_manager->flist[i])) { | ||
| 232 | return true; | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | soffset = radeon_sa_bo_hole_soffset(sa_manager); | ||
| 237 | eoffset = radeon_sa_bo_hole_eoffset(sa_manager); | ||
| 238 | wasted = (align - (soffset % align)) % align; | ||
| 239 | |||
| 240 | if ((eoffset - soffset) >= (size + wasted)) { | ||
| 241 | return true; | ||
| 242 | } | ||
| 243 | |||
| 244 | return false; | ||
| 245 | } | ||
| 246 | |||
| 214 | static bool radeon_sa_bo_next_hole(struct radeon_sa_manager *sa_manager, | 247 | static bool radeon_sa_bo_next_hole(struct radeon_sa_manager *sa_manager, |
| 215 | struct radeon_fence **fences, | 248 | struct radeon_fence **fences, |
| 216 | unsigned *tries) | 249 | unsigned *tries) |
| @@ -297,8 +330,8 @@ int radeon_sa_bo_new(struct radeon_device *rdev, | |||
| 297 | INIT_LIST_HEAD(&(*sa_bo)->olist); | 330 | INIT_LIST_HEAD(&(*sa_bo)->olist); |
| 298 | INIT_LIST_HEAD(&(*sa_bo)->flist); | 331 | INIT_LIST_HEAD(&(*sa_bo)->flist); |
| 299 | 332 | ||
| 300 | spin_lock(&sa_manager->lock); | 333 | spin_lock(&sa_manager->wq.lock); |
| 301 | do { | 334 | while(1) { |
| 302 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | 335 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
| 303 | fences[i] = NULL; | 336 | fences[i] = NULL; |
| 304 | tries[i] = 0; | 337 | tries[i] = 0; |
| @@ -309,30 +342,34 @@ int radeon_sa_bo_new(struct radeon_device *rdev, | |||
| 309 | 342 | ||
| 310 | if (radeon_sa_bo_try_alloc(sa_manager, *sa_bo, | 343 | if (radeon_sa_bo_try_alloc(sa_manager, *sa_bo, |
| 311 | size, align)) { | 344 | size, align)) { |
| 312 | spin_unlock(&sa_manager->lock); | 345 | spin_unlock(&sa_manager->wq.lock); |
| 313 | return 0; | 346 | return 0; |
| 314 | } | 347 | } |
| 315 | 348 | ||
| 316 | /* see if we can skip over some allocations */ | 349 | /* see if we can skip over some allocations */ |
| 317 | } while (radeon_sa_bo_next_hole(sa_manager, fences, tries)); | 350 | } while (radeon_sa_bo_next_hole(sa_manager, fences, tries)); |
| 318 | 351 | ||
| 319 | if (block) { | 352 | if (!block) { |
| 320 | spin_unlock(&sa_manager->lock); | 353 | break; |
| 321 | r = radeon_fence_wait_any(rdev, fences, false); | 354 | } |
| 322 | spin_lock(&sa_manager->lock); | 355 | |
| 323 | if (r) { | 356 | spin_unlock(&sa_manager->wq.lock); |
| 324 | /* if we have nothing to wait for we | 357 | r = radeon_fence_wait_any(rdev, fences, false); |
| 325 | are practically out of memory */ | 358 | spin_lock(&sa_manager->wq.lock); |
| 326 | if (r == -ENOENT) { | 359 | /* if we have nothing to wait for block */ |
| 327 | r = -ENOMEM; | 360 | if (r == -ENOENT) { |
| 328 | } | 361 | r = wait_event_interruptible_locked( |
| 329 | goto out_err; | 362 | sa_manager->wq, |
| 330 | } | 363 | radeon_sa_event(sa_manager, size, align) |
| 364 | ); | ||
| 365 | } | ||
| 366 | if (r) { | ||
| 367 | goto out_err; | ||
| 331 | } | 368 | } |
| 332 | } while (block); | 369 | }; |
| 333 | 370 | ||
| 334 | out_err: | 371 | out_err: |
| 335 | spin_unlock(&sa_manager->lock); | 372 | spin_unlock(&sa_manager->wq.lock); |
| 336 | kfree(*sa_bo); | 373 | kfree(*sa_bo); |
| 337 | *sa_bo = NULL; | 374 | *sa_bo = NULL; |
| 338 | return r; | 375 | return r; |
| @@ -348,15 +385,16 @@ void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo **sa_bo, | |||
| 348 | } | 385 | } |
| 349 | 386 | ||
| 350 | sa_manager = (*sa_bo)->manager; | 387 | sa_manager = (*sa_bo)->manager; |
| 351 | spin_lock(&sa_manager->lock); | 388 | spin_lock(&sa_manager->wq.lock); |
| 352 | if (fence && fence->seq && fence->seq < RADEON_FENCE_NOTEMITED_SEQ) { | 389 | if (fence && !radeon_fence_signaled(fence)) { |
| 353 | (*sa_bo)->fence = radeon_fence_ref(fence); | 390 | (*sa_bo)->fence = radeon_fence_ref(fence); |
| 354 | list_add_tail(&(*sa_bo)->flist, | 391 | list_add_tail(&(*sa_bo)->flist, |
| 355 | &sa_manager->flist[fence->ring]); | 392 | &sa_manager->flist[fence->ring]); |
| 356 | } else { | 393 | } else { |
| 357 | radeon_sa_bo_remove_locked(*sa_bo); | 394 | radeon_sa_bo_remove_locked(*sa_bo); |
| 358 | } | 395 | } |
| 359 | spin_unlock(&sa_manager->lock); | 396 | wake_up_all_locked(&sa_manager->wq); |
| 397 | spin_unlock(&sa_manager->wq.lock); | ||
| 360 | *sa_bo = NULL; | 398 | *sa_bo = NULL; |
| 361 | } | 399 | } |
| 362 | 400 | ||
| @@ -366,7 +404,7 @@ void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager, | |||
| 366 | { | 404 | { |
| 367 | struct radeon_sa_bo *i; | 405 | struct radeon_sa_bo *i; |
| 368 | 406 | ||
| 369 | spin_lock(&sa_manager->lock); | 407 | spin_lock(&sa_manager->wq.lock); |
| 370 | list_for_each_entry(i, &sa_manager->olist, olist) { | 408 | list_for_each_entry(i, &sa_manager->olist, olist) { |
| 371 | if (&i->olist == sa_manager->hole) { | 409 | if (&i->olist == sa_manager->hole) { |
| 372 | seq_printf(m, ">"); | 410 | seq_printf(m, ">"); |
| @@ -381,6 +419,6 @@ void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager, | |||
| 381 | } | 419 | } |
| 382 | seq_printf(m, "\n"); | 420 | seq_printf(m, "\n"); |
| 383 | } | 421 | } |
| 384 | spin_unlock(&sa_manager->lock); | 422 | spin_unlock(&sa_manager->wq.lock); |
| 385 | } | 423 | } |
| 386 | #endif | 424 | #endif |
diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c index e2ace5dce117..7cc78de6ddc3 100644 --- a/drivers/gpu/drm/radeon/radeon_semaphore.c +++ b/drivers/gpu/drm/radeon/radeon_semaphore.c | |||
| @@ -68,70 +68,49 @@ void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, | |||
| 68 | radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, true); | 68 | radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, true); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | /* caller must hold ring lock */ | ||
| 71 | int radeon_semaphore_sync_rings(struct radeon_device *rdev, | 72 | int radeon_semaphore_sync_rings(struct radeon_device *rdev, |
| 72 | struct radeon_semaphore *semaphore, | 73 | struct radeon_semaphore *semaphore, |
| 73 | bool sync_to[RADEON_NUM_RINGS], | 74 | int signaler, int waiter) |
| 74 | int dst_ring) | ||
| 75 | { | 75 | { |
| 76 | int i = 0, r; | 76 | int r; |
| 77 | 77 | ||
| 78 | mutex_lock(&rdev->ring_lock); | 78 | /* no need to signal and wait on the same ring */ |
| 79 | r = radeon_ring_alloc(rdev, &rdev->ring[dst_ring], RADEON_NUM_RINGS * 8); | 79 | if (signaler == waiter) { |
| 80 | if (r) { | 80 | return 0; |
| 81 | goto error; | ||
| 82 | } | 81 | } |
| 83 | 82 | ||
| 84 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | 83 | /* prevent GPU deadlocks */ |
| 85 | /* no need to sync to our own or unused rings */ | 84 | if (!rdev->ring[signaler].ready) { |
| 86 | if (!sync_to[i] || i == dst_ring) | 85 | dev_err(rdev->dev, "Trying to sync to a disabled ring!"); |
| 87 | continue; | 86 | return -EINVAL; |
| 88 | 87 | } | |
| 89 | /* prevent GPU deadlocks */ | ||
| 90 | if (!rdev->ring[i].ready) { | ||
| 91 | dev_err(rdev->dev, "Trying to sync to a disabled ring!"); | ||
| 92 | r = -EINVAL; | ||
| 93 | goto error; | ||
| 94 | } | ||
| 95 | |||
| 96 | r = radeon_ring_alloc(rdev, &rdev->ring[i], 8); | ||
| 97 | if (r) { | ||
| 98 | goto error; | ||
| 99 | } | ||
| 100 | |||
| 101 | radeon_semaphore_emit_signal(rdev, i, semaphore); | ||
| 102 | radeon_semaphore_emit_wait(rdev, dst_ring, semaphore); | ||
| 103 | 88 | ||
| 104 | radeon_ring_commit(rdev, &rdev->ring[i]); | 89 | r = radeon_ring_alloc(rdev, &rdev->ring[signaler], 8); |
| 90 | if (r) { | ||
| 91 | return r; | ||
| 105 | } | 92 | } |
| 93 | radeon_semaphore_emit_signal(rdev, signaler, semaphore); | ||
| 94 | radeon_ring_commit(rdev, &rdev->ring[signaler]); | ||
| 106 | 95 | ||
| 107 | radeon_ring_commit(rdev, &rdev->ring[dst_ring]); | 96 | /* we assume caller has already allocated space on waiters ring */ |
| 108 | mutex_unlock(&rdev->ring_lock); | 97 | radeon_semaphore_emit_wait(rdev, waiter, semaphore); |
| 109 | 98 | ||
| 110 | return 0; | 99 | return 0; |
| 111 | |||
| 112 | error: | ||
| 113 | /* unlock all locks taken so far */ | ||
| 114 | for (--i; i >= 0; --i) { | ||
| 115 | if (sync_to[i] || i == dst_ring) { | ||
| 116 | radeon_ring_undo(&rdev->ring[i]); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | radeon_ring_undo(&rdev->ring[dst_ring]); | ||
| 120 | mutex_unlock(&rdev->ring_lock); | ||
| 121 | return r; | ||
| 122 | } | 100 | } |
| 123 | 101 | ||
| 124 | void radeon_semaphore_free(struct radeon_device *rdev, | 102 | void radeon_semaphore_free(struct radeon_device *rdev, |
| 125 | struct radeon_semaphore *semaphore, | 103 | struct radeon_semaphore **semaphore, |
| 126 | struct radeon_fence *fence) | 104 | struct radeon_fence *fence) |
| 127 | { | 105 | { |
| 128 | if (semaphore == NULL) { | 106 | if (semaphore == NULL || *semaphore == NULL) { |
| 129 | return; | 107 | return; |
| 130 | } | 108 | } |
| 131 | if (semaphore->waiters > 0) { | 109 | if ((*semaphore)->waiters > 0) { |
| 132 | dev_err(rdev->dev, "semaphore %p has more waiters than signalers," | 110 | dev_err(rdev->dev, "semaphore %p has more waiters than signalers," |
| 133 | " hardware lockup imminent!\n", semaphore); | 111 | " hardware lockup imminent!\n", *semaphore); |
| 134 | } | 112 | } |
| 135 | radeon_sa_bo_free(rdev, &semaphore->sa_bo, fence); | 113 | radeon_sa_bo_free(rdev, &(*semaphore)->sa_bo, fence); |
| 136 | kfree(semaphore); | 114 | kfree(*semaphore); |
| 115 | *semaphore = NULL; | ||
| 137 | } | 116 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c index efff929ea49d..7c16540c10ff 100644 --- a/drivers/gpu/drm/radeon/radeon_test.c +++ b/drivers/gpu/drm/radeon/radeon_test.c | |||
| @@ -106,13 +106,7 @@ void radeon_test_moves(struct radeon_device *rdev) | |||
| 106 | 106 | ||
| 107 | radeon_bo_kunmap(gtt_obj[i]); | 107 | radeon_bo_kunmap(gtt_obj[i]); |
| 108 | 108 | ||
| 109 | r = radeon_fence_create(rdev, &fence, RADEON_RING_TYPE_GFX_INDEX); | 109 | r = radeon_copy(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, &fence); |
| 110 | if (r) { | ||
| 111 | DRM_ERROR("Failed to create GTT->VRAM fence %d\n", i); | ||
| 112 | goto out_cleanup; | ||
| 113 | } | ||
| 114 | |||
| 115 | r = radeon_copy(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, fence); | ||
| 116 | if (r) { | 110 | if (r) { |
| 117 | DRM_ERROR("Failed GTT->VRAM copy %d\n", i); | 111 | DRM_ERROR("Failed GTT->VRAM copy %d\n", i); |
| 118 | goto out_cleanup; | 112 | goto out_cleanup; |
| @@ -155,13 +149,7 @@ void radeon_test_moves(struct radeon_device *rdev) | |||
| 155 | 149 | ||
| 156 | radeon_bo_kunmap(vram_obj); | 150 | radeon_bo_kunmap(vram_obj); |
| 157 | 151 | ||
| 158 | r = radeon_fence_create(rdev, &fence, RADEON_RING_TYPE_GFX_INDEX); | 152 | r = radeon_copy(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, &fence); |
| 159 | if (r) { | ||
| 160 | DRM_ERROR("Failed to create VRAM->GTT fence %d\n", i); | ||
| 161 | goto out_cleanup; | ||
| 162 | } | ||
| 163 | |||
| 164 | r = radeon_copy(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, fence); | ||
| 165 | if (r) { | 153 | if (r) { |
| 166 | DRM_ERROR("Failed VRAM->GTT copy %d\n", i); | 154 | DRM_ERROR("Failed VRAM->GTT copy %d\n", i); |
| 167 | goto out_cleanup; | 155 | goto out_cleanup; |
| @@ -241,36 +229,33 @@ void radeon_test_ring_sync(struct radeon_device *rdev, | |||
| 241 | { | 229 | { |
| 242 | struct radeon_fence *fence1 = NULL, *fence2 = NULL; | 230 | struct radeon_fence *fence1 = NULL, *fence2 = NULL; |
| 243 | struct radeon_semaphore *semaphore = NULL; | 231 | struct radeon_semaphore *semaphore = NULL; |
| 244 | int ridxA = radeon_ring_index(rdev, ringA); | ||
| 245 | int ridxB = radeon_ring_index(rdev, ringB); | ||
| 246 | int r; | 232 | int r; |
| 247 | 233 | ||
| 248 | r = radeon_fence_create(rdev, &fence1, ridxA); | 234 | r = radeon_semaphore_create(rdev, &semaphore); |
| 249 | if (r) { | 235 | if (r) { |
| 250 | DRM_ERROR("Failed to create sync fence 1\n"); | 236 | DRM_ERROR("Failed to create semaphore\n"); |
| 251 | goto out_cleanup; | 237 | goto out_cleanup; |
| 252 | } | 238 | } |
| 253 | r = radeon_fence_create(rdev, &fence2, ridxA); | 239 | |
| 240 | r = radeon_ring_lock(rdev, ringA, 64); | ||
| 254 | if (r) { | 241 | if (r) { |
| 255 | DRM_ERROR("Failed to create sync fence 2\n"); | 242 | DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); |
| 256 | goto out_cleanup; | 243 | goto out_cleanup; |
| 257 | } | 244 | } |
| 258 | 245 | radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); | |
| 259 | r = radeon_semaphore_create(rdev, &semaphore); | 246 | r = radeon_fence_emit(rdev, &fence1, ringA->idx); |
| 260 | if (r) { | 247 | if (r) { |
| 261 | DRM_ERROR("Failed to create semaphore\n"); | 248 | DRM_ERROR("Failed to emit fence 1\n"); |
| 249 | radeon_ring_unlock_undo(rdev, ringA); | ||
| 262 | goto out_cleanup; | 250 | goto out_cleanup; |
| 263 | } | 251 | } |
| 264 | 252 | radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); | |
| 265 | r = radeon_ring_lock(rdev, ringA, 64); | 253 | r = radeon_fence_emit(rdev, &fence2, ringA->idx); |
| 266 | if (r) { | 254 | if (r) { |
| 267 | DRM_ERROR("Failed to lock ring A %d\n", ridxA); | 255 | DRM_ERROR("Failed to emit fence 2\n"); |
| 256 | radeon_ring_unlock_undo(rdev, ringA); | ||
| 268 | goto out_cleanup; | 257 | goto out_cleanup; |
| 269 | } | 258 | } |
| 270 | radeon_semaphore_emit_wait(rdev, ridxA, semaphore); | ||
| 271 | radeon_fence_emit(rdev, fence1); | ||
| 272 | radeon_semaphore_emit_wait(rdev, ridxA, semaphore); | ||
| 273 | radeon_fence_emit(rdev, fence2); | ||
| 274 | radeon_ring_unlock_commit(rdev, ringA); | 259 | radeon_ring_unlock_commit(rdev, ringA); |
| 275 | 260 | ||
| 276 | mdelay(1000); | 261 | mdelay(1000); |
| @@ -285,7 +270,7 @@ void radeon_test_ring_sync(struct radeon_device *rdev, | |||
| 285 | DRM_ERROR("Failed to lock ring B %p\n", ringB); | 270 | DRM_ERROR("Failed to lock ring B %p\n", ringB); |
| 286 | goto out_cleanup; | 271 | goto out_cleanup; |
| 287 | } | 272 | } |
| 288 | radeon_semaphore_emit_signal(rdev, ridxB, semaphore); | 273 | radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore); |
| 289 | radeon_ring_unlock_commit(rdev, ringB); | 274 | radeon_ring_unlock_commit(rdev, ringB); |
| 290 | 275 | ||
| 291 | r = radeon_fence_wait(fence1, false); | 276 | r = radeon_fence_wait(fence1, false); |
| @@ -306,7 +291,7 @@ void radeon_test_ring_sync(struct radeon_device *rdev, | |||
| 306 | DRM_ERROR("Failed to lock ring B %p\n", ringB); | 291 | DRM_ERROR("Failed to lock ring B %p\n", ringB); |
| 307 | goto out_cleanup; | 292 | goto out_cleanup; |
| 308 | } | 293 | } |
| 309 | radeon_semaphore_emit_signal(rdev, ridxB, semaphore); | 294 | radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore); |
| 310 | radeon_ring_unlock_commit(rdev, ringB); | 295 | radeon_ring_unlock_commit(rdev, ringB); |
| 311 | 296 | ||
| 312 | r = radeon_fence_wait(fence2, false); | 297 | r = radeon_fence_wait(fence2, false); |
| @@ -316,8 +301,7 @@ void radeon_test_ring_sync(struct radeon_device *rdev, | |||
| 316 | } | 301 | } |
| 317 | 302 | ||
| 318 | out_cleanup: | 303 | out_cleanup: |
| 319 | if (semaphore) | 304 | radeon_semaphore_free(rdev, &semaphore, NULL); |
| 320 | radeon_semaphore_free(rdev, semaphore, NULL); | ||
| 321 | 305 | ||
| 322 | if (fence1) | 306 | if (fence1) |
| 323 | radeon_fence_unref(&fence1); | 307 | radeon_fence_unref(&fence1); |
| @@ -336,23 +320,9 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, | |||
| 336 | { | 320 | { |
| 337 | struct radeon_fence *fenceA = NULL, *fenceB = NULL; | 321 | struct radeon_fence *fenceA = NULL, *fenceB = NULL; |
| 338 | struct radeon_semaphore *semaphore = NULL; | 322 | struct radeon_semaphore *semaphore = NULL; |
| 339 | int ridxA = radeon_ring_index(rdev, ringA); | ||
| 340 | int ridxB = radeon_ring_index(rdev, ringB); | ||
| 341 | int ridxC = radeon_ring_index(rdev, ringC); | ||
| 342 | bool sigA, sigB; | 323 | bool sigA, sigB; |
| 343 | int i, r; | 324 | int i, r; |
| 344 | 325 | ||
| 345 | r = radeon_fence_create(rdev, &fenceA, ridxA); | ||
| 346 | if (r) { | ||
| 347 | DRM_ERROR("Failed to create sync fence 1\n"); | ||
| 348 | goto out_cleanup; | ||
| 349 | } | ||
| 350 | r = radeon_fence_create(rdev, &fenceB, ridxB); | ||
| 351 | if (r) { | ||
| 352 | DRM_ERROR("Failed to create sync fence 2\n"); | ||
| 353 | goto out_cleanup; | ||
| 354 | } | ||
| 355 | |||
| 356 | r = radeon_semaphore_create(rdev, &semaphore); | 326 | r = radeon_semaphore_create(rdev, &semaphore); |
| 357 | if (r) { | 327 | if (r) { |
| 358 | DRM_ERROR("Failed to create semaphore\n"); | 328 | DRM_ERROR("Failed to create semaphore\n"); |
| @@ -361,20 +331,30 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, | |||
| 361 | 331 | ||
| 362 | r = radeon_ring_lock(rdev, ringA, 64); | 332 | r = radeon_ring_lock(rdev, ringA, 64); |
| 363 | if (r) { | 333 | if (r) { |
| 364 | DRM_ERROR("Failed to lock ring A %d\n", ridxA); | 334 | DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); |
| 335 | goto out_cleanup; | ||
| 336 | } | ||
| 337 | radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); | ||
| 338 | r = radeon_fence_emit(rdev, &fenceA, ringA->idx); | ||
| 339 | if (r) { | ||
| 340 | DRM_ERROR("Failed to emit sync fence 1\n"); | ||
| 341 | radeon_ring_unlock_undo(rdev, ringA); | ||
| 365 | goto out_cleanup; | 342 | goto out_cleanup; |
| 366 | } | 343 | } |
| 367 | radeon_semaphore_emit_wait(rdev, ridxA, semaphore); | ||
| 368 | radeon_fence_emit(rdev, fenceA); | ||
| 369 | radeon_ring_unlock_commit(rdev, ringA); | 344 | radeon_ring_unlock_commit(rdev, ringA); |
| 370 | 345 | ||
| 371 | r = radeon_ring_lock(rdev, ringB, 64); | 346 | r = radeon_ring_lock(rdev, ringB, 64); |
| 372 | if (r) { | 347 | if (r) { |
| 373 | DRM_ERROR("Failed to lock ring B %d\n", ridxB); | 348 | DRM_ERROR("Failed to lock ring B %d\n", ringB->idx); |
| 349 | goto out_cleanup; | ||
| 350 | } | ||
| 351 | radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore); | ||
| 352 | r = radeon_fence_emit(rdev, &fenceB, ringB->idx); | ||
| 353 | if (r) { | ||
| 354 | DRM_ERROR("Failed to create sync fence 2\n"); | ||
| 355 | radeon_ring_unlock_undo(rdev, ringB); | ||
| 374 | goto out_cleanup; | 356 | goto out_cleanup; |
| 375 | } | 357 | } |
| 376 | radeon_semaphore_emit_wait(rdev, ridxB, semaphore); | ||
| 377 | radeon_fence_emit(rdev, fenceB); | ||
| 378 | radeon_ring_unlock_commit(rdev, ringB); | 358 | radeon_ring_unlock_commit(rdev, ringB); |
| 379 | 359 | ||
| 380 | mdelay(1000); | 360 | mdelay(1000); |
| @@ -393,7 +373,7 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, | |||
| 393 | DRM_ERROR("Failed to lock ring B %p\n", ringC); | 373 | DRM_ERROR("Failed to lock ring B %p\n", ringC); |
| 394 | goto out_cleanup; | 374 | goto out_cleanup; |
| 395 | } | 375 | } |
| 396 | radeon_semaphore_emit_signal(rdev, ridxC, semaphore); | 376 | radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore); |
| 397 | radeon_ring_unlock_commit(rdev, ringC); | 377 | radeon_ring_unlock_commit(rdev, ringC); |
| 398 | 378 | ||
| 399 | for (i = 0; i < 30; ++i) { | 379 | for (i = 0; i < 30; ++i) { |
| @@ -419,7 +399,7 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, | |||
| 419 | DRM_ERROR("Failed to lock ring B %p\n", ringC); | 399 | DRM_ERROR("Failed to lock ring B %p\n", ringC); |
| 420 | goto out_cleanup; | 400 | goto out_cleanup; |
| 421 | } | 401 | } |
| 422 | radeon_semaphore_emit_signal(rdev, ridxC, semaphore); | 402 | radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore); |
| 423 | radeon_ring_unlock_commit(rdev, ringC); | 403 | radeon_ring_unlock_commit(rdev, ringC); |
| 424 | 404 | ||
| 425 | mdelay(1000); | 405 | mdelay(1000); |
| @@ -436,8 +416,7 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, | |||
| 436 | } | 416 | } |
| 437 | 417 | ||
| 438 | out_cleanup: | 418 | out_cleanup: |
| 439 | if (semaphore) | 419 | radeon_semaphore_free(rdev, &semaphore, NULL); |
| 440 | radeon_semaphore_free(rdev, semaphore, NULL); | ||
| 441 | 420 | ||
| 442 | if (fenceA) | 421 | if (fenceA) |
| 443 | radeon_fence_unref(&fenceA); | 422 | radeon_fence_unref(&fenceA); |
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index c94a2257761f..5b71c716d83f 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c | |||
| @@ -222,15 +222,11 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, | |||
| 222 | { | 222 | { |
| 223 | struct radeon_device *rdev; | 223 | struct radeon_device *rdev; |
| 224 | uint64_t old_start, new_start; | 224 | uint64_t old_start, new_start; |
| 225 | struct radeon_fence *fence, *old_fence; | 225 | struct radeon_fence *fence; |
| 226 | struct radeon_semaphore *sem = NULL; | 226 | int r, ridx; |
| 227 | int r; | ||
| 228 | 227 | ||
| 229 | rdev = radeon_get_rdev(bo->bdev); | 228 | rdev = radeon_get_rdev(bo->bdev); |
| 230 | r = radeon_fence_create(rdev, &fence, radeon_copy_ring_index(rdev)); | 229 | ridx = radeon_copy_ring_index(rdev); |
| 231 | if (unlikely(r)) { | ||
| 232 | return r; | ||
| 233 | } | ||
| 234 | old_start = old_mem->start << PAGE_SHIFT; | 230 | old_start = old_mem->start << PAGE_SHIFT; |
| 235 | new_start = new_mem->start << PAGE_SHIFT; | 231 | new_start = new_mem->start << PAGE_SHIFT; |
| 236 | 232 | ||
| @@ -243,7 +239,6 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, | |||
| 243 | break; | 239 | break; |
| 244 | default: | 240 | default: |
| 245 | DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); | 241 | DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); |
| 246 | radeon_fence_unref(&fence); | ||
| 247 | return -EINVAL; | 242 | return -EINVAL; |
| 248 | } | 243 | } |
| 249 | switch (new_mem->mem_type) { | 244 | switch (new_mem->mem_type) { |
| @@ -255,46 +250,23 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, | |||
| 255 | break; | 250 | break; |
| 256 | default: | 251 | default: |
| 257 | DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); | 252 | DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); |
| 258 | radeon_fence_unref(&fence); | ||
| 259 | return -EINVAL; | 253 | return -EINVAL; |
| 260 | } | 254 | } |
| 261 | if (!rdev->ring[radeon_copy_ring_index(rdev)].ready) { | 255 | if (!rdev->ring[ridx].ready) { |
| 262 | DRM_ERROR("Trying to move memory with ring turned off.\n"); | 256 | DRM_ERROR("Trying to move memory with ring turned off.\n"); |
| 263 | radeon_fence_unref(&fence); | ||
| 264 | return -EINVAL; | 257 | return -EINVAL; |
| 265 | } | 258 | } |
| 266 | 259 | ||
| 267 | BUILD_BUG_ON((PAGE_SIZE % RADEON_GPU_PAGE_SIZE) != 0); | 260 | BUILD_BUG_ON((PAGE_SIZE % RADEON_GPU_PAGE_SIZE) != 0); |
| 268 | 261 | ||
| 269 | /* sync other rings */ | 262 | /* sync other rings */ |
| 270 | old_fence = bo->sync_obj; | 263 | fence = bo->sync_obj; |
| 271 | if (old_fence && old_fence->ring != fence->ring | ||
| 272 | && !radeon_fence_signaled(old_fence)) { | ||
| 273 | bool sync_to_ring[RADEON_NUM_RINGS] = { }; | ||
| 274 | sync_to_ring[old_fence->ring] = true; | ||
| 275 | |||
| 276 | r = radeon_semaphore_create(rdev, &sem); | ||
| 277 | if (r) { | ||
| 278 | radeon_fence_unref(&fence); | ||
| 279 | return r; | ||
| 280 | } | ||
| 281 | |||
| 282 | r = radeon_semaphore_sync_rings(rdev, sem, | ||
| 283 | sync_to_ring, fence->ring); | ||
| 284 | if (r) { | ||
| 285 | radeon_semaphore_free(rdev, sem, NULL); | ||
| 286 | radeon_fence_unref(&fence); | ||
| 287 | return r; | ||
| 288 | } | ||
| 289 | } | ||
| 290 | |||
| 291 | r = radeon_copy(rdev, old_start, new_start, | 264 | r = radeon_copy(rdev, old_start, new_start, |
| 292 | new_mem->num_pages * (PAGE_SIZE / RADEON_GPU_PAGE_SIZE), /* GPU pages */ | 265 | new_mem->num_pages * (PAGE_SIZE / RADEON_GPU_PAGE_SIZE), /* GPU pages */ |
| 293 | fence); | 266 | &fence); |
| 294 | /* FIXME: handle copy error */ | 267 | /* FIXME: handle copy error */ |
| 295 | r = ttm_bo_move_accel_cleanup(bo, (void *)fence, NULL, | 268 | r = ttm_bo_move_accel_cleanup(bo, (void *)fence, NULL, |
| 296 | evict, no_wait_reserve, no_wait_gpu, new_mem); | 269 | evict, no_wait_reserve, no_wait_gpu, new_mem); |
| 297 | radeon_semaphore_free(rdev, sem, fence); | ||
| 298 | radeon_fence_unref(&fence); | 270 | radeon_fence_unref(&fence); |
| 299 | return r; | 271 | return r; |
| 300 | } | 272 | } |
| @@ -762,9 +734,7 @@ int radeon_ttm_init(struct radeon_device *rdev) | |||
| 762 | } | 734 | } |
| 763 | DRM_INFO("radeon: %uM of GTT memory ready.\n", | 735 | DRM_INFO("radeon: %uM of GTT memory ready.\n", |
| 764 | (unsigned)(rdev->mc.gtt_size / (1024 * 1024))); | 736 | (unsigned)(rdev->mc.gtt_size / (1024 * 1024))); |
| 765 | if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) { | 737 | rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; |
| 766 | rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; | ||
| 767 | } | ||
| 768 | 738 | ||
| 769 | r = radeon_ttm_debugfs_init(rdev); | 739 | r = radeon_ttm_debugfs_init(rdev); |
| 770 | if (r) { | 740 | if (r) { |
| @@ -825,9 +795,9 @@ static int radeon_ttm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 825 | return VM_FAULT_NOPAGE; | 795 | return VM_FAULT_NOPAGE; |
| 826 | } | 796 | } |
| 827 | rdev = radeon_get_rdev(bo->bdev); | 797 | rdev = radeon_get_rdev(bo->bdev); |
| 828 | mutex_lock(&rdev->vram_mutex); | 798 | down_read(&rdev->pm.mclk_lock); |
| 829 | r = ttm_vm_ops->fault(vma, vmf); | 799 | r = ttm_vm_ops->fault(vma, vmf); |
| 830 | mutex_unlock(&rdev->vram_mutex); | 800 | up_read(&rdev->pm.mclk_lock); |
| 831 | return r; | 801 | return r; |
| 832 | } | 802 | } |
| 833 | 803 | ||
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index a464eb5e2df2..2752f7f78237 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c | |||
| @@ -426,13 +426,11 @@ static int rs400_startup(struct radeon_device *rdev) | |||
| 426 | return r; | 426 | return r; |
| 427 | } | 427 | } |
| 428 | 428 | ||
| 429 | r = radeon_ib_pool_start(rdev); | 429 | r = radeon_ib_pool_init(rdev); |
| 430 | if (r) | 430 | if (r) { |
| 431 | return r; | 431 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 432 | |||
| 433 | r = radeon_ib_ring_tests(rdev); | ||
| 434 | if (r) | ||
| 435 | return r; | 432 | return r; |
| 433 | } | ||
| 436 | 434 | ||
| 437 | return 0; | 435 | return 0; |
| 438 | } | 436 | } |
| @@ -470,7 +468,6 @@ int rs400_resume(struct radeon_device *rdev) | |||
| 470 | 468 | ||
| 471 | int rs400_suspend(struct radeon_device *rdev) | 469 | int rs400_suspend(struct radeon_device *rdev) |
| 472 | { | 470 | { |
| 473 | radeon_ib_pool_suspend(rdev); | ||
| 474 | r100_cp_disable(rdev); | 471 | r100_cp_disable(rdev); |
| 475 | radeon_wb_disable(rdev); | 472 | radeon_wb_disable(rdev); |
| 476 | r100_irq_disable(rdev); | 473 | r100_irq_disable(rdev); |
| @@ -482,7 +479,7 @@ void rs400_fini(struct radeon_device *rdev) | |||
| 482 | { | 479 | { |
| 483 | r100_cp_fini(rdev); | 480 | r100_cp_fini(rdev); |
| 484 | radeon_wb_fini(rdev); | 481 | radeon_wb_fini(rdev); |
| 485 | r100_ib_fini(rdev); | 482 | radeon_ib_pool_fini(rdev); |
| 486 | radeon_gem_fini(rdev); | 483 | radeon_gem_fini(rdev); |
| 487 | rs400_gart_fini(rdev); | 484 | rs400_gart_fini(rdev); |
| 488 | radeon_irq_kms_fini(rdev); | 485 | radeon_irq_kms_fini(rdev); |
| @@ -550,20 +547,14 @@ int rs400_init(struct radeon_device *rdev) | |||
| 550 | return r; | 547 | return r; |
| 551 | r300_set_reg_safe(rdev); | 548 | r300_set_reg_safe(rdev); |
| 552 | 549 | ||
| 553 | r = radeon_ib_pool_init(rdev); | ||
| 554 | rdev->accel_working = true; | 550 | rdev->accel_working = true; |
| 555 | if (r) { | ||
| 556 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 557 | rdev->accel_working = false; | ||
| 558 | } | ||
| 559 | |||
| 560 | r = rs400_startup(rdev); | 551 | r = rs400_startup(rdev); |
| 561 | if (r) { | 552 | if (r) { |
| 562 | /* Somethings want wront with the accel init stop accel */ | 553 | /* Somethings want wront with the accel init stop accel */ |
| 563 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 554 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
| 564 | r100_cp_fini(rdev); | 555 | r100_cp_fini(rdev); |
| 565 | radeon_wb_fini(rdev); | 556 | radeon_wb_fini(rdev); |
| 566 | r100_ib_fini(rdev); | 557 | radeon_ib_pool_fini(rdev); |
| 567 | rs400_gart_fini(rdev); | 558 | rs400_gart_fini(rdev); |
| 568 | radeon_irq_kms_fini(rdev); | 559 | radeon_irq_kms_fini(rdev); |
| 569 | rdev->accel_working = false; | 560 | rdev->accel_working = false; |
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index e95c5e61d4e2..5301b3df8466 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c | |||
| @@ -294,6 +294,7 @@ void rs600_hpd_init(struct radeon_device *rdev) | |||
| 294 | { | 294 | { |
| 295 | struct drm_device *dev = rdev->ddev; | 295 | struct drm_device *dev = rdev->ddev; |
| 296 | struct drm_connector *connector; | 296 | struct drm_connector *connector; |
| 297 | unsigned enable = 0; | ||
| 297 | 298 | ||
| 298 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 299 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 299 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 300 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| @@ -301,26 +302,25 @@ void rs600_hpd_init(struct radeon_device *rdev) | |||
| 301 | case RADEON_HPD_1: | 302 | case RADEON_HPD_1: |
| 302 | WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, | 303 | WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, |
| 303 | S_007D00_DC_HOT_PLUG_DETECT1_EN(1)); | 304 | S_007D00_DC_HOT_PLUG_DETECT1_EN(1)); |
| 304 | rdev->irq.hpd[0] = true; | ||
| 305 | break; | 305 | break; |
| 306 | case RADEON_HPD_2: | 306 | case RADEON_HPD_2: |
| 307 | WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, | 307 | WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, |
| 308 | S_007D10_DC_HOT_PLUG_DETECT2_EN(1)); | 308 | S_007D10_DC_HOT_PLUG_DETECT2_EN(1)); |
| 309 | rdev->irq.hpd[1] = true; | ||
| 310 | break; | 309 | break; |
| 311 | default: | 310 | default: |
| 312 | break; | 311 | break; |
| 313 | } | 312 | } |
| 313 | enable |= 1 << radeon_connector->hpd.hpd; | ||
| 314 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); | 314 | radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); |
| 315 | } | 315 | } |
| 316 | if (rdev->irq.installed) | 316 | radeon_irq_kms_enable_hpd(rdev, enable); |
| 317 | rs600_irq_set(rdev); | ||
| 318 | } | 317 | } |
| 319 | 318 | ||
| 320 | void rs600_hpd_fini(struct radeon_device *rdev) | 319 | void rs600_hpd_fini(struct radeon_device *rdev) |
| 321 | { | 320 | { |
| 322 | struct drm_device *dev = rdev->ddev; | 321 | struct drm_device *dev = rdev->ddev; |
| 323 | struct drm_connector *connector; | 322 | struct drm_connector *connector; |
| 323 | unsigned disable = 0; | ||
| 324 | 324 | ||
| 325 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 325 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 326 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 326 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| @@ -328,17 +328,17 @@ void rs600_hpd_fini(struct radeon_device *rdev) | |||
| 328 | case RADEON_HPD_1: | 328 | case RADEON_HPD_1: |
| 329 | WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, | 329 | WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, |
| 330 | S_007D00_DC_HOT_PLUG_DETECT1_EN(0)); | 330 | S_007D00_DC_HOT_PLUG_DETECT1_EN(0)); |
| 331 | rdev->irq.hpd[0] = false; | ||
| 332 | break; | 331 | break; |
| 333 | case RADEON_HPD_2: | 332 | case RADEON_HPD_2: |
| 334 | WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, | 333 | WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, |
| 335 | S_007D10_DC_HOT_PLUG_DETECT2_EN(0)); | 334 | S_007D10_DC_HOT_PLUG_DETECT2_EN(0)); |
| 336 | rdev->irq.hpd[1] = false; | ||
| 337 | break; | 335 | break; |
| 338 | default: | 336 | default: |
| 339 | break; | 337 | break; |
| 340 | } | 338 | } |
| 339 | disable |= 1 << radeon_connector->hpd.hpd; | ||
| 341 | } | 340 | } |
| 341 | radeon_irq_kms_disable_hpd(rdev, disable); | ||
| 342 | } | 342 | } |
| 343 | 343 | ||
| 344 | int rs600_asic_reset(struct radeon_device *rdev) | 344 | int rs600_asic_reset(struct radeon_device *rdev) |
| @@ -564,18 +564,18 @@ int rs600_irq_set(struct radeon_device *rdev) | |||
| 564 | WREG32(R_000040_GEN_INT_CNTL, 0); | 564 | WREG32(R_000040_GEN_INT_CNTL, 0); |
| 565 | return -EINVAL; | 565 | return -EINVAL; |
| 566 | } | 566 | } |
| 567 | if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { | 567 | if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { |
| 568 | tmp |= S_000040_SW_INT_EN(1); | 568 | tmp |= S_000040_SW_INT_EN(1); |
| 569 | } | 569 | } |
| 570 | if (rdev->irq.gui_idle) { | 570 | if (rdev->irq.gui_idle) { |
| 571 | tmp |= S_000040_GUI_IDLE(1); | 571 | tmp |= S_000040_GUI_IDLE(1); |
| 572 | } | 572 | } |
| 573 | if (rdev->irq.crtc_vblank_int[0] || | 573 | if (rdev->irq.crtc_vblank_int[0] || |
| 574 | rdev->irq.pflip[0]) { | 574 | atomic_read(&rdev->irq.pflip[0])) { |
| 575 | mode_int |= S_006540_D1MODE_VBLANK_INT_MASK(1); | 575 | mode_int |= S_006540_D1MODE_VBLANK_INT_MASK(1); |
| 576 | } | 576 | } |
| 577 | if (rdev->irq.crtc_vblank_int[1] || | 577 | if (rdev->irq.crtc_vblank_int[1] || |
| 578 | rdev->irq.pflip[1]) { | 578 | atomic_read(&rdev->irq.pflip[1])) { |
| 579 | mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1); | 579 | mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1); |
| 580 | } | 580 | } |
| 581 | if (rdev->irq.hpd[0]) { | 581 | if (rdev->irq.hpd[0]) { |
| @@ -686,7 +686,6 @@ int rs600_irq_process(struct radeon_device *rdev) | |||
| 686 | /* GUI idle */ | 686 | /* GUI idle */ |
| 687 | if (G_000040_GUI_IDLE(status)) { | 687 | if (G_000040_GUI_IDLE(status)) { |
| 688 | rdev->irq.gui_idle_acked = true; | 688 | rdev->irq.gui_idle_acked = true; |
| 689 | rdev->pm.gui_idle = true; | ||
| 690 | wake_up(&rdev->irq.idle_queue); | 689 | wake_up(&rdev->irq.idle_queue); |
| 691 | } | 690 | } |
| 692 | /* Vertical blank interrupts */ | 691 | /* Vertical blank interrupts */ |
| @@ -696,7 +695,7 @@ int rs600_irq_process(struct radeon_device *rdev) | |||
| 696 | rdev->pm.vblank_sync = true; | 695 | rdev->pm.vblank_sync = true; |
| 697 | wake_up(&rdev->irq.vblank_queue); | 696 | wake_up(&rdev->irq.vblank_queue); |
| 698 | } | 697 | } |
| 699 | if (rdev->irq.pflip[0]) | 698 | if (atomic_read(&rdev->irq.pflip[0])) |
| 700 | radeon_crtc_handle_flip(rdev, 0); | 699 | radeon_crtc_handle_flip(rdev, 0); |
| 701 | } | 700 | } |
| 702 | if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { | 701 | if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { |
| @@ -705,7 +704,7 @@ int rs600_irq_process(struct radeon_device *rdev) | |||
| 705 | rdev->pm.vblank_sync = true; | 704 | rdev->pm.vblank_sync = true; |
| 706 | wake_up(&rdev->irq.vblank_queue); | 705 | wake_up(&rdev->irq.vblank_queue); |
| 707 | } | 706 | } |
| 708 | if (rdev->irq.pflip[1]) | 707 | if (atomic_read(&rdev->irq.pflip[1])) |
| 709 | radeon_crtc_handle_flip(rdev, 1); | 708 | radeon_crtc_handle_flip(rdev, 1); |
| 710 | } | 709 | } |
| 711 | if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { | 710 | if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { |
| @@ -908,13 +907,11 @@ static int rs600_startup(struct radeon_device *rdev) | |||
| 908 | return r; | 907 | return r; |
| 909 | } | 908 | } |
| 910 | 909 | ||
| 911 | r = radeon_ib_pool_start(rdev); | 910 | r = radeon_ib_pool_init(rdev); |
| 912 | if (r) | 911 | if (r) { |
| 913 | return r; | 912 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 914 | |||
| 915 | r = radeon_ib_ring_tests(rdev); | ||
| 916 | if (r) | ||
| 917 | return r; | 913 | return r; |
| 914 | } | ||
| 918 | 915 | ||
| 919 | r = r600_audio_init(rdev); | 916 | r = r600_audio_init(rdev); |
| 920 | if (r) { | 917 | if (r) { |
| @@ -956,7 +953,6 @@ int rs600_resume(struct radeon_device *rdev) | |||
| 956 | 953 | ||
| 957 | int rs600_suspend(struct radeon_device *rdev) | 954 | int rs600_suspend(struct radeon_device *rdev) |
| 958 | { | 955 | { |
| 959 | radeon_ib_pool_suspend(rdev); | ||
| 960 | r600_audio_fini(rdev); | 956 | r600_audio_fini(rdev); |
| 961 | r100_cp_disable(rdev); | 957 | r100_cp_disable(rdev); |
| 962 | radeon_wb_disable(rdev); | 958 | radeon_wb_disable(rdev); |
| @@ -970,7 +966,7 @@ void rs600_fini(struct radeon_device *rdev) | |||
| 970 | r600_audio_fini(rdev); | 966 | r600_audio_fini(rdev); |
| 971 | r100_cp_fini(rdev); | 967 | r100_cp_fini(rdev); |
| 972 | radeon_wb_fini(rdev); | 968 | radeon_wb_fini(rdev); |
| 973 | r100_ib_fini(rdev); | 969 | radeon_ib_pool_fini(rdev); |
| 974 | radeon_gem_fini(rdev); | 970 | radeon_gem_fini(rdev); |
| 975 | rs600_gart_fini(rdev); | 971 | rs600_gart_fini(rdev); |
| 976 | radeon_irq_kms_fini(rdev); | 972 | radeon_irq_kms_fini(rdev); |
| @@ -1038,20 +1034,14 @@ int rs600_init(struct radeon_device *rdev) | |||
| 1038 | return r; | 1034 | return r; |
| 1039 | rs600_set_safe_registers(rdev); | 1035 | rs600_set_safe_registers(rdev); |
| 1040 | 1036 | ||
| 1041 | r = radeon_ib_pool_init(rdev); | ||
| 1042 | rdev->accel_working = true; | 1037 | rdev->accel_working = true; |
| 1043 | if (r) { | ||
| 1044 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 1045 | rdev->accel_working = false; | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | r = rs600_startup(rdev); | 1038 | r = rs600_startup(rdev); |
| 1049 | if (r) { | 1039 | if (r) { |
| 1050 | /* Somethings want wront with the accel init stop accel */ | 1040 | /* Somethings want wront with the accel init stop accel */ |
| 1051 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 1041 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
| 1052 | r100_cp_fini(rdev); | 1042 | r100_cp_fini(rdev); |
| 1053 | radeon_wb_fini(rdev); | 1043 | radeon_wb_fini(rdev); |
| 1054 | r100_ib_fini(rdev); | 1044 | radeon_ib_pool_fini(rdev); |
| 1055 | rs600_gart_fini(rdev); | 1045 | rs600_gart_fini(rdev); |
| 1056 | radeon_irq_kms_fini(rdev); | 1046 | radeon_irq_kms_fini(rdev); |
| 1057 | rdev->accel_working = false; | 1047 | rdev->accel_working = false; |
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 159b6a43fda0..3b663fcfe061 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c | |||
| @@ -637,13 +637,11 @@ static int rs690_startup(struct radeon_device *rdev) | |||
| 637 | return r; | 637 | return r; |
| 638 | } | 638 | } |
| 639 | 639 | ||
| 640 | r = radeon_ib_pool_start(rdev); | 640 | r = radeon_ib_pool_init(rdev); |
| 641 | if (r) | 641 | if (r) { |
| 642 | return r; | 642 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 643 | |||
| 644 | r = radeon_ib_ring_tests(rdev); | ||
| 645 | if (r) | ||
| 646 | return r; | 643 | return r; |
| 644 | } | ||
| 647 | 645 | ||
| 648 | r = r600_audio_init(rdev); | 646 | r = r600_audio_init(rdev); |
| 649 | if (r) { | 647 | if (r) { |
| @@ -685,7 +683,6 @@ int rs690_resume(struct radeon_device *rdev) | |||
| 685 | 683 | ||
| 686 | int rs690_suspend(struct radeon_device *rdev) | 684 | int rs690_suspend(struct radeon_device *rdev) |
| 687 | { | 685 | { |
| 688 | radeon_ib_pool_suspend(rdev); | ||
| 689 | r600_audio_fini(rdev); | 686 | r600_audio_fini(rdev); |
| 690 | r100_cp_disable(rdev); | 687 | r100_cp_disable(rdev); |
| 691 | radeon_wb_disable(rdev); | 688 | radeon_wb_disable(rdev); |
| @@ -699,7 +696,7 @@ void rs690_fini(struct radeon_device *rdev) | |||
| 699 | r600_audio_fini(rdev); | 696 | r600_audio_fini(rdev); |
| 700 | r100_cp_fini(rdev); | 697 | r100_cp_fini(rdev); |
| 701 | radeon_wb_fini(rdev); | 698 | radeon_wb_fini(rdev); |
| 702 | r100_ib_fini(rdev); | 699 | radeon_ib_pool_fini(rdev); |
| 703 | radeon_gem_fini(rdev); | 700 | radeon_gem_fini(rdev); |
| 704 | rs400_gart_fini(rdev); | 701 | rs400_gart_fini(rdev); |
| 705 | radeon_irq_kms_fini(rdev); | 702 | radeon_irq_kms_fini(rdev); |
| @@ -768,20 +765,14 @@ int rs690_init(struct radeon_device *rdev) | |||
| 768 | return r; | 765 | return r; |
| 769 | rs600_set_safe_registers(rdev); | 766 | rs600_set_safe_registers(rdev); |
| 770 | 767 | ||
| 771 | r = radeon_ib_pool_init(rdev); | ||
| 772 | rdev->accel_working = true; | 768 | rdev->accel_working = true; |
| 773 | if (r) { | ||
| 774 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 775 | rdev->accel_working = false; | ||
| 776 | } | ||
| 777 | |||
| 778 | r = rs690_startup(rdev); | 769 | r = rs690_startup(rdev); |
| 779 | if (r) { | 770 | if (r) { |
| 780 | /* Somethings want wront with the accel init stop accel */ | 771 | /* Somethings want wront with the accel init stop accel */ |
| 781 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 772 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
| 782 | r100_cp_fini(rdev); | 773 | r100_cp_fini(rdev); |
| 783 | radeon_wb_fini(rdev); | 774 | radeon_wb_fini(rdev); |
| 784 | r100_ib_fini(rdev); | 775 | radeon_ib_pool_fini(rdev); |
| 785 | rs400_gart_fini(rdev); | 776 | rs400_gart_fini(rdev); |
| 786 | radeon_irq_kms_fini(rdev); | 777 | radeon_irq_kms_fini(rdev); |
| 787 | rdev->accel_working = false; | 778 | rdev->accel_working = false; |
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 7f08cedb5333..a12fbcc8ccb6 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c | |||
| @@ -408,13 +408,11 @@ static int rv515_startup(struct radeon_device *rdev) | |||
| 408 | return r; | 408 | return r; |
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | r = radeon_ib_pool_start(rdev); | 411 | r = radeon_ib_pool_init(rdev); |
| 412 | if (r) | 412 | if (r) { |
| 413 | return r; | 413 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 414 | |||
| 415 | r = radeon_ib_ring_tests(rdev); | ||
| 416 | if (r) | ||
| 417 | return r; | 414 | return r; |
| 415 | } | ||
| 418 | 416 | ||
| 419 | return 0; | 417 | return 0; |
| 420 | } | 418 | } |
| @@ -469,7 +467,7 @@ void rv515_fini(struct radeon_device *rdev) | |||
| 469 | { | 467 | { |
| 470 | r100_cp_fini(rdev); | 468 | r100_cp_fini(rdev); |
| 471 | radeon_wb_fini(rdev); | 469 | radeon_wb_fini(rdev); |
| 472 | r100_ib_fini(rdev); | 470 | radeon_ib_pool_fini(rdev); |
| 473 | radeon_gem_fini(rdev); | 471 | radeon_gem_fini(rdev); |
| 474 | rv370_pcie_gart_fini(rdev); | 472 | rv370_pcie_gart_fini(rdev); |
| 475 | radeon_agp_fini(rdev); | 473 | radeon_agp_fini(rdev); |
| @@ -543,20 +541,14 @@ int rv515_init(struct radeon_device *rdev) | |||
| 543 | return r; | 541 | return r; |
| 544 | rv515_set_safe_registers(rdev); | 542 | rv515_set_safe_registers(rdev); |
| 545 | 543 | ||
| 546 | r = radeon_ib_pool_init(rdev); | ||
| 547 | rdev->accel_working = true; | 544 | rdev->accel_working = true; |
| 548 | if (r) { | ||
| 549 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 550 | rdev->accel_working = false; | ||
| 551 | } | ||
| 552 | |||
| 553 | r = rv515_startup(rdev); | 545 | r = rv515_startup(rdev); |
| 554 | if (r) { | 546 | if (r) { |
| 555 | /* Somethings want wront with the accel init stop accel */ | 547 | /* Somethings want wront with the accel init stop accel */ |
| 556 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); | 548 | dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
| 557 | r100_cp_fini(rdev); | 549 | r100_cp_fini(rdev); |
| 558 | radeon_wb_fini(rdev); | 550 | radeon_wb_fini(rdev); |
| 559 | r100_ib_fini(rdev); | 551 | radeon_ib_pool_fini(rdev); |
| 560 | radeon_irq_kms_fini(rdev); | 552 | radeon_irq_kms_fini(rdev); |
| 561 | rv370_pcie_gart_fini(rdev); | 553 | rv370_pcie_gart_fini(rdev); |
| 562 | radeon_agp_fini(rdev); | 554 | radeon_agp_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index b4f51c569c36..ca8ffec10ff6 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
| @@ -358,8 +358,10 @@ static int rv770_cp_load_microcode(struct radeon_device *rdev) | |||
| 358 | 358 | ||
| 359 | void r700_cp_fini(struct radeon_device *rdev) | 359 | void r700_cp_fini(struct radeon_device *rdev) |
| 360 | { | 360 | { |
| 361 | struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; | ||
| 361 | r700_cp_stop(rdev); | 362 | r700_cp_stop(rdev); |
| 362 | radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); | 363 | radeon_ring_fini(rdev, ring); |
| 364 | radeon_scratch_free(rdev, ring->rptr_save_reg); | ||
| 363 | } | 365 | } |
| 364 | 366 | ||
| 365 | /* | 367 | /* |
| @@ -951,13 +953,11 @@ static int rv770_startup(struct radeon_device *rdev) | |||
| 951 | if (r) | 953 | if (r) |
| 952 | return r; | 954 | return r; |
| 953 | 955 | ||
| 954 | r = radeon_ib_pool_start(rdev); | 956 | r = radeon_ib_pool_init(rdev); |
| 955 | if (r) | 957 | if (r) { |
| 956 | return r; | 958 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 957 | |||
| 958 | r = radeon_ib_ring_tests(rdev); | ||
| 959 | if (r) | ||
| 960 | return r; | 959 | return r; |
| 960 | } | ||
| 961 | 961 | ||
| 962 | r = r600_audio_init(rdev); | 962 | r = r600_audio_init(rdev); |
| 963 | if (r) { | 963 | if (r) { |
| @@ -994,9 +994,6 @@ int rv770_resume(struct radeon_device *rdev) | |||
| 994 | int rv770_suspend(struct radeon_device *rdev) | 994 | int rv770_suspend(struct radeon_device *rdev) |
| 995 | { | 995 | { |
| 996 | r600_audio_fini(rdev); | 996 | r600_audio_fini(rdev); |
| 997 | radeon_ib_pool_suspend(rdev); | ||
| 998 | r600_blit_suspend(rdev); | ||
| 999 | /* FIXME: we should wait for ring to be empty */ | ||
| 1000 | r700_cp_stop(rdev); | 997 | r700_cp_stop(rdev); |
| 1001 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; | 998 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; |
| 1002 | r600_irq_suspend(rdev); | 999 | r600_irq_suspend(rdev); |
| @@ -1076,20 +1073,14 @@ int rv770_init(struct radeon_device *rdev) | |||
| 1076 | if (r) | 1073 | if (r) |
| 1077 | return r; | 1074 | return r; |
| 1078 | 1075 | ||
| 1079 | r = radeon_ib_pool_init(rdev); | ||
| 1080 | rdev->accel_working = true; | 1076 | rdev->accel_working = true; |
| 1081 | if (r) { | ||
| 1082 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 1083 | rdev->accel_working = false; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | r = rv770_startup(rdev); | 1077 | r = rv770_startup(rdev); |
| 1087 | if (r) { | 1078 | if (r) { |
| 1088 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | 1079 | dev_err(rdev->dev, "disabling GPU acceleration\n"); |
| 1089 | r700_cp_fini(rdev); | 1080 | r700_cp_fini(rdev); |
| 1090 | r600_irq_fini(rdev); | 1081 | r600_irq_fini(rdev); |
| 1091 | radeon_wb_fini(rdev); | 1082 | radeon_wb_fini(rdev); |
| 1092 | r100_ib_fini(rdev); | 1083 | radeon_ib_pool_fini(rdev); |
| 1093 | radeon_irq_kms_fini(rdev); | 1084 | radeon_irq_kms_fini(rdev); |
| 1094 | rv770_pcie_gart_fini(rdev); | 1085 | rv770_pcie_gart_fini(rdev); |
| 1095 | rdev->accel_working = false; | 1086 | rdev->accel_working = false; |
| @@ -1104,7 +1095,7 @@ void rv770_fini(struct radeon_device *rdev) | |||
| 1104 | r700_cp_fini(rdev); | 1095 | r700_cp_fini(rdev); |
| 1105 | r600_irq_fini(rdev); | 1096 | r600_irq_fini(rdev); |
| 1106 | radeon_wb_fini(rdev); | 1097 | radeon_wb_fini(rdev); |
| 1107 | r100_ib_fini(rdev); | 1098 | radeon_ib_pool_fini(rdev); |
| 1108 | radeon_irq_kms_fini(rdev); | 1099 | radeon_irq_kms_fini(rdev); |
| 1109 | rv770_pcie_gart_fini(rdev); | 1100 | rv770_pcie_gart_fini(rdev); |
| 1110 | r600_vram_scratch_fini(rdev); | 1101 | r600_vram_scratch_fini(rdev); |
| @@ -1121,6 +1112,8 @@ static void rv770_pcie_gen2_enable(struct radeon_device *rdev) | |||
| 1121 | { | 1112 | { |
| 1122 | u32 link_width_cntl, lanes, speed_cntl, tmp; | 1113 | u32 link_width_cntl, lanes, speed_cntl, tmp; |
| 1123 | u16 link_cntl2; | 1114 | u16 link_cntl2; |
| 1115 | u32 mask; | ||
| 1116 | int ret; | ||
| 1124 | 1117 | ||
| 1125 | if (radeon_pcie_gen2 == 0) | 1118 | if (radeon_pcie_gen2 == 0) |
| 1126 | return; | 1119 | return; |
| @@ -1135,6 +1128,15 @@ static void rv770_pcie_gen2_enable(struct radeon_device *rdev) | |||
| 1135 | if (ASIC_IS_X2(rdev)) | 1128 | if (ASIC_IS_X2(rdev)) |
| 1136 | return; | 1129 | return; |
| 1137 | 1130 | ||
| 1131 | ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); | ||
| 1132 | if (ret != 0) | ||
| 1133 | return; | ||
| 1134 | |||
| 1135 | if (!(mask & DRM_PCIE_SPEED_50)) | ||
| 1136 | return; | ||
| 1137 | |||
| 1138 | DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); | ||
| 1139 | |||
| 1138 | /* advertise upconfig capability */ | 1140 | /* advertise upconfig capability */ |
| 1139 | link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); | 1141 | link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); |
| 1140 | link_width_cntl &= ~LC_UPCONFIGURE_DIS; | 1142 | link_width_cntl &= ~LC_UPCONFIGURE_DIS; |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 0b0279291a73..c053f8193771 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
| @@ -1762,13 +1762,34 @@ void si_fence_ring_emit(struct radeon_device *rdev, | |||
| 1762 | */ | 1762 | */ |
| 1763 | void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) | 1763 | void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) |
| 1764 | { | 1764 | { |
| 1765 | struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; | 1765 | struct radeon_ring *ring = &rdev->ring[ib->ring]; |
| 1766 | u32 header; | 1766 | u32 header; |
| 1767 | 1767 | ||
| 1768 | if (ib->is_const_ib) | 1768 | if (ib->is_const_ib) { |
| 1769 | /* set switch buffer packet before const IB */ | ||
| 1770 | radeon_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); | ||
| 1771 | radeon_ring_write(ring, 0); | ||
| 1772 | |||
| 1769 | header = PACKET3(PACKET3_INDIRECT_BUFFER_CONST, 2); | 1773 | header = PACKET3(PACKET3_INDIRECT_BUFFER_CONST, 2); |
| 1770 | else | 1774 | } else { |
| 1775 | u32 next_rptr; | ||
| 1776 | if (ring->rptr_save_reg) { | ||
| 1777 | next_rptr = ring->wptr + 3 + 4 + 8; | ||
| 1778 | radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | ||
| 1779 | radeon_ring_write(ring, ((ring->rptr_save_reg - | ||
| 1780 | PACKET3_SET_CONFIG_REG_START) >> 2)); | ||
| 1781 | radeon_ring_write(ring, next_rptr); | ||
| 1782 | } else if (rdev->wb.enabled) { | ||
| 1783 | next_rptr = ring->wptr + 5 + 4 + 8; | ||
| 1784 | radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); | ||
| 1785 | radeon_ring_write(ring, (1 << 8)); | ||
| 1786 | radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); | ||
| 1787 | radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff); | ||
| 1788 | radeon_ring_write(ring, next_rptr); | ||
| 1789 | } | ||
| 1790 | |||
| 1771 | header = PACKET3(PACKET3_INDIRECT_BUFFER, 2); | 1791 | header = PACKET3(PACKET3_INDIRECT_BUFFER, 2); |
| 1792 | } | ||
| 1772 | 1793 | ||
| 1773 | radeon_ring_write(ring, header); | 1794 | radeon_ring_write(ring, header); |
| 1774 | radeon_ring_write(ring, | 1795 | radeon_ring_write(ring, |
| @@ -1779,18 +1800,20 @@ void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) | |||
| 1779 | radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF); | 1800 | radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF); |
| 1780 | radeon_ring_write(ring, ib->length_dw | (ib->vm_id << 24)); | 1801 | radeon_ring_write(ring, ib->length_dw | (ib->vm_id << 24)); |
| 1781 | 1802 | ||
| 1782 | /* flush read cache over gart for this vmid */ | 1803 | if (!ib->is_const_ib) { |
| 1783 | radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | 1804 | /* flush read cache over gart for this vmid */ |
| 1784 | radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); | 1805 | radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); |
| 1785 | radeon_ring_write(ring, ib->vm_id); | 1806 | radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); |
| 1786 | radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); | 1807 | radeon_ring_write(ring, ib->vm_id); |
| 1787 | radeon_ring_write(ring, PACKET3_TCL1_ACTION_ENA | | 1808 | radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); |
| 1788 | PACKET3_TC_ACTION_ENA | | 1809 | radeon_ring_write(ring, PACKET3_TCL1_ACTION_ENA | |
| 1789 | PACKET3_SH_KCACHE_ACTION_ENA | | 1810 | PACKET3_TC_ACTION_ENA | |
| 1790 | PACKET3_SH_ICACHE_ACTION_ENA); | 1811 | PACKET3_SH_KCACHE_ACTION_ENA | |
| 1791 | radeon_ring_write(ring, 0xFFFFFFFF); | 1812 | PACKET3_SH_ICACHE_ACTION_ENA); |
| 1792 | radeon_ring_write(ring, 0); | 1813 | radeon_ring_write(ring, 0xFFFFFFFF); |
| 1793 | radeon_ring_write(ring, 10); /* poll interval */ | 1814 | radeon_ring_write(ring, 0); |
| 1815 | radeon_ring_write(ring, 10); /* poll interval */ | ||
| 1816 | } | ||
| 1794 | } | 1817 | } |
| 1795 | 1818 | ||
| 1796 | /* | 1819 | /* |
| @@ -1917,10 +1940,20 @@ static int si_cp_start(struct radeon_device *rdev) | |||
| 1917 | 1940 | ||
| 1918 | static void si_cp_fini(struct radeon_device *rdev) | 1941 | static void si_cp_fini(struct radeon_device *rdev) |
| 1919 | { | 1942 | { |
| 1943 | struct radeon_ring *ring; | ||
| 1920 | si_cp_enable(rdev, false); | 1944 | si_cp_enable(rdev, false); |
| 1921 | radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); | 1945 | |
| 1922 | radeon_ring_fini(rdev, &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]); | 1946 | ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; |
| 1923 | radeon_ring_fini(rdev, &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]); | 1947 | radeon_ring_fini(rdev, ring); |
| 1948 | radeon_scratch_free(rdev, ring->rptr_save_reg); | ||
| 1949 | |||
| 1950 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; | ||
| 1951 | radeon_ring_fini(rdev, ring); | ||
| 1952 | radeon_scratch_free(rdev, ring->rptr_save_reg); | ||
| 1953 | |||
| 1954 | ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; | ||
| 1955 | radeon_ring_fini(rdev, ring); | ||
| 1956 | radeon_scratch_free(rdev, ring->rptr_save_reg); | ||
| 1924 | } | 1957 | } |
| 1925 | 1958 | ||
| 1926 | static int si_cp_resume(struct radeon_device *rdev) | 1959 | static int si_cp_resume(struct radeon_device *rdev) |
| @@ -2702,7 +2735,7 @@ int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) | |||
| 2702 | if (ib->is_const_ib) | 2735 | if (ib->is_const_ib) |
| 2703 | ret = si_vm_packet3_ce_check(rdev, ib->ptr, &pkt); | 2736 | ret = si_vm_packet3_ce_check(rdev, ib->ptr, &pkt); |
| 2704 | else { | 2737 | else { |
| 2705 | switch (ib->fence->ring) { | 2738 | switch (ib->ring) { |
| 2706 | case RADEON_RING_TYPE_GFX_INDEX: | 2739 | case RADEON_RING_TYPE_GFX_INDEX: |
| 2707 | ret = si_vm_packet3_gfx_check(rdev, ib->ptr, &pkt); | 2740 | ret = si_vm_packet3_gfx_check(rdev, ib->ptr, &pkt); |
| 2708 | break; | 2741 | break; |
| @@ -2711,7 +2744,7 @@ int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) | |||
| 2711 | ret = si_vm_packet3_compute_check(rdev, ib->ptr, &pkt); | 2744 | ret = si_vm_packet3_compute_check(rdev, ib->ptr, &pkt); |
| 2712 | break; | 2745 | break; |
| 2713 | default: | 2746 | default: |
| 2714 | dev_err(rdev->dev, "Non-PM4 ring %d !\n", ib->fence->ring); | 2747 | dev_err(rdev->dev, "Non-PM4 ring %d !\n", ib->ring); |
| 2715 | ret = -EINVAL; | 2748 | ret = -EINVAL; |
| 2716 | break; | 2749 | break; |
| 2717 | } | 2750 | } |
| @@ -2942,7 +2975,6 @@ static void si_disable_interrupts(struct radeon_device *rdev) | |||
| 2942 | WREG32(IH_RB_RPTR, 0); | 2975 | WREG32(IH_RB_RPTR, 0); |
| 2943 | WREG32(IH_RB_WPTR, 0); | 2976 | WREG32(IH_RB_WPTR, 0); |
| 2944 | rdev->ih.enabled = false; | 2977 | rdev->ih.enabled = false; |
| 2945 | rdev->ih.wptr = 0; | ||
| 2946 | rdev->ih.rptr = 0; | 2978 | rdev->ih.rptr = 0; |
| 2947 | } | 2979 | } |
| 2948 | 2980 | ||
| @@ -3093,45 +3125,45 @@ int si_irq_set(struct radeon_device *rdev) | |||
| 3093 | hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; | 3125 | hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; |
| 3094 | 3126 | ||
| 3095 | /* enable CP interrupts on all rings */ | 3127 | /* enable CP interrupts on all rings */ |
| 3096 | if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { | 3128 | if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { |
| 3097 | DRM_DEBUG("si_irq_set: sw int gfx\n"); | 3129 | DRM_DEBUG("si_irq_set: sw int gfx\n"); |
| 3098 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; | 3130 | cp_int_cntl |= TIME_STAMP_INT_ENABLE; |
| 3099 | } | 3131 | } |
| 3100 | if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP1_INDEX]) { | 3132 | if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP1_INDEX])) { |
| 3101 | DRM_DEBUG("si_irq_set: sw int cp1\n"); | 3133 | DRM_DEBUG("si_irq_set: sw int cp1\n"); |
| 3102 | cp_int_cntl1 |= TIME_STAMP_INT_ENABLE; | 3134 | cp_int_cntl1 |= TIME_STAMP_INT_ENABLE; |
| 3103 | } | 3135 | } |
| 3104 | if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP2_INDEX]) { | 3136 | if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP2_INDEX])) { |
| 3105 | DRM_DEBUG("si_irq_set: sw int cp2\n"); | 3137 | DRM_DEBUG("si_irq_set: sw int cp2\n"); |
| 3106 | cp_int_cntl2 |= TIME_STAMP_INT_ENABLE; | 3138 | cp_int_cntl2 |= TIME_STAMP_INT_ENABLE; |
| 3107 | } | 3139 | } |
| 3108 | if (rdev->irq.crtc_vblank_int[0] || | 3140 | if (rdev->irq.crtc_vblank_int[0] || |
| 3109 | rdev->irq.pflip[0]) { | 3141 | atomic_read(&rdev->irq.pflip[0])) { |
| 3110 | DRM_DEBUG("si_irq_set: vblank 0\n"); | 3142 | DRM_DEBUG("si_irq_set: vblank 0\n"); |
| 3111 | crtc1 |= VBLANK_INT_MASK; | 3143 | crtc1 |= VBLANK_INT_MASK; |
| 3112 | } | 3144 | } |
| 3113 | if (rdev->irq.crtc_vblank_int[1] || | 3145 | if (rdev->irq.crtc_vblank_int[1] || |
| 3114 | rdev->irq.pflip[1]) { | 3146 | atomic_read(&rdev->irq.pflip[1])) { |
| 3115 | DRM_DEBUG("si_irq_set: vblank 1\n"); | 3147 | DRM_DEBUG("si_irq_set: vblank 1\n"); |
| 3116 | crtc2 |= VBLANK_INT_MASK; | 3148 | crtc2 |= VBLANK_INT_MASK; |
| 3117 | } | 3149 | } |
| 3118 | if (rdev->irq.crtc_vblank_int[2] || | 3150 | if (rdev->irq.crtc_vblank_int[2] || |
| 3119 | rdev->irq.pflip[2]) { | 3151 | atomic_read(&rdev->irq.pflip[2])) { |
| 3120 | DRM_DEBUG("si_irq_set: vblank 2\n"); | 3152 | DRM_DEBUG("si_irq_set: vblank 2\n"); |
| 3121 | crtc3 |= VBLANK_INT_MASK; | 3153 | crtc3 |= VBLANK_INT_MASK; |
| 3122 | } | 3154 | } |
| 3123 | if (rdev->irq.crtc_vblank_int[3] || | 3155 | if (rdev->irq.crtc_vblank_int[3] || |
| 3124 | rdev->irq.pflip[3]) { | 3156 | atomic_read(&rdev->irq.pflip[3])) { |
| 3125 | DRM_DEBUG("si_irq_set: vblank 3\n"); | 3157 | DRM_DEBUG("si_irq_set: vblank 3\n"); |
| 3126 | crtc4 |= VBLANK_INT_MASK; | 3158 | crtc4 |= VBLANK_INT_MASK; |
| 3127 | } | 3159 | } |
| 3128 | if (rdev->irq.crtc_vblank_int[4] || | 3160 | if (rdev->irq.crtc_vblank_int[4] || |
| 3129 | rdev->irq.pflip[4]) { | 3161 | atomic_read(&rdev->irq.pflip[4])) { |
| 3130 | DRM_DEBUG("si_irq_set: vblank 4\n"); | 3162 | DRM_DEBUG("si_irq_set: vblank 4\n"); |
| 3131 | crtc5 |= VBLANK_INT_MASK; | 3163 | crtc5 |= VBLANK_INT_MASK; |
| 3132 | } | 3164 | } |
| 3133 | if (rdev->irq.crtc_vblank_int[5] || | 3165 | if (rdev->irq.crtc_vblank_int[5] || |
| 3134 | rdev->irq.pflip[5]) { | 3166 | atomic_read(&rdev->irq.pflip[5])) { |
| 3135 | DRM_DEBUG("si_irq_set: vblank 5\n"); | 3167 | DRM_DEBUG("si_irq_set: vblank 5\n"); |
| 3136 | crtc6 |= VBLANK_INT_MASK; | 3168 | crtc6 |= VBLANK_INT_MASK; |
| 3137 | } | 3169 | } |
| @@ -3359,29 +3391,27 @@ int si_irq_process(struct radeon_device *rdev) | |||
| 3359 | u32 rptr; | 3391 | u32 rptr; |
| 3360 | u32 src_id, src_data, ring_id; | 3392 | u32 src_id, src_data, ring_id; |
| 3361 | u32 ring_index; | 3393 | u32 ring_index; |
| 3362 | unsigned long flags; | ||
| 3363 | bool queue_hotplug = false; | 3394 | bool queue_hotplug = false; |
| 3364 | 3395 | ||
| 3365 | if (!rdev->ih.enabled || rdev->shutdown) | 3396 | if (!rdev->ih.enabled || rdev->shutdown) |
| 3366 | return IRQ_NONE; | 3397 | return IRQ_NONE; |
| 3367 | 3398 | ||
| 3368 | wptr = si_get_ih_wptr(rdev); | 3399 | wptr = si_get_ih_wptr(rdev); |
| 3400 | |||
| 3401 | restart_ih: | ||
| 3402 | /* is somebody else already processing irqs? */ | ||
| 3403 | if (atomic_xchg(&rdev->ih.lock, 1)) | ||
| 3404 | return IRQ_NONE; | ||
| 3405 | |||
| 3369 | rptr = rdev->ih.rptr; | 3406 | rptr = rdev->ih.rptr; |
| 3370 | DRM_DEBUG("si_irq_process start: rptr %d, wptr %d\n", rptr, wptr); | 3407 | DRM_DEBUG("si_irq_process start: rptr %d, wptr %d\n", rptr, wptr); |
| 3371 | 3408 | ||
| 3372 | spin_lock_irqsave(&rdev->ih.lock, flags); | ||
| 3373 | if (rptr == wptr) { | ||
| 3374 | spin_unlock_irqrestore(&rdev->ih.lock, flags); | ||
| 3375 | return IRQ_NONE; | ||
| 3376 | } | ||
| 3377 | restart_ih: | ||
| 3378 | /* Order reading of wptr vs. reading of IH ring data */ | 3409 | /* Order reading of wptr vs. reading of IH ring data */ |
| 3379 | rmb(); | 3410 | rmb(); |
| 3380 | 3411 | ||
| 3381 | /* display interrupts */ | 3412 | /* display interrupts */ |
| 3382 | si_irq_ack(rdev); | 3413 | si_irq_ack(rdev); |
| 3383 | 3414 | ||
| 3384 | rdev->ih.wptr = wptr; | ||
| 3385 | while (rptr != wptr) { | 3415 | while (rptr != wptr) { |
| 3386 | /* wptr/rptr are in bytes! */ | 3416 | /* wptr/rptr are in bytes! */ |
| 3387 | ring_index = rptr / 4; | 3417 | ring_index = rptr / 4; |
| @@ -3399,7 +3429,7 @@ restart_ih: | |||
| 3399 | rdev->pm.vblank_sync = true; | 3429 | rdev->pm.vblank_sync = true; |
| 3400 | wake_up(&rdev->irq.vblank_queue); | 3430 | wake_up(&rdev->irq.vblank_queue); |
| 3401 | } | 3431 | } |
| 3402 | if (rdev->irq.pflip[0]) | 3432 | if (atomic_read(&rdev->irq.pflip[0])) |
| 3403 | radeon_crtc_handle_flip(rdev, 0); | 3433 | radeon_crtc_handle_flip(rdev, 0); |
| 3404 | rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; | 3434 | rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; |
| 3405 | DRM_DEBUG("IH: D1 vblank\n"); | 3435 | DRM_DEBUG("IH: D1 vblank\n"); |
| @@ -3425,7 +3455,7 @@ restart_ih: | |||
| 3425 | rdev->pm.vblank_sync = true; | 3455 | rdev->pm.vblank_sync = true; |
| 3426 | wake_up(&rdev->irq.vblank_queue); | 3456 | wake_up(&rdev->irq.vblank_queue); |
| 3427 | } | 3457 | } |
| 3428 | if (rdev->irq.pflip[1]) | 3458 | if (atomic_read(&rdev->irq.pflip[1])) |
| 3429 | radeon_crtc_handle_flip(rdev, 1); | 3459 | radeon_crtc_handle_flip(rdev, 1); |
| 3430 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; | 3460 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; |
| 3431 | DRM_DEBUG("IH: D2 vblank\n"); | 3461 | DRM_DEBUG("IH: D2 vblank\n"); |
| @@ -3451,7 +3481,7 @@ restart_ih: | |||
| 3451 | rdev->pm.vblank_sync = true; | 3481 | rdev->pm.vblank_sync = true; |
| 3452 | wake_up(&rdev->irq.vblank_queue); | 3482 | wake_up(&rdev->irq.vblank_queue); |
| 3453 | } | 3483 | } |
| 3454 | if (rdev->irq.pflip[2]) | 3484 | if (atomic_read(&rdev->irq.pflip[2])) |
| 3455 | radeon_crtc_handle_flip(rdev, 2); | 3485 | radeon_crtc_handle_flip(rdev, 2); |
| 3456 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; | 3486 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; |
| 3457 | DRM_DEBUG("IH: D3 vblank\n"); | 3487 | DRM_DEBUG("IH: D3 vblank\n"); |
| @@ -3477,7 +3507,7 @@ restart_ih: | |||
| 3477 | rdev->pm.vblank_sync = true; | 3507 | rdev->pm.vblank_sync = true; |
| 3478 | wake_up(&rdev->irq.vblank_queue); | 3508 | wake_up(&rdev->irq.vblank_queue); |
| 3479 | } | 3509 | } |
| 3480 | if (rdev->irq.pflip[3]) | 3510 | if (atomic_read(&rdev->irq.pflip[3])) |
| 3481 | radeon_crtc_handle_flip(rdev, 3); | 3511 | radeon_crtc_handle_flip(rdev, 3); |
| 3482 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; | 3512 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; |
| 3483 | DRM_DEBUG("IH: D4 vblank\n"); | 3513 | DRM_DEBUG("IH: D4 vblank\n"); |
| @@ -3503,7 +3533,7 @@ restart_ih: | |||
| 3503 | rdev->pm.vblank_sync = true; | 3533 | rdev->pm.vblank_sync = true; |
| 3504 | wake_up(&rdev->irq.vblank_queue); | 3534 | wake_up(&rdev->irq.vblank_queue); |
| 3505 | } | 3535 | } |
| 3506 | if (rdev->irq.pflip[4]) | 3536 | if (atomic_read(&rdev->irq.pflip[4])) |
| 3507 | radeon_crtc_handle_flip(rdev, 4); | 3537 | radeon_crtc_handle_flip(rdev, 4); |
| 3508 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; | 3538 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; |
| 3509 | DRM_DEBUG("IH: D5 vblank\n"); | 3539 | DRM_DEBUG("IH: D5 vblank\n"); |
| @@ -3529,7 +3559,7 @@ restart_ih: | |||
| 3529 | rdev->pm.vblank_sync = true; | 3559 | rdev->pm.vblank_sync = true; |
| 3530 | wake_up(&rdev->irq.vblank_queue); | 3560 | wake_up(&rdev->irq.vblank_queue); |
| 3531 | } | 3561 | } |
| 3532 | if (rdev->irq.pflip[5]) | 3562 | if (atomic_read(&rdev->irq.pflip[5])) |
| 3533 | radeon_crtc_handle_flip(rdev, 5); | 3563 | radeon_crtc_handle_flip(rdev, 5); |
| 3534 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; | 3564 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; |
| 3535 | DRM_DEBUG("IH: D6 vblank\n"); | 3565 | DRM_DEBUG("IH: D6 vblank\n"); |
| @@ -3620,7 +3650,6 @@ restart_ih: | |||
| 3620 | break; | 3650 | break; |
| 3621 | case 233: /* GUI IDLE */ | 3651 | case 233: /* GUI IDLE */ |
| 3622 | DRM_DEBUG("IH: GUI idle\n"); | 3652 | DRM_DEBUG("IH: GUI idle\n"); |
| 3623 | rdev->pm.gui_idle = true; | ||
| 3624 | wake_up(&rdev->irq.idle_queue); | 3653 | wake_up(&rdev->irq.idle_queue); |
| 3625 | break; | 3654 | break; |
| 3626 | default: | 3655 | default: |
| @@ -3632,15 +3661,17 @@ restart_ih: | |||
| 3632 | rptr += 16; | 3661 | rptr += 16; |
| 3633 | rptr &= rdev->ih.ptr_mask; | 3662 | rptr &= rdev->ih.ptr_mask; |
| 3634 | } | 3663 | } |
| 3635 | /* make sure wptr hasn't changed while processing */ | ||
| 3636 | wptr = si_get_ih_wptr(rdev); | ||
| 3637 | if (wptr != rdev->ih.wptr) | ||
| 3638 | goto restart_ih; | ||
| 3639 | if (queue_hotplug) | 3664 | if (queue_hotplug) |
| 3640 | schedule_work(&rdev->hotplug_work); | 3665 | schedule_work(&rdev->hotplug_work); |
| 3641 | rdev->ih.rptr = rptr; | 3666 | rdev->ih.rptr = rptr; |
| 3642 | WREG32(IH_RB_RPTR, rdev->ih.rptr); | 3667 | WREG32(IH_RB_RPTR, rdev->ih.rptr); |
| 3643 | spin_unlock_irqrestore(&rdev->ih.lock, flags); | 3668 | atomic_set(&rdev->ih.lock, 0); |
| 3669 | |||
| 3670 | /* make sure wptr hasn't changed while processing */ | ||
| 3671 | wptr = si_get_ih_wptr(rdev); | ||
| 3672 | if (wptr != rptr) | ||
| 3673 | goto restart_ih; | ||
| 3674 | |||
| 3644 | return IRQ_HANDLED; | 3675 | return IRQ_HANDLED; |
| 3645 | } | 3676 | } |
| 3646 | 3677 | ||
| @@ -3752,35 +3783,18 @@ static int si_startup(struct radeon_device *rdev) | |||
| 3752 | if (r) | 3783 | if (r) |
| 3753 | return r; | 3784 | return r; |
| 3754 | 3785 | ||
| 3755 | r = radeon_ib_pool_start(rdev); | 3786 | r = radeon_ib_pool_init(rdev); |
| 3756 | if (r) | ||
| 3757 | return r; | ||
| 3758 | |||
| 3759 | r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); | ||
| 3760 | if (r) { | ||
| 3761 | DRM_ERROR("radeon: failed testing IB (%d) on CP ring 0\n", r); | ||
| 3762 | rdev->accel_working = false; | ||
| 3763 | return r; | ||
| 3764 | } | ||
| 3765 | |||
| 3766 | r = radeon_ib_test(rdev, CAYMAN_RING_TYPE_CP1_INDEX, &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]); | ||
| 3767 | if (r) { | 3787 | if (r) { |
| 3768 | DRM_ERROR("radeon: failed testing IB (%d) on CP ring 1\n", r); | 3788 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
| 3769 | rdev->accel_working = false; | ||
| 3770 | return r; | 3789 | return r; |
| 3771 | } | 3790 | } |
| 3772 | 3791 | ||
| 3773 | r = radeon_ib_test(rdev, CAYMAN_RING_TYPE_CP2_INDEX, &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]); | 3792 | r = radeon_vm_manager_init(rdev); |
| 3774 | if (r) { | 3793 | if (r) { |
| 3775 | DRM_ERROR("radeon: failed testing IB (%d) on CP ring 2\n", r); | 3794 | dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); |
| 3776 | rdev->accel_working = false; | ||
| 3777 | return r; | 3795 | return r; |
| 3778 | } | 3796 | } |
| 3779 | 3797 | ||
| 3780 | r = radeon_vm_manager_start(rdev); | ||
| 3781 | if (r) | ||
| 3782 | return r; | ||
| 3783 | |||
| 3784 | return 0; | 3798 | return 0; |
| 3785 | } | 3799 | } |
| 3786 | 3800 | ||
| @@ -3809,12 +3823,6 @@ int si_resume(struct radeon_device *rdev) | |||
| 3809 | 3823 | ||
| 3810 | int si_suspend(struct radeon_device *rdev) | 3824 | int si_suspend(struct radeon_device *rdev) |
| 3811 | { | 3825 | { |
| 3812 | /* FIXME: we should wait for ring to be empty */ | ||
| 3813 | radeon_ib_pool_suspend(rdev); | ||
| 3814 | radeon_vm_manager_suspend(rdev); | ||
| 3815 | #if 0 | ||
| 3816 | r600_blit_suspend(rdev); | ||
| 3817 | #endif | ||
| 3818 | si_cp_enable(rdev, false); | 3826 | si_cp_enable(rdev, false); |
| 3819 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; | 3827 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; |
| 3820 | rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; | 3828 | rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; |
| @@ -3903,17 +3911,7 @@ int si_init(struct radeon_device *rdev) | |||
| 3903 | if (r) | 3911 | if (r) |
| 3904 | return r; | 3912 | return r; |
| 3905 | 3913 | ||
| 3906 | r = radeon_ib_pool_init(rdev); | ||
| 3907 | rdev->accel_working = true; | 3914 | rdev->accel_working = true; |
| 3908 | if (r) { | ||
| 3909 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | ||
| 3910 | rdev->accel_working = false; | ||
| 3911 | } | ||
| 3912 | r = radeon_vm_manager_init(rdev); | ||
| 3913 | if (r) { | ||
| 3914 | dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); | ||
| 3915 | } | ||
| 3916 | |||
| 3917 | r = si_startup(rdev); | 3915 | r = si_startup(rdev); |
| 3918 | if (r) { | 3916 | if (r) { |
| 3919 | dev_err(rdev->dev, "disabling GPU acceleration\n"); | 3917 | dev_err(rdev->dev, "disabling GPU acceleration\n"); |
| @@ -3921,7 +3919,7 @@ int si_init(struct radeon_device *rdev) | |||
| 3921 | si_irq_fini(rdev); | 3919 | si_irq_fini(rdev); |
| 3922 | si_rlc_fini(rdev); | 3920 | si_rlc_fini(rdev); |
| 3923 | radeon_wb_fini(rdev); | 3921 | radeon_wb_fini(rdev); |
| 3924 | r100_ib_fini(rdev); | 3922 | radeon_ib_pool_fini(rdev); |
| 3925 | radeon_vm_manager_fini(rdev); | 3923 | radeon_vm_manager_fini(rdev); |
| 3926 | radeon_irq_kms_fini(rdev); | 3924 | radeon_irq_kms_fini(rdev); |
| 3927 | si_pcie_gart_fini(rdev); | 3925 | si_pcie_gart_fini(rdev); |
| @@ -3950,7 +3948,7 @@ void si_fini(struct radeon_device *rdev) | |||
| 3950 | si_rlc_fini(rdev); | 3948 | si_rlc_fini(rdev); |
| 3951 | radeon_wb_fini(rdev); | 3949 | radeon_wb_fini(rdev); |
| 3952 | radeon_vm_manager_fini(rdev); | 3950 | radeon_vm_manager_fini(rdev); |
| 3953 | r100_ib_fini(rdev); | 3951 | radeon_ib_pool_fini(rdev); |
| 3954 | radeon_irq_kms_fini(rdev); | 3952 | radeon_irq_kms_fini(rdev); |
| 3955 | si_pcie_gart_fini(rdev); | 3953 | si_pcie_gart_fini(rdev); |
| 3956 | r600_vram_scratch_fini(rdev); | 3954 | r600_vram_scratch_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index db4067962868..7869089e8761 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h | |||
| @@ -901,5 +901,6 @@ | |||
| 901 | #define PACKET3_WAIT_ON_DE_COUNTER_DIFF 0x88 | 901 | #define PACKET3_WAIT_ON_DE_COUNTER_DIFF 0x88 |
| 902 | #define PACKET3_SET_CE_DE_COUNTERS 0x89 | 902 | #define PACKET3_SET_CE_DE_COUNTERS 0x89 |
| 903 | #define PACKET3_WAIT_ON_AVAIL_BUFFER 0x8A | 903 | #define PACKET3_WAIT_ON_AVAIL_BUFFER 0x8A |
| 904 | #define PACKET3_SWITCH_BUFFER 0x8B | ||
| 904 | 905 | ||
| 905 | #endif | 906 | #endif |
diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c index 6eb507a5d130..1efbb9075837 100644 --- a/drivers/gpu/drm/savage/savage_bci.c +++ b/drivers/gpu/drm/savage/savage_bci.c | |||
| @@ -1050,6 +1050,7 @@ void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) | |||
| 1050 | { | 1050 | { |
| 1051 | struct drm_device_dma *dma = dev->dma; | 1051 | struct drm_device_dma *dma = dev->dma; |
| 1052 | drm_savage_private_t *dev_priv = dev->dev_private; | 1052 | drm_savage_private_t *dev_priv = dev->dev_private; |
| 1053 | int release_idlelock = 0; | ||
| 1053 | int i; | 1054 | int i; |
| 1054 | 1055 | ||
| 1055 | if (!dma) | 1056 | if (!dma) |
| @@ -1059,7 +1060,10 @@ void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) | |||
| 1059 | if (!dma->buflist) | 1060 | if (!dma->buflist) |
| 1060 | return; | 1061 | return; |
| 1061 | 1062 | ||
| 1062 | /*i830_flush_queue(dev); */ | 1063 | if (file_priv->master && file_priv->master->lock.hw_lock) { |
| 1064 | drm_idlelock_take(&file_priv->master->lock); | ||
| 1065 | release_idlelock = 1; | ||
| 1066 | } | ||
| 1063 | 1067 | ||
| 1064 | for (i = 0; i < dma->buf_count; i++) { | 1068 | for (i = 0; i < dma->buf_count; i++) { |
| 1065 | struct drm_buf *buf = dma->buflist[i]; | 1069 | struct drm_buf *buf = dma->buflist[i]; |
| @@ -1075,7 +1079,8 @@ void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) | |||
| 1075 | } | 1079 | } |
| 1076 | } | 1080 | } |
| 1077 | 1081 | ||
| 1078 | drm_core_reclaim_buffers(dev, file_priv); | 1082 | if (release_idlelock) |
| 1083 | drm_idlelock_release(&file_priv->master->lock); | ||
| 1079 | } | 1084 | } |
| 1080 | 1085 | ||
| 1081 | struct drm_ioctl_desc savage_ioctls[] = { | 1086 | struct drm_ioctl_desc savage_ioctls[] = { |
diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c index 89afe0b83643..d31d4cca9a4c 100644 --- a/drivers/gpu/drm/savage/savage_drv.c +++ b/drivers/gpu/drm/savage/savage_drv.c | |||
| @@ -52,9 +52,9 @@ static struct drm_driver driver = { | |||
| 52 | .dev_priv_size = sizeof(drm_savage_buf_priv_t), | 52 | .dev_priv_size = sizeof(drm_savage_buf_priv_t), |
| 53 | .load = savage_driver_load, | 53 | .load = savage_driver_load, |
| 54 | .firstopen = savage_driver_firstopen, | 54 | .firstopen = savage_driver_firstopen, |
| 55 | .preclose = savage_reclaim_buffers, | ||
| 55 | .lastclose = savage_driver_lastclose, | 56 | .lastclose = savage_driver_lastclose, |
| 56 | .unload = savage_driver_unload, | 57 | .unload = savage_driver_unload, |
| 57 | .reclaim_buffers = savage_reclaim_buffers, | ||
| 58 | .ioctls = savage_ioctls, | 58 | .ioctls = savage_ioctls, |
| 59 | .dma_ioctl = savage_bci_buffers, | 59 | .dma_ioctl = savage_bci_buffers, |
| 60 | .fops = &savage_driver_fops, | 60 | .fops = &savage_driver_fops, |
diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index dd14cd1a0033..7f119870147c 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c | |||
| @@ -105,10 +105,9 @@ static struct drm_driver driver = { | |||
| 105 | .load = sis_driver_load, | 105 | .load = sis_driver_load, |
| 106 | .unload = sis_driver_unload, | 106 | .unload = sis_driver_unload, |
| 107 | .open = sis_driver_open, | 107 | .open = sis_driver_open, |
| 108 | .preclose = sis_reclaim_buffers_locked, | ||
| 108 | .postclose = sis_driver_postclose, | 109 | .postclose = sis_driver_postclose, |
| 109 | .dma_quiescent = sis_idle, | 110 | .dma_quiescent = sis_idle, |
| 110 | .reclaim_buffers = NULL, | ||
| 111 | .reclaim_buffers_idlelocked = sis_reclaim_buffers_locked, | ||
| 112 | .lastclose = sis_lastclose, | 111 | .lastclose = sis_lastclose, |
| 113 | .ioctls = sis_ioctls, | 112 | .ioctls = sis_ioctls, |
| 114 | .fops = &sis_driver_fops, | 113 | .fops = &sis_driver_fops, |
diff --git a/drivers/gpu/drm/sis/sis_mm.c b/drivers/gpu/drm/sis/sis_mm.c index dd4a316c3d74..2c231070d250 100644 --- a/drivers/gpu/drm/sis/sis_mm.c +++ b/drivers/gpu/drm/sis/sis_mm.c | |||
| @@ -74,7 +74,7 @@ static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file | |||
| 74 | dev_priv->vram_offset = fb->offset; | 74 | dev_priv->vram_offset = fb->offset; |
| 75 | 75 | ||
| 76 | mutex_unlock(&dev->struct_mutex); | 76 | mutex_unlock(&dev->struct_mutex); |
| 77 | DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size); | 77 | DRM_DEBUG("offset = %lu, size = %lu\n", fb->offset, fb->size); |
| 78 | 78 | ||
| 79 | return 0; | 79 | return 0; |
| 80 | } | 80 | } |
| @@ -161,7 +161,7 @@ fail_alloc: | |||
| 161 | mem->size = 0; | 161 | mem->size = 0; |
| 162 | mem->free = 0; | 162 | mem->free = 0; |
| 163 | 163 | ||
| 164 | DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem->size, | 164 | DRM_DEBUG("alloc %d, size = %ld, offset = %ld\n", pool, mem->size, |
| 165 | mem->offset); | 165 | mem->offset); |
| 166 | 166 | ||
| 167 | return retval; | 167 | return retval; |
| @@ -215,7 +215,7 @@ static int sis_ioctl_agp_init(struct drm_device *dev, void *data, | |||
| 215 | dev_priv->agp_offset = agp->offset; | 215 | dev_priv->agp_offset = agp->offset; |
| 216 | mutex_unlock(&dev->struct_mutex); | 216 | mutex_unlock(&dev->struct_mutex); |
| 217 | 217 | ||
| 218 | DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size); | 218 | DRM_DEBUG("offset = %lu, size = %lu\n", agp->offset, agp->size); |
| 219 | return 0; | 219 | return 0; |
| 220 | } | 220 | } |
| 221 | 221 | ||
| @@ -321,14 +321,20 @@ void sis_reclaim_buffers_locked(struct drm_device *dev, | |||
| 321 | struct sis_file_private *file_priv = file->driver_priv; | 321 | struct sis_file_private *file_priv = file->driver_priv; |
| 322 | struct sis_memblock *entry, *next; | 322 | struct sis_memblock *entry, *next; |
| 323 | 323 | ||
| 324 | if (!(file->minor->master && file->master->lock.hw_lock)) | ||
| 325 | return; | ||
| 326 | |||
| 327 | drm_idlelock_take(&file->master->lock); | ||
| 328 | |||
| 324 | mutex_lock(&dev->struct_mutex); | 329 | mutex_lock(&dev->struct_mutex); |
| 325 | if (list_empty(&file_priv->obj_list)) { | 330 | if (list_empty(&file_priv->obj_list)) { |
| 326 | mutex_unlock(&dev->struct_mutex); | 331 | mutex_unlock(&dev->struct_mutex); |
| 332 | drm_idlelock_release(&file->master->lock); | ||
| 333 | |||
| 327 | return; | 334 | return; |
| 328 | } | 335 | } |
| 329 | 336 | ||
| 330 | if (dev->driver->dma_quiescent) | 337 | sis_idle(dev); |
| 331 | dev->driver->dma_quiescent(dev); | ||
| 332 | 338 | ||
| 333 | 339 | ||
| 334 | list_for_each_entry_safe(entry, next, &file_priv->obj_list, | 340 | list_for_each_entry_safe(entry, next, &file_priv->obj_list, |
| @@ -343,6 +349,9 @@ void sis_reclaim_buffers_locked(struct drm_device *dev, | |||
| 343 | kfree(entry); | 349 | kfree(entry); |
| 344 | } | 350 | } |
| 345 | mutex_unlock(&dev->struct_mutex); | 351 | mutex_unlock(&dev->struct_mutex); |
| 352 | |||
| 353 | drm_idlelock_release(&file->master->lock); | ||
| 354 | |||
| 346 | return; | 355 | return; |
| 347 | } | 356 | } |
| 348 | 357 | ||
diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index 1613c78544c0..90f6b13acfac 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c | |||
| @@ -54,7 +54,6 @@ static const struct file_operations tdfx_driver_fops = { | |||
| 54 | 54 | ||
| 55 | static struct drm_driver driver = { | 55 | static struct drm_driver driver = { |
| 56 | .driver_features = DRIVER_USE_MTRR, | 56 | .driver_features = DRIVER_USE_MTRR, |
| 57 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 58 | .fops = &tdfx_driver_fops, | 57 | .fops = &tdfx_driver_fops, |
| 59 | .name = DRIVER_NAME, | 58 | .name = DRIVER_NAME, |
| 60 | .desc = DRIVER_DESC, | 59 | .desc = DRIVER_DESC, |
diff --git a/drivers/gpu/drm/udl/udl_encoder.c b/drivers/gpu/drm/udl/udl_encoder.c index 56e75f0f1df5..0731ab2e6c06 100644 --- a/drivers/gpu/drm/udl/udl_encoder.c +++ b/drivers/gpu/drm/udl/udl_encoder.c | |||
| @@ -27,7 +27,7 @@ static void udl_encoder_disable(struct drm_encoder *encoder) | |||
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | static bool udl_mode_fixup(struct drm_encoder *encoder, | 29 | static bool udl_mode_fixup(struct drm_encoder *encoder, |
| 30 | struct drm_display_mode *mode, | 30 | const struct drm_display_mode *mode, |
| 31 | struct drm_display_mode *adjusted_mode) | 31 | struct drm_display_mode *adjusted_mode) |
| 32 | { | 32 | { |
| 33 | return true; | 33 | return true; |
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 0d7816789da1..f5dd89e891de 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c | |||
| @@ -45,12 +45,25 @@ static char *udl_vidreg_unlock(char *buf) | |||
| 45 | * 0x01 H and V sync off (screen blank but powered) | 45 | * 0x01 H and V sync off (screen blank but powered) |
| 46 | * 0x07 DPMS powerdown (requires modeset to come back) | 46 | * 0x07 DPMS powerdown (requires modeset to come back) |
| 47 | */ | 47 | */ |
| 48 | static char *udl_enable_hvsync(char *buf, bool enable) | 48 | static char *udl_set_blank(char *buf, int dpms_mode) |
| 49 | { | 49 | { |
| 50 | if (enable) | 50 | u8 reg; |
| 51 | return udl_set_register(buf, 0x1F, 0x00); | 51 | switch (dpms_mode) { |
| 52 | else | 52 | case DRM_MODE_DPMS_OFF: |
| 53 | return udl_set_register(buf, 0x1F, 0x07); | 53 | reg = 0x07; |
| 54 | break; | ||
| 55 | case DRM_MODE_DPMS_STANDBY: | ||
| 56 | reg = 0x05; | ||
| 57 | break; | ||
| 58 | case DRM_MODE_DPMS_SUSPEND: | ||
| 59 | reg = 0x01; | ||
| 60 | break; | ||
| 61 | case DRM_MODE_DPMS_ON: | ||
| 62 | reg = 0x00; | ||
| 63 | break; | ||
| 64 | } | ||
| 65 | |||
| 66 | return udl_set_register(buf, 0x1f, reg); | ||
| 54 | } | 67 | } |
| 55 | 68 | ||
| 56 | static char *udl_set_color_depth(char *buf, u8 selection) | 69 | static char *udl_set_color_depth(char *buf, u8 selection) |
| @@ -199,6 +212,20 @@ static char *udl_set_vid_cmds(char *wrptr, struct drm_display_mode *mode) | |||
| 199 | return wrptr; | 212 | return wrptr; |
| 200 | } | 213 | } |
| 201 | 214 | ||
| 215 | static char *udl_dummy_render(char *wrptr) | ||
| 216 | { | ||
| 217 | *wrptr++ = 0xAF; | ||
| 218 | *wrptr++ = 0x6A; /* copy */ | ||
| 219 | *wrptr++ = 0x00; /* from addr */ | ||
| 220 | *wrptr++ = 0x00; | ||
| 221 | *wrptr++ = 0x00; | ||
| 222 | *wrptr++ = 0x01; /* one pixel */ | ||
| 223 | *wrptr++ = 0x00; /* to address */ | ||
| 224 | *wrptr++ = 0x00; | ||
| 225 | *wrptr++ = 0x00; | ||
| 226 | return wrptr; | ||
| 227 | } | ||
| 228 | |||
| 202 | static int udl_crtc_write_mode_to_hw(struct drm_crtc *crtc) | 229 | static int udl_crtc_write_mode_to_hw(struct drm_crtc *crtc) |
| 203 | { | 230 | { |
| 204 | struct drm_device *dev = crtc->dev; | 231 | struct drm_device *dev = crtc->dev; |
| @@ -235,9 +262,10 @@ static void udl_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
| 235 | 262 | ||
| 236 | buf = (char *)urb->transfer_buffer; | 263 | buf = (char *)urb->transfer_buffer; |
| 237 | buf = udl_vidreg_lock(buf); | 264 | buf = udl_vidreg_lock(buf); |
| 238 | buf = udl_enable_hvsync(buf, false); | 265 | buf = udl_set_blank(buf, mode); |
| 239 | buf = udl_vidreg_unlock(buf); | 266 | buf = udl_vidreg_unlock(buf); |
| 240 | 267 | ||
| 268 | buf = udl_dummy_render(buf); | ||
| 241 | retval = udl_submit_urb(dev, urb, buf - (char *) | 269 | retval = udl_submit_urb(dev, urb, buf - (char *) |
| 242 | urb->transfer_buffer); | 270 | urb->transfer_buffer); |
| 243 | } else { | 271 | } else { |
| @@ -251,7 +279,7 @@ static void udl_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
| 251 | } | 279 | } |
| 252 | 280 | ||
| 253 | static bool udl_crtc_mode_fixup(struct drm_crtc *crtc, | 281 | static bool udl_crtc_mode_fixup(struct drm_crtc *crtc, |
| 254 | struct drm_display_mode *mode, | 282 | const struct drm_display_mode *mode, |
| 255 | struct drm_display_mode *adjusted_mode) | 283 | struct drm_display_mode *adjusted_mode) |
| 256 | 284 | ||
| 257 | { | 285 | { |
| @@ -306,9 +334,11 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc, | |||
| 306 | wrptr = udl_set_base8bpp(wrptr, 2 * mode->vdisplay * mode->hdisplay); | 334 | wrptr = udl_set_base8bpp(wrptr, 2 * mode->vdisplay * mode->hdisplay); |
| 307 | 335 | ||
| 308 | wrptr = udl_set_vid_cmds(wrptr, adjusted_mode); | 336 | wrptr = udl_set_vid_cmds(wrptr, adjusted_mode); |
| 309 | wrptr = udl_enable_hvsync(wrptr, true); | 337 | wrptr = udl_set_blank(wrptr, DRM_MODE_DPMS_ON); |
| 310 | wrptr = udl_vidreg_unlock(wrptr); | 338 | wrptr = udl_vidreg_unlock(wrptr); |
| 311 | 339 | ||
| 340 | wrptr = udl_dummy_render(wrptr); | ||
| 341 | |||
| 312 | ufb->active_16 = true; | 342 | ufb->active_16 = true; |
| 313 | if (old_fb) { | 343 | if (old_fb) { |
| 314 | struct udl_framebuffer *uold_fb = to_udl_fb(old_fb); | 344 | struct udl_framebuffer *uold_fb = to_udl_fb(old_fb); |
diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index 02661f35f7a0..e927b4c052f5 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c | |||
| @@ -75,6 +75,7 @@ static struct drm_driver driver = { | |||
| 75 | .load = via_driver_load, | 75 | .load = via_driver_load, |
| 76 | .unload = via_driver_unload, | 76 | .unload = via_driver_unload, |
| 77 | .open = via_driver_open, | 77 | .open = via_driver_open, |
| 78 | .preclose = via_reclaim_buffers_locked, | ||
| 78 | .postclose = via_driver_postclose, | 79 | .postclose = via_driver_postclose, |
| 79 | .context_dtor = via_final_context, | 80 | .context_dtor = via_final_context, |
| 80 | .get_vblank_counter = via_get_vblank_counter, | 81 | .get_vblank_counter = via_get_vblank_counter, |
| @@ -85,9 +86,6 @@ static struct drm_driver driver = { | |||
| 85 | .irq_uninstall = via_driver_irq_uninstall, | 86 | .irq_uninstall = via_driver_irq_uninstall, |
| 86 | .irq_handler = via_driver_irq_handler, | 87 | .irq_handler = via_driver_irq_handler, |
| 87 | .dma_quiescent = via_driver_dma_quiescent, | 88 | .dma_quiescent = via_driver_dma_quiescent, |
| 88 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 89 | .reclaim_buffers_locked = NULL, | ||
| 90 | .reclaim_buffers_idlelocked = via_reclaim_buffers_locked, | ||
| 91 | .lastclose = via_lastclose, | 89 | .lastclose = via_lastclose, |
| 92 | .ioctls = via_ioctls, | 90 | .ioctls = via_ioctls, |
| 93 | .fops = &via_driver_fops, | 91 | .fops = &via_driver_fops, |
diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c index a3574d09a07d..acfcb358e7b7 100644 --- a/drivers/gpu/drm/via/via_mm.c +++ b/drivers/gpu/drm/via/via_mm.c | |||
| @@ -215,14 +215,20 @@ void via_reclaim_buffers_locked(struct drm_device *dev, | |||
| 215 | struct via_file_private *file_priv = file->driver_priv; | 215 | struct via_file_private *file_priv = file->driver_priv; |
| 216 | struct via_memblock *entry, *next; | 216 | struct via_memblock *entry, *next; |
| 217 | 217 | ||
| 218 | if (!(file->minor->master && file->master->lock.hw_lock)) | ||
| 219 | return; | ||
| 220 | |||
| 221 | drm_idlelock_take(&file->master->lock); | ||
| 222 | |||
| 218 | mutex_lock(&dev->struct_mutex); | 223 | mutex_lock(&dev->struct_mutex); |
| 219 | if (list_empty(&file_priv->obj_list)) { | 224 | if (list_empty(&file_priv->obj_list)) { |
| 220 | mutex_unlock(&dev->struct_mutex); | 225 | mutex_unlock(&dev->struct_mutex); |
| 226 | drm_idlelock_release(&file->master->lock); | ||
| 227 | |||
| 221 | return; | 228 | return; |
| 222 | } | 229 | } |
| 223 | 230 | ||
| 224 | if (dev->driver->dma_quiescent) | 231 | via_driver_dma_quiescent(dev); |
| 225 | dev->driver->dma_quiescent(dev); | ||
| 226 | 232 | ||
| 227 | list_for_each_entry_safe(entry, next, &file_priv->obj_list, | 233 | list_for_each_entry_safe(entry, next, &file_priv->obj_list, |
| 228 | owner_list) { | 234 | owner_list) { |
| @@ -231,5 +237,8 @@ void via_reclaim_buffers_locked(struct drm_device *dev, | |||
| 231 | kfree(entry); | 237 | kfree(entry); |
| 232 | } | 238 | } |
| 233 | mutex_unlock(&dev->struct_mutex); | 239 | mutex_unlock(&dev->struct_mutex); |
| 240 | |||
| 241 | drm_idlelock_release(&file->master->lock); | ||
| 242 | |||
| 234 | return; | 243 | return; |
| 235 | } | 244 | } |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index ee24d216aa85..4d9edead01ac 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | |||
| @@ -769,10 +769,7 @@ static int vmw_driver_open(struct drm_device *dev, struct drm_file *file_priv) | |||
| 769 | goto out_no_tfile; | 769 | goto out_no_tfile; |
| 770 | 770 | ||
| 771 | file_priv->driver_priv = vmw_fp; | 771 | file_priv->driver_priv = vmw_fp; |
| 772 | 772 | dev_priv->bdev.dev_mapping = dev->dev_mapping; | |
| 773 | if (unlikely(dev_priv->bdev.dev_mapping == NULL)) | ||
| 774 | dev_priv->bdev.dev_mapping = | ||
| 775 | file_priv->filp->f_path.dentry->d_inode->i_mapping; | ||
| 776 | 773 | ||
| 777 | return 0; | 774 | return 0; |
| 778 | 775 | ||
| @@ -1147,7 +1144,6 @@ static struct drm_driver driver = { | |||
| 1147 | .get_vblank_counter = vmw_get_vblank_counter, | 1144 | .get_vblank_counter = vmw_get_vblank_counter, |
| 1148 | .enable_vblank = vmw_enable_vblank, | 1145 | .enable_vblank = vmw_enable_vblank, |
| 1149 | .disable_vblank = vmw_disable_vblank, | 1146 | .disable_vblank = vmw_disable_vblank, |
| 1150 | .reclaim_buffers_locked = NULL, | ||
| 1151 | .ioctls = vmw_ioctls, | 1147 | .ioctls = vmw_ioctls, |
| 1152 | .num_ioctls = DRM_ARRAY_SIZE(vmw_ioctls), | 1148 | .num_ioctls = DRM_ARRAY_SIZE(vmw_ioctls), |
| 1153 | .dma_quiescent = NULL, /*vmw_dma_quiescent, */ | 1149 | .dma_quiescent = NULL, /*vmw_dma_quiescent, */ |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 8c2754f835ef..240ff3125040 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
| @@ -2485,9 +2485,10 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp | |||
| 2485 | */ | 2485 | */ |
| 2486 | if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { | 2486 | if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { |
| 2487 | atomic_set(&r1_bio->remaining, read_targets); | 2487 | atomic_set(&r1_bio->remaining, read_targets); |
| 2488 | for (i = 0; i < conf->raid_disks * 2; i++) { | 2488 | for (i = 0; i < conf->raid_disks * 2 && read_targets; i++) { |
| 2489 | bio = r1_bio->bios[i]; | 2489 | bio = r1_bio->bios[i]; |
| 2490 | if (bio->bi_end_io == end_sync_read) { | 2490 | if (bio->bi_end_io == end_sync_read) { |
| 2491 | read_targets--; | ||
| 2491 | md_sync_acct(bio->bi_bdev, nr_sectors); | 2492 | md_sync_acct(bio->bi_bdev, nr_sectors); |
| 2492 | generic_make_request(bio); | 2493 | generic_make_request(bio); |
| 2493 | } | 2494 | } |
diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c index 8b864afb40b6..62e0022561bc 100644 --- a/drivers/staging/omapdrm/omap_crtc.c +++ b/drivers/staging/omapdrm/omap_crtc.c | |||
| @@ -60,7 +60,7 @@ static void omap_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | static bool omap_crtc_mode_fixup(struct drm_crtc *crtc, | 62 | static bool omap_crtc_mode_fixup(struct drm_crtc *crtc, |
| 63 | struct drm_display_mode *mode, | 63 | const struct drm_display_mode *mode, |
| 64 | struct drm_display_mode *adjusted_mode) | 64 | struct drm_display_mode *adjusted_mode) |
| 65 | { | 65 | { |
| 66 | return true; | 66 | return true; |
diff --git a/drivers/staging/omapdrm/omap_encoder.c b/drivers/staging/omapdrm/omap_encoder.c index 06c52cb62d2f..31c735d39217 100644 --- a/drivers/staging/omapdrm/omap_encoder.c +++ b/drivers/staging/omapdrm/omap_encoder.c | |||
| @@ -48,7 +48,7 @@ static void omap_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | static bool omap_encoder_mode_fixup(struct drm_encoder *encoder, | 50 | static bool omap_encoder_mode_fixup(struct drm_encoder *encoder, |
| 51 | struct drm_display_mode *mode, | 51 | const struct drm_display_mode *mode, |
| 52 | struct drm_display_mode *adjusted_mode) | 52 | struct drm_display_mode *adjusted_mode) |
| 53 | { | 53 | { |
| 54 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | 54 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 31ad880ca2ef..d6b67bb9075f 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
| @@ -348,7 +348,6 @@ struct drm_buf { | |||
| 348 | struct drm_buf *next; /**< Kernel-only: used for free list */ | 348 | struct drm_buf *next; /**< Kernel-only: used for free list */ |
| 349 | __volatile__ int waiting; /**< On kernel DMA queue */ | 349 | __volatile__ int waiting; /**< On kernel DMA queue */ |
| 350 | __volatile__ int pending; /**< On hardware DMA queue */ | 350 | __volatile__ int pending; /**< On hardware DMA queue */ |
| 351 | wait_queue_head_t dma_wait; /**< Processes waiting */ | ||
| 352 | struct drm_file *file_priv; /**< Private of holding file descr */ | 351 | struct drm_file *file_priv; /**< Private of holding file descr */ |
| 353 | int context; /**< Kernel queue for this buffer */ | 352 | int context; /**< Kernel queue for this buffer */ |
| 354 | int while_locked; /**< Dispatch this buffer while locked */ | 353 | int while_locked; /**< Dispatch this buffer while locked */ |
| @@ -876,12 +875,6 @@ struct drm_driver { | |||
| 876 | void (*irq_preinstall) (struct drm_device *dev); | 875 | void (*irq_preinstall) (struct drm_device *dev); |
| 877 | int (*irq_postinstall) (struct drm_device *dev); | 876 | int (*irq_postinstall) (struct drm_device *dev); |
| 878 | void (*irq_uninstall) (struct drm_device *dev); | 877 | void (*irq_uninstall) (struct drm_device *dev); |
| 879 | void (*reclaim_buffers) (struct drm_device *dev, | ||
| 880 | struct drm_file * file_priv); | ||
| 881 | void (*reclaim_buffers_locked) (struct drm_device *dev, | ||
| 882 | struct drm_file *file_priv); | ||
| 883 | void (*reclaim_buffers_idlelocked) (struct drm_device *dev, | ||
| 884 | struct drm_file *file_priv); | ||
| 885 | void (*set_version) (struct drm_device *dev, | 878 | void (*set_version) (struct drm_device *dev, |
| 886 | struct drm_set_version *sv); | 879 | struct drm_set_version *sv); |
| 887 | 880 | ||
| @@ -1108,12 +1101,8 @@ struct drm_device { | |||
| 1108 | 1101 | ||
| 1109 | /*@} */ | 1102 | /*@} */ |
| 1110 | 1103 | ||
| 1111 | /** \name DMA queues (contexts) */ | 1104 | /** \name DMA support */ |
| 1112 | /*@{ */ | 1105 | /*@{ */ |
| 1113 | int queue_count; /**< Number of active DMA queues */ | ||
| 1114 | int queue_reserved; /**< Number of reserved DMA queues */ | ||
| 1115 | int queue_slots; /**< Actual length of queuelist */ | ||
| 1116 | struct drm_queue **queuelist; /**< Vector of pointers to DMA queues */ | ||
| 1117 | struct drm_device_dma *dma; /**< Optional pointer for DMA support */ | 1106 | struct drm_device_dma *dma; /**< Optional pointer for DMA support */ |
| 1118 | /*@} */ | 1107 | /*@} */ |
| 1119 | 1108 | ||
| @@ -1540,7 +1529,6 @@ extern int drm_debugfs_cleanup(struct drm_minor *minor); | |||
| 1540 | /* Info file support */ | 1529 | /* Info file support */ |
| 1541 | extern int drm_name_info(struct seq_file *m, void *data); | 1530 | extern int drm_name_info(struct seq_file *m, void *data); |
| 1542 | extern int drm_vm_info(struct seq_file *m, void *data); | 1531 | extern int drm_vm_info(struct seq_file *m, void *data); |
| 1543 | extern int drm_queues_info(struct seq_file *m, void *data); | ||
| 1544 | extern int drm_bufs_info(struct seq_file *m, void *data); | 1532 | extern int drm_bufs_info(struct seq_file *m, void *data); |
| 1545 | extern int drm_vblank_info(struct seq_file *m, void *data); | 1533 | extern int drm_vblank_info(struct seq_file *m, void *data); |
| 1546 | extern int drm_clients_info(struct seq_file *m, void* data); | 1534 | extern int drm_clients_info(struct seq_file *m, void* data); |
| @@ -1761,6 +1749,11 @@ extern int drm_get_pci_dev(struct pci_dev *pdev, | |||
| 1761 | const struct pci_device_id *ent, | 1749 | const struct pci_device_id *ent, |
| 1762 | struct drm_driver *driver); | 1750 | struct drm_driver *driver); |
| 1763 | 1751 | ||
| 1752 | #define DRM_PCIE_SPEED_25 1 | ||
| 1753 | #define DRM_PCIE_SPEED_50 2 | ||
| 1754 | #define DRM_PCIE_SPEED_80 4 | ||
| 1755 | |||
| 1756 | extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask); | ||
| 1764 | 1757 | ||
| 1765 | /* platform section */ | 1758 | /* platform section */ |
| 1766 | extern int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device); | 1759 | extern int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device); |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index bac55c215113..a1a0386e0160 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
| @@ -676,8 +676,6 @@ struct drm_plane { | |||
| 676 | * This is used to set modes. | 676 | * This is used to set modes. |
| 677 | */ | 677 | */ |
| 678 | struct drm_mode_set { | 678 | struct drm_mode_set { |
| 679 | struct list_head head; | ||
| 680 | |||
| 681 | struct drm_framebuffer *fb; | 679 | struct drm_framebuffer *fb; |
| 682 | struct drm_crtc *crtc; | 680 | struct drm_crtc *crtc; |
| 683 | struct drm_display_mode *mode; | 681 | struct drm_display_mode *mode; |
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 7988e55c98d0..e01cc80c9c30 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h | |||
| @@ -62,7 +62,7 @@ struct drm_crtc_helper_funcs { | |||
| 62 | 62 | ||
| 63 | /* Provider can fixup or change mode timings before modeset occurs */ | 63 | /* Provider can fixup or change mode timings before modeset occurs */ |
| 64 | bool (*mode_fixup)(struct drm_crtc *crtc, | 64 | bool (*mode_fixup)(struct drm_crtc *crtc, |
| 65 | struct drm_display_mode *mode, | 65 | const struct drm_display_mode *mode, |
| 66 | struct drm_display_mode *adjusted_mode); | 66 | struct drm_display_mode *adjusted_mode); |
| 67 | /* Actually set the mode */ | 67 | /* Actually set the mode */ |
| 68 | int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, | 68 | int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, |
| @@ -96,7 +96,7 @@ struct drm_encoder_helper_funcs { | |||
| 96 | void (*restore)(struct drm_encoder *encoder); | 96 | void (*restore)(struct drm_encoder *encoder); |
| 97 | 97 | ||
| 98 | bool (*mode_fixup)(struct drm_encoder *encoder, | 98 | bool (*mode_fixup)(struct drm_encoder *encoder, |
| 99 | struct drm_display_mode *mode, | 99 | const struct drm_display_mode *mode, |
| 100 | struct drm_display_mode *adjusted_mode); | 100 | struct drm_display_mode *adjusted_mode); |
| 101 | void (*prepare)(struct drm_encoder *encoder); | 101 | void (*prepare)(struct drm_encoder *encoder); |
| 102 | void (*commit)(struct drm_encoder *encoder); | 102 | void (*commit)(struct drm_encoder *encoder); |
diff --git a/include/drm/drm_encoder_slave.h b/include/drm/drm_encoder_slave.h index 2f65633d28a7..7dc385233805 100644 --- a/include/drm/drm_encoder_slave.h +++ b/include/drm/drm_encoder_slave.h | |||
| @@ -54,7 +54,7 @@ struct drm_encoder_slave_funcs { | |||
| 54 | void (*save)(struct drm_encoder *encoder); | 54 | void (*save)(struct drm_encoder *encoder); |
| 55 | void (*restore)(struct drm_encoder *encoder); | 55 | void (*restore)(struct drm_encoder *encoder); |
| 56 | bool (*mode_fixup)(struct drm_encoder *encoder, | 56 | bool (*mode_fixup)(struct drm_encoder *encoder, |
| 57 | struct drm_display_mode *mode, | 57 | const struct drm_display_mode *mode, |
| 58 | struct drm_display_mode *adjusted_mode); | 58 | struct drm_display_mode *adjusted_mode); |
| 59 | int (*mode_valid)(struct drm_encoder *encoder, | 59 | int (*mode_valid)(struct drm_encoder *encoder, |
| 60 | struct drm_display_mode *mode); | 60 | struct drm_display_mode *mode); |
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 564b14aa7e16..06d7f798a08c 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h | |||
| @@ -50,6 +50,7 @@ struct drm_mm_node { | |||
| 50 | unsigned scanned_next_free : 1; | 50 | unsigned scanned_next_free : 1; |
| 51 | unsigned scanned_preceeds_hole : 1; | 51 | unsigned scanned_preceeds_hole : 1; |
| 52 | unsigned allocated : 1; | 52 | unsigned allocated : 1; |
| 53 | unsigned long color; | ||
| 53 | unsigned long start; | 54 | unsigned long start; |
| 54 | unsigned long size; | 55 | unsigned long size; |
| 55 | struct drm_mm *mm; | 56 | struct drm_mm *mm; |
| @@ -66,6 +67,7 @@ struct drm_mm { | |||
| 66 | spinlock_t unused_lock; | 67 | spinlock_t unused_lock; |
| 67 | unsigned int scan_check_range : 1; | 68 | unsigned int scan_check_range : 1; |
| 68 | unsigned scan_alignment; | 69 | unsigned scan_alignment; |
| 70 | unsigned long scan_color; | ||
| 69 | unsigned long scan_size; | 71 | unsigned long scan_size; |
| 70 | unsigned long scan_hit_start; | 72 | unsigned long scan_hit_start; |
| 71 | unsigned scan_hit_size; | 73 | unsigned scan_hit_size; |
| @@ -73,6 +75,9 @@ struct drm_mm { | |||
| 73 | unsigned long scan_start; | 75 | unsigned long scan_start; |
| 74 | unsigned long scan_end; | 76 | unsigned long scan_end; |
| 75 | struct drm_mm_node *prev_scanned_node; | 77 | struct drm_mm_node *prev_scanned_node; |
| 78 | |||
| 79 | void (*color_adjust)(struct drm_mm_node *node, unsigned long color, | ||
| 80 | unsigned long *start, unsigned long *end); | ||
| 76 | }; | 81 | }; |
| 77 | 82 | ||
| 78 | static inline bool drm_mm_node_allocated(struct drm_mm_node *node) | 83 | static inline bool drm_mm_node_allocated(struct drm_mm_node *node) |
| @@ -100,11 +105,13 @@ static inline bool drm_mm_initialized(struct drm_mm *mm) | |||
| 100 | extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, | 105 | extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, |
| 101 | unsigned long size, | 106 | unsigned long size, |
| 102 | unsigned alignment, | 107 | unsigned alignment, |
| 108 | unsigned long color, | ||
| 103 | int atomic); | 109 | int atomic); |
| 104 | extern struct drm_mm_node *drm_mm_get_block_range_generic( | 110 | extern struct drm_mm_node *drm_mm_get_block_range_generic( |
| 105 | struct drm_mm_node *node, | 111 | struct drm_mm_node *node, |
| 106 | unsigned long size, | 112 | unsigned long size, |
| 107 | unsigned alignment, | 113 | unsigned alignment, |
| 114 | unsigned long color, | ||
| 108 | unsigned long start, | 115 | unsigned long start, |
| 109 | unsigned long end, | 116 | unsigned long end, |
| 110 | int atomic); | 117 | int atomic); |
| @@ -112,13 +119,13 @@ static inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent, | |||
| 112 | unsigned long size, | 119 | unsigned long size, |
| 113 | unsigned alignment) | 120 | unsigned alignment) |
| 114 | { | 121 | { |
| 115 | return drm_mm_get_block_generic(parent, size, alignment, 0); | 122 | return drm_mm_get_block_generic(parent, size, alignment, 0, 0); |
| 116 | } | 123 | } |
| 117 | static inline struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *parent, | 124 | static inline struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *parent, |
| 118 | unsigned long size, | 125 | unsigned long size, |
| 119 | unsigned alignment) | 126 | unsigned alignment) |
| 120 | { | 127 | { |
| 121 | return drm_mm_get_block_generic(parent, size, alignment, 1); | 128 | return drm_mm_get_block_generic(parent, size, alignment, 0, 1); |
| 122 | } | 129 | } |
| 123 | static inline struct drm_mm_node *drm_mm_get_block_range( | 130 | static inline struct drm_mm_node *drm_mm_get_block_range( |
| 124 | struct drm_mm_node *parent, | 131 | struct drm_mm_node *parent, |
| @@ -127,8 +134,19 @@ static inline struct drm_mm_node *drm_mm_get_block_range( | |||
| 127 | unsigned long start, | 134 | unsigned long start, |
| 128 | unsigned long end) | 135 | unsigned long end) |
| 129 | { | 136 | { |
| 130 | return drm_mm_get_block_range_generic(parent, size, alignment, | 137 | return drm_mm_get_block_range_generic(parent, size, alignment, 0, |
| 131 | start, end, 0); | 138 | start, end, 0); |
| 139 | } | ||
| 140 | static inline struct drm_mm_node *drm_mm_get_color_block_range( | ||
| 141 | struct drm_mm_node *parent, | ||
| 142 | unsigned long size, | ||
| 143 | unsigned alignment, | ||
| 144 | unsigned long color, | ||
| 145 | unsigned long start, | ||
| 146 | unsigned long end) | ||
| 147 | { | ||
| 148 | return drm_mm_get_block_range_generic(parent, size, alignment, color, | ||
| 149 | start, end, 0); | ||
| 132 | } | 150 | } |
| 133 | static inline struct drm_mm_node *drm_mm_get_block_atomic_range( | 151 | static inline struct drm_mm_node *drm_mm_get_block_atomic_range( |
| 134 | struct drm_mm_node *parent, | 152 | struct drm_mm_node *parent, |
| @@ -137,7 +155,7 @@ static inline struct drm_mm_node *drm_mm_get_block_atomic_range( | |||
| 137 | unsigned long start, | 155 | unsigned long start, |
| 138 | unsigned long end) | 156 | unsigned long end) |
| 139 | { | 157 | { |
| 140 | return drm_mm_get_block_range_generic(parent, size, alignment, | 158 | return drm_mm_get_block_range_generic(parent, size, alignment, 0, |
| 141 | start, end, 1); | 159 | start, end, 1); |
| 142 | } | 160 | } |
| 143 | extern int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, | 161 | extern int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, |
| @@ -149,18 +167,59 @@ extern int drm_mm_insert_node_in_range(struct drm_mm *mm, | |||
| 149 | extern void drm_mm_put_block(struct drm_mm_node *cur); | 167 | extern void drm_mm_put_block(struct drm_mm_node *cur); |
| 150 | extern void drm_mm_remove_node(struct drm_mm_node *node); | 168 | extern void drm_mm_remove_node(struct drm_mm_node *node); |
| 151 | extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new); | 169 | extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new); |
| 152 | extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, | 170 | extern struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, |
| 153 | unsigned long size, | 171 | unsigned long size, |
| 154 | unsigned alignment, | 172 | unsigned alignment, |
| 155 | int best_match); | 173 | unsigned long color, |
| 156 | extern struct drm_mm_node *drm_mm_search_free_in_range( | 174 | bool best_match); |
| 175 | extern struct drm_mm_node *drm_mm_search_free_in_range_generic( | ||
| 176 | const struct drm_mm *mm, | ||
| 177 | unsigned long size, | ||
| 178 | unsigned alignment, | ||
| 179 | unsigned long color, | ||
| 180 | unsigned long start, | ||
| 181 | unsigned long end, | ||
| 182 | bool best_match); | ||
| 183 | static inline struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, | ||
| 184 | unsigned long size, | ||
| 185 | unsigned alignment, | ||
| 186 | bool best_match) | ||
| 187 | { | ||
| 188 | return drm_mm_search_free_generic(mm,size, alignment, 0, best_match); | ||
| 189 | } | ||
| 190 | static inline struct drm_mm_node *drm_mm_search_free_in_range( | ||
| 157 | const struct drm_mm *mm, | 191 | const struct drm_mm *mm, |
| 158 | unsigned long size, | 192 | unsigned long size, |
| 159 | unsigned alignment, | 193 | unsigned alignment, |
| 160 | unsigned long start, | 194 | unsigned long start, |
| 161 | unsigned long end, | 195 | unsigned long end, |
| 162 | int best_match); | 196 | bool best_match) |
| 163 | extern int drm_mm_init(struct drm_mm *mm, unsigned long start, | 197 | { |
| 198 | return drm_mm_search_free_in_range_generic(mm, size, alignment, 0, | ||
| 199 | start, end, best_match); | ||
| 200 | } | ||
| 201 | static inline struct drm_mm_node *drm_mm_search_free_color(const struct drm_mm *mm, | ||
| 202 | unsigned long size, | ||
| 203 | unsigned alignment, | ||
| 204 | unsigned long color, | ||
| 205 | bool best_match) | ||
| 206 | { | ||
| 207 | return drm_mm_search_free_generic(mm,size, alignment, color, best_match); | ||
| 208 | } | ||
| 209 | static inline struct drm_mm_node *drm_mm_search_free_in_range_color( | ||
| 210 | const struct drm_mm *mm, | ||
| 211 | unsigned long size, | ||
| 212 | unsigned alignment, | ||
| 213 | unsigned long color, | ||
| 214 | unsigned long start, | ||
| 215 | unsigned long end, | ||
| 216 | bool best_match) | ||
| 217 | { | ||
| 218 | return drm_mm_search_free_in_range_generic(mm, size, alignment, color, | ||
| 219 | start, end, best_match); | ||
| 220 | } | ||
| 221 | extern int drm_mm_init(struct drm_mm *mm, | ||
| 222 | unsigned long start, | ||
| 164 | unsigned long size); | 223 | unsigned long size); |
| 165 | extern void drm_mm_takedown(struct drm_mm *mm); | 224 | extern void drm_mm_takedown(struct drm_mm *mm); |
| 166 | extern int drm_mm_clean(struct drm_mm *mm); | 225 | extern int drm_mm_clean(struct drm_mm *mm); |
| @@ -171,10 +230,14 @@ static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block) | |||
| 171 | return block->mm; | 230 | return block->mm; |
| 172 | } | 231 | } |
| 173 | 232 | ||
| 174 | void drm_mm_init_scan(struct drm_mm *mm, unsigned long size, | 233 | void drm_mm_init_scan(struct drm_mm *mm, |
| 175 | unsigned alignment); | 234 | unsigned long size, |
| 176 | void drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size, | 235 | unsigned alignment, |
| 236 | unsigned long color); | ||
| 237 | void drm_mm_init_scan_with_range(struct drm_mm *mm, | ||
| 238 | unsigned long size, | ||
| 177 | unsigned alignment, | 239 | unsigned alignment, |
| 240 | unsigned long color, | ||
| 178 | unsigned long start, | 241 | unsigned long start, |
| 179 | unsigned long end); | 242 | unsigned long end); |
| 180 | int drm_mm_scan_add_block(struct drm_mm_node *node); | 243 | int drm_mm_scan_add_block(struct drm_mm_node *node); |
diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index a7aec391b7b7..7ff5c99b1638 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h | |||
| @@ -686,14 +686,6 @@ | |||
| 686 | {0x8086, 0x1132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 686 | {0x8086, 0x1132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
| 687 | {0, 0, 0} | 687 | {0, 0, 0} |
| 688 | 688 | ||
| 689 | #define i830_PCI_IDS \ | ||
| 690 | {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 691 | {0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 692 | {0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 693 | {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 694 | {0x8086, 0x358e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 695 | {0, 0, 0} | ||
| 696 | |||
| 697 | #define gamma_PCI_IDS \ | 689 | #define gamma_PCI_IDS \ |
| 698 | {0x3d3d, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 690 | {0x3d3d, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
| 699 | {0, 0, 0} | 691 | {0, 0, 0} |
| @@ -726,37 +718,3 @@ | |||
| 726 | 718 | ||
| 727 | #define ffb_PCI_IDS \ | 719 | #define ffb_PCI_IDS \ |
| 728 | {0, 0, 0} | 720 | {0, 0, 0} |
| 729 | |||
| 730 | #define i915_PCI_IDS \ | ||
| 731 | {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 732 | {0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 733 | {0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 734 | {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 735 | {0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 736 | {0x8086, 0x258a, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 737 | {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 738 | {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 739 | {0x8086, 0x27a2, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 740 | {0x8086, 0x27ae, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 741 | {0x8086, 0x2972, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 742 | {0x8086, 0x2982, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 743 | {0x8086, 0x2992, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 744 | {0x8086, 0x29a2, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 745 | {0x8086, 0x29b2, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 746 | {0x8086, 0x29c2, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 747 | {0x8086, 0x29d2, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 748 | {0x8086, 0x2a02, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 749 | {0x8086, 0x2a12, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 750 | {0x8086, 0x2a42, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 751 | {0x8086, 0x2e02, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 752 | {0x8086, 0x2e12, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 753 | {0x8086, 0x2e22, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 754 | {0x8086, 0x2e32, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 755 | {0x8086, 0x2e42, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 756 | {0x8086, 0xa001, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 757 | {0x8086, 0xa011, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 758 | {0x8086, 0x35e8, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 759 | {0x8086, 0x0042, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 760 | {0x8086, 0x0046, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 761 | {0x8086, 0x0102, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ | ||
| 762 | {0, 0, 0} | ||
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index f3f82242bf1d..8cc70837f929 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h | |||
| @@ -200,6 +200,9 @@ typedef struct _drm_i915_sarea { | |||
| 200 | #define DRM_I915_GEM_EXECBUFFER2 0x29 | 200 | #define DRM_I915_GEM_EXECBUFFER2 0x29 |
| 201 | #define DRM_I915_GET_SPRITE_COLORKEY 0x2a | 201 | #define DRM_I915_GET_SPRITE_COLORKEY 0x2a |
| 202 | #define DRM_I915_SET_SPRITE_COLORKEY 0x2b | 202 | #define DRM_I915_SET_SPRITE_COLORKEY 0x2b |
| 203 | #define DRM_I915_GEM_WAIT 0x2c | ||
| 204 | #define DRM_I915_GEM_CONTEXT_CREATE 0x2d | ||
| 205 | #define DRM_I915_GEM_CONTEXT_DESTROY 0x2e | ||
| 203 | 206 | ||
| 204 | #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) | 207 | #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) |
| 205 | #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) | 208 | #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) |
| @@ -243,6 +246,9 @@ typedef struct _drm_i915_sarea { | |||
| 243 | #define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs) | 246 | #define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs) |
| 244 | #define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) | 247 | #define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) |
| 245 | #define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) | 248 | #define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) |
| 249 | #define DRM_IOCTL_I915_GEM_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait) | ||
| 250 | #define DRM_IOCTL_I915_GEM_CONTEXT_CREATE DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create) | ||
| 251 | #define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy) | ||
| 246 | 252 | ||
| 247 | /* Allow drivers to submit batchbuffers directly to hardware, relying | 253 | /* Allow drivers to submit batchbuffers directly to hardware, relying |
| 248 | * on the security mechanisms provided by hardware. | 254 | * on the security mechanisms provided by hardware. |
| @@ -298,6 +304,7 @@ typedef struct drm_i915_irq_wait { | |||
| 298 | #define I915_PARAM_HAS_GEN7_SOL_RESET 16 | 304 | #define I915_PARAM_HAS_GEN7_SOL_RESET 16 |
| 299 | #define I915_PARAM_HAS_LLC 17 | 305 | #define I915_PARAM_HAS_LLC 17 |
| 300 | #define I915_PARAM_HAS_ALIASING_PPGTT 18 | 306 | #define I915_PARAM_HAS_ALIASING_PPGTT 18 |
| 307 | #define I915_PARAM_HAS_WAIT_TIMEOUT 19 | ||
| 301 | 308 | ||
| 302 | typedef struct drm_i915_getparam { | 309 | typedef struct drm_i915_getparam { |
| 303 | int param; | 310 | int param; |
| @@ -656,13 +663,19 @@ struct drm_i915_gem_execbuffer2 { | |||
| 656 | #define I915_EXEC_CONSTANTS_ABSOLUTE (1<<6) | 663 | #define I915_EXEC_CONSTANTS_ABSOLUTE (1<<6) |
| 657 | #define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */ | 664 | #define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */ |
| 658 | __u64 flags; | 665 | __u64 flags; |
| 659 | __u64 rsvd1; | 666 | __u64 rsvd1; /* now used for context info */ |
| 660 | __u64 rsvd2; | 667 | __u64 rsvd2; |
| 661 | }; | 668 | }; |
| 662 | 669 | ||
| 663 | /** Resets the SO write offset registers for transform feedback on gen7. */ | 670 | /** Resets the SO write offset registers for transform feedback on gen7. */ |
| 664 | #define I915_EXEC_GEN7_SOL_RESET (1<<8) | 671 | #define I915_EXEC_GEN7_SOL_RESET (1<<8) |
| 665 | 672 | ||
| 673 | #define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) | ||
| 674 | #define i915_execbuffer2_set_context_id(eb2, context) \ | ||
| 675 | (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK | ||
| 676 | #define i915_execbuffer2_get_context_id(eb2) \ | ||
| 677 | ((eb2).rsvd1 & I915_EXEC_CONTEXT_ID_MASK) | ||
| 678 | |||
| 666 | struct drm_i915_gem_pin { | 679 | struct drm_i915_gem_pin { |
| 667 | /** Handle of the buffer to be pinned. */ | 680 | /** Handle of the buffer to be pinned. */ |
| 668 | __u32 handle; | 681 | __u32 handle; |
| @@ -886,4 +899,23 @@ struct drm_intel_sprite_colorkey { | |||
| 886 | __u32 flags; | 899 | __u32 flags; |
| 887 | }; | 900 | }; |
| 888 | 901 | ||
| 902 | struct drm_i915_gem_wait { | ||
| 903 | /** Handle of BO we shall wait on */ | ||
| 904 | __u32 bo_handle; | ||
| 905 | __u32 flags; | ||
| 906 | /** Number of nanoseconds to wait, Returns time remaining. */ | ||
| 907 | __s64 timeout_ns; | ||
| 908 | }; | ||
| 909 | |||
| 910 | struct drm_i915_gem_context_create { | ||
| 911 | /* output: id of new context*/ | ||
| 912 | __u32 ctx_id; | ||
| 913 | __u32 pad; | ||
| 914 | }; | ||
| 915 | |||
| 916 | struct drm_i915_gem_context_destroy { | ||
| 917 | __u32 ctx_id; | ||
| 918 | __u32 pad; | ||
| 919 | }; | ||
| 920 | |||
| 889 | #endif /* _I915_DRM_H_ */ | 921 | #endif /* _I915_DRM_H_ */ |
diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 923afb5dcf0c..8e29d551bb3c 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h | |||
| @@ -19,8 +19,16 @@ const struct intel_gtt { | |||
| 19 | dma_addr_t scratch_page_dma; | 19 | dma_addr_t scratch_page_dma; |
| 20 | /* for ppgtt PDE access */ | 20 | /* for ppgtt PDE access */ |
| 21 | u32 __iomem *gtt; | 21 | u32 __iomem *gtt; |
| 22 | /* needed for ioremap in drm/i915 */ | ||
| 23 | phys_addr_t gma_bus_addr; | ||
| 22 | } *intel_gtt_get(void); | 24 | } *intel_gtt_get(void); |
| 23 | 25 | ||
| 26 | int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, | ||
| 27 | struct agp_bridge_data *bridge); | ||
| 28 | void intel_gmch_remove(void); | ||
| 29 | |||
| 30 | bool intel_enable_gtt(void); | ||
| 31 | |||
| 24 | void intel_gtt_chipset_flush(void); | 32 | void intel_gtt_chipset_flush(void); |
| 25 | void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg); | 33 | void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg); |
| 26 | void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries); | 34 | void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries); |
diff --git a/include/drm/sis_drm.h b/include/drm/sis_drm.h index 035b804dda6d..df3763222d73 100644 --- a/include/drm/sis_drm.h +++ b/include/drm/sis_drm.h | |||
| @@ -51,17 +51,17 @@ | |||
| 51 | 51 | ||
| 52 | typedef struct { | 52 | typedef struct { |
| 53 | int context; | 53 | int context; |
| 54 | unsigned int offset; | 54 | unsigned long offset; |
| 55 | unsigned int size; | 55 | unsigned long size; |
| 56 | unsigned long free; | 56 | unsigned long free; |
| 57 | } drm_sis_mem_t; | 57 | } drm_sis_mem_t; |
| 58 | 58 | ||
| 59 | typedef struct { | 59 | typedef struct { |
| 60 | unsigned int offset, size; | 60 | unsigned long offset, size; |
| 61 | } drm_sis_agp_t; | 61 | } drm_sis_agp_t; |
| 62 | 62 | ||
| 63 | typedef struct { | 63 | typedef struct { |
| 64 | unsigned int offset, size; | 64 | unsigned long offset, size; |
| 65 | } drm_sis_fb_t; | 65 | } drm_sis_fb_t; |
| 66 | 66 | ||
| 67 | struct sis_file_private { | 67 | struct sis_file_private { |
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index a05f1b55714d..084e8989a6e1 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h | |||
| @@ -39,8 +39,6 @@ | |||
| 39 | #include "linux/fs.h" | 39 | #include "linux/fs.h" |
| 40 | #include "linux/spinlock.h" | 40 | #include "linux/spinlock.h" |
| 41 | 41 | ||
| 42 | struct ttm_backend; | ||
| 43 | |||
| 44 | struct ttm_backend_func { | 42 | struct ttm_backend_func { |
| 45 | /** | 43 | /** |
| 46 | * struct ttm_backend_func member bind | 44 | * struct ttm_backend_func member bind |
| @@ -119,7 +117,6 @@ struct ttm_tt { | |||
| 119 | unsigned long num_pages; | 117 | unsigned long num_pages; |
| 120 | struct sg_table *sg; /* for SG objects via dma-buf */ | 118 | struct sg_table *sg; /* for SG objects via dma-buf */ |
| 121 | struct ttm_bo_global *glob; | 119 | struct ttm_bo_global *glob; |
| 122 | struct ttm_backend *be; | ||
| 123 | struct file *swap_storage; | 120 | struct file *swap_storage; |
| 124 | enum ttm_caching_state caching_state; | 121 | enum ttm_caching_state caching_state; |
| 125 | enum { | 122 | enum { |
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index fd0dc30c9f15..cc07d2777bbe 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h | |||
| @@ -165,6 +165,7 @@ enum hrtimer_base_type { | |||
| 165 | * @lock: lock protecting the base and associated clock bases | 165 | * @lock: lock protecting the base and associated clock bases |
| 166 | * and timers | 166 | * and timers |
| 167 | * @active_bases: Bitfield to mark bases with active timers | 167 | * @active_bases: Bitfield to mark bases with active timers |
| 168 | * @clock_was_set: Indicates that clock was set from irq context. | ||
| 168 | * @expires_next: absolute time of the next event which was scheduled | 169 | * @expires_next: absolute time of the next event which was scheduled |
| 169 | * via clock_set_next_event() | 170 | * via clock_set_next_event() |
| 170 | * @hres_active: State of high resolution mode | 171 | * @hres_active: State of high resolution mode |
| @@ -177,7 +178,8 @@ enum hrtimer_base_type { | |||
| 177 | */ | 178 | */ |
| 178 | struct hrtimer_cpu_base { | 179 | struct hrtimer_cpu_base { |
| 179 | raw_spinlock_t lock; | 180 | raw_spinlock_t lock; |
| 180 | unsigned long active_bases; | 181 | unsigned int active_bases; |
| 182 | unsigned int clock_was_set; | ||
| 181 | #ifdef CONFIG_HIGH_RES_TIMERS | 183 | #ifdef CONFIG_HIGH_RES_TIMERS |
| 182 | ktime_t expires_next; | 184 | ktime_t expires_next; |
| 183 | int hres_active; | 185 | int hres_active; |
| @@ -286,6 +288,8 @@ extern void hrtimer_peek_ahead_timers(void); | |||
| 286 | # define MONOTONIC_RES_NSEC HIGH_RES_NSEC | 288 | # define MONOTONIC_RES_NSEC HIGH_RES_NSEC |
| 287 | # define KTIME_MONOTONIC_RES KTIME_HIGH_RES | 289 | # define KTIME_MONOTONIC_RES KTIME_HIGH_RES |
| 288 | 290 | ||
| 291 | extern void clock_was_set_delayed(void); | ||
| 292 | |||
| 289 | #else | 293 | #else |
| 290 | 294 | ||
| 291 | # define MONOTONIC_RES_NSEC LOW_RES_NSEC | 295 | # define MONOTONIC_RES_NSEC LOW_RES_NSEC |
| @@ -306,6 +310,9 @@ static inline int hrtimer_is_hres_active(struct hrtimer *timer) | |||
| 306 | { | 310 | { |
| 307 | return 0; | 311 | return 0; |
| 308 | } | 312 | } |
| 313 | |||
| 314 | static inline void clock_was_set_delayed(void) { } | ||
| 315 | |||
| 309 | #endif | 316 | #endif |
| 310 | 317 | ||
| 311 | extern void clock_was_set(void); | 318 | extern void clock_was_set(void); |
| @@ -320,6 +327,7 @@ extern ktime_t ktime_get(void); | |||
| 320 | extern ktime_t ktime_get_real(void); | 327 | extern ktime_t ktime_get_real(void); |
| 321 | extern ktime_t ktime_get_boottime(void); | 328 | extern ktime_t ktime_get_boottime(void); |
| 322 | extern ktime_t ktime_get_monotonic_offset(void); | 329 | extern ktime_t ktime_get_monotonic_offset(void); |
| 330 | extern ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot); | ||
| 323 | 331 | ||
| 324 | DECLARE_PER_CPU(struct tick_device, tick_cpu_device); | 332 | DECLARE_PER_CPU(struct tick_device, tick_cpu_device); |
| 325 | 333 | ||
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index 4b608f543412..7f04132eb02d 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h | |||
| @@ -521,6 +521,11 @@ | |||
| 521 | #define PCI_EXP_OBFF_MSGA_EN 0x2000 /* OBFF enable with Message type A */ | 521 | #define PCI_EXP_OBFF_MSGA_EN 0x2000 /* OBFF enable with Message type A */ |
| 522 | #define PCI_EXP_OBFF_MSGB_EN 0x4000 /* OBFF enable with Message type B */ | 522 | #define PCI_EXP_OBFF_MSGB_EN 0x4000 /* OBFF enable with Message type B */ |
| 523 | #define PCI_EXP_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */ | 523 | #define PCI_EXP_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */ |
| 524 | #define PCI_EXP_LNKCAP2 44 /* Link Capability 2 */ | ||
| 525 | #define PCI_EXP_LNKCAP2_SLS_2_5GB 0x01 /* Current Link Speed 2.5GT/s */ | ||
| 526 | #define PCI_EXP_LNKCAP2_SLS_5_0GB 0x02 /* Current Link Speed 5.0GT/s */ | ||
| 527 | #define PCI_EXP_LNKCAP2_SLS_8_0GB 0x04 /* Current Link Speed 8.0GT/s */ | ||
| 528 | #define PCI_EXP_LNKCAP2_CROSSLINK 0x100 /* Crosslink supported */ | ||
| 524 | #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ | 529 | #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ |
| 525 | #define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */ | 530 | #define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */ |
| 526 | 531 | ||
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 26d1a47591f1..9cac722b169c 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
| @@ -184,7 +184,6 @@ static inline int rcu_preempt_depth(void) | |||
| 184 | /* Internal to kernel */ | 184 | /* Internal to kernel */ |
| 185 | extern void rcu_sched_qs(int cpu); | 185 | extern void rcu_sched_qs(int cpu); |
| 186 | extern void rcu_bh_qs(int cpu); | 186 | extern void rcu_bh_qs(int cpu); |
| 187 | extern void rcu_preempt_note_context_switch(void); | ||
| 188 | extern void rcu_check_callbacks(int cpu, int user); | 187 | extern void rcu_check_callbacks(int cpu, int user); |
| 189 | struct notifier_block; | 188 | struct notifier_block; |
| 190 | extern void rcu_idle_enter(void); | 189 | extern void rcu_idle_enter(void); |
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h index 854dc4c5c271..4e56a9c69a35 100644 --- a/include/linux/rcutiny.h +++ b/include/linux/rcutiny.h | |||
| @@ -87,6 +87,10 @@ static inline void kfree_call_rcu(struct rcu_head *head, | |||
| 87 | 87 | ||
| 88 | #ifdef CONFIG_TINY_RCU | 88 | #ifdef CONFIG_TINY_RCU |
| 89 | 89 | ||
| 90 | static inline void rcu_preempt_note_context_switch(void) | ||
| 91 | { | ||
| 92 | } | ||
| 93 | |||
| 90 | static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) | 94 | static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) |
| 91 | { | 95 | { |
| 92 | *delta_jiffies = ULONG_MAX; | 96 | *delta_jiffies = ULONG_MAX; |
| @@ -95,6 +99,7 @@ static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) | |||
| 95 | 99 | ||
| 96 | #else /* #ifdef CONFIG_TINY_RCU */ | 100 | #else /* #ifdef CONFIG_TINY_RCU */ |
| 97 | 101 | ||
| 102 | void rcu_preempt_note_context_switch(void); | ||
| 98 | int rcu_preempt_needs_cpu(void); | 103 | int rcu_preempt_needs_cpu(void); |
| 99 | 104 | ||
| 100 | static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) | 105 | static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) |
| @@ -108,6 +113,7 @@ static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) | |||
| 108 | static inline void rcu_note_context_switch(int cpu) | 113 | static inline void rcu_note_context_switch(int cpu) |
| 109 | { | 114 | { |
| 110 | rcu_sched_qs(cpu); | 115 | rcu_sched_qs(cpu); |
| 116 | rcu_preempt_note_context_switch(); | ||
| 111 | } | 117 | } |
| 112 | 118 | ||
| 113 | /* | 119 | /* |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 4059c0f33f07..4a1f493e0fef 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -1871,22 +1871,12 @@ static inline void rcu_copy_process(struct task_struct *p) | |||
| 1871 | INIT_LIST_HEAD(&p->rcu_node_entry); | 1871 | INIT_LIST_HEAD(&p->rcu_node_entry); |
| 1872 | } | 1872 | } |
| 1873 | 1873 | ||
| 1874 | static inline void rcu_switch_from(struct task_struct *prev) | ||
| 1875 | { | ||
| 1876 | if (prev->rcu_read_lock_nesting != 0) | ||
| 1877 | rcu_preempt_note_context_switch(); | ||
| 1878 | } | ||
| 1879 | |||
| 1880 | #else | 1874 | #else |
| 1881 | 1875 | ||
| 1882 | static inline void rcu_copy_process(struct task_struct *p) | 1876 | static inline void rcu_copy_process(struct task_struct *p) |
| 1883 | { | 1877 | { |
| 1884 | } | 1878 | } |
| 1885 | 1879 | ||
| 1886 | static inline void rcu_switch_from(struct task_struct *prev) | ||
| 1887 | { | ||
| 1888 | } | ||
| 1889 | |||
| 1890 | #endif | 1880 | #endif |
| 1891 | 1881 | ||
| 1892 | #ifdef CONFIG_SMP | 1882 | #ifdef CONFIG_SMP |
| @@ -1909,6 +1899,14 @@ static inline int set_cpus_allowed_ptr(struct task_struct *p, | |||
| 1909 | } | 1899 | } |
| 1910 | #endif | 1900 | #endif |
| 1911 | 1901 | ||
| 1902 | #ifdef CONFIG_NO_HZ | ||
| 1903 | void calc_load_enter_idle(void); | ||
| 1904 | void calc_load_exit_idle(void); | ||
| 1905 | #else | ||
| 1906 | static inline void calc_load_enter_idle(void) { } | ||
| 1907 | static inline void calc_load_exit_idle(void) { } | ||
| 1908 | #endif /* CONFIG_NO_HZ */ | ||
| 1909 | |||
| 1912 | #ifndef CONFIG_CPUMASK_OFFSTACK | 1910 | #ifndef CONFIG_CPUMASK_OFFSTACK |
| 1913 | static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask) | 1911 | static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask) |
| 1914 | { | 1912 | { |
diff --git a/kernel/fork.c b/kernel/fork.c index ab5211b9e622..f00e319d8376 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -304,12 +304,17 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) | |||
| 304 | } | 304 | } |
| 305 | 305 | ||
| 306 | err = arch_dup_task_struct(tsk, orig); | 306 | err = arch_dup_task_struct(tsk, orig); |
| 307 | if (err) | ||
| 308 | goto out; | ||
| 309 | 307 | ||
| 308 | /* | ||
| 309 | * We defer looking at err, because we will need this setup | ||
| 310 | * for the clean up path to work correctly. | ||
| 311 | */ | ||
| 310 | tsk->stack = ti; | 312 | tsk->stack = ti; |
| 311 | |||
| 312 | setup_thread_stack(tsk, orig); | 313 | setup_thread_stack(tsk, orig); |
| 314 | |||
| 315 | if (err) | ||
| 316 | goto out; | ||
| 317 | |||
| 313 | clear_user_return_notifier(tsk); | 318 | clear_user_return_notifier(tsk); |
| 314 | clear_tsk_need_resched(tsk); | 319 | clear_tsk_need_resched(tsk); |
| 315 | stackend = end_of_stack(tsk); | 320 | stackend = end_of_stack(tsk); |
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index ae34bf51682b..6db7a5ed52b5 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
| @@ -657,6 +657,14 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, | |||
| 657 | return 0; | 657 | return 0; |
| 658 | } | 658 | } |
| 659 | 659 | ||
| 660 | static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base) | ||
| 661 | { | ||
| 662 | ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset; | ||
| 663 | ktime_t *offs_boot = &base->clock_base[HRTIMER_BASE_BOOTTIME].offset; | ||
| 664 | |||
| 665 | return ktime_get_update_offsets(offs_real, offs_boot); | ||
| 666 | } | ||
| 667 | |||
| 660 | /* | 668 | /* |
| 661 | * Retrigger next event is called after clock was set | 669 | * Retrigger next event is called after clock was set |
| 662 | * | 670 | * |
| @@ -665,22 +673,12 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, | |||
| 665 | static void retrigger_next_event(void *arg) | 673 | static void retrigger_next_event(void *arg) |
| 666 | { | 674 | { |
| 667 | struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases); | 675 | struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases); |
| 668 | struct timespec realtime_offset, xtim, wtm, sleep; | ||
| 669 | 676 | ||
| 670 | if (!hrtimer_hres_active()) | 677 | if (!hrtimer_hres_active()) |
| 671 | return; | 678 | return; |
| 672 | 679 | ||
| 673 | /* Optimized out for !HIGH_RES */ | ||
| 674 | get_xtime_and_monotonic_and_sleep_offset(&xtim, &wtm, &sleep); | ||
| 675 | set_normalized_timespec(&realtime_offset, -wtm.tv_sec, -wtm.tv_nsec); | ||
| 676 | |||
| 677 | /* Adjust CLOCK_REALTIME offset */ | ||
| 678 | raw_spin_lock(&base->lock); | 680 | raw_spin_lock(&base->lock); |
| 679 | base->clock_base[HRTIMER_BASE_REALTIME].offset = | 681 | hrtimer_update_base(base); |
| 680 | timespec_to_ktime(realtime_offset); | ||
| 681 | base->clock_base[HRTIMER_BASE_BOOTTIME].offset = | ||
| 682 | timespec_to_ktime(sleep); | ||
| 683 | |||
| 684 | hrtimer_force_reprogram(base, 0); | 682 | hrtimer_force_reprogram(base, 0); |
| 685 | raw_spin_unlock(&base->lock); | 683 | raw_spin_unlock(&base->lock); |
| 686 | } | 684 | } |
| @@ -710,13 +708,25 @@ static int hrtimer_switch_to_hres(void) | |||
| 710 | base->clock_base[i].resolution = KTIME_HIGH_RES; | 708 | base->clock_base[i].resolution = KTIME_HIGH_RES; |
| 711 | 709 | ||
| 712 | tick_setup_sched_timer(); | 710 | tick_setup_sched_timer(); |
| 713 | |||
| 714 | /* "Retrigger" the interrupt to get things going */ | 711 | /* "Retrigger" the interrupt to get things going */ |
| 715 | retrigger_next_event(NULL); | 712 | retrigger_next_event(NULL); |
| 716 | local_irq_restore(flags); | 713 | local_irq_restore(flags); |
| 717 | return 1; | 714 | return 1; |
| 718 | } | 715 | } |
| 719 | 716 | ||
| 717 | /* | ||
| 718 | * Called from timekeeping code to reprogramm the hrtimer interrupt | ||
| 719 | * device. If called from the timer interrupt context we defer it to | ||
| 720 | * softirq context. | ||
| 721 | */ | ||
| 722 | void clock_was_set_delayed(void) | ||
| 723 | { | ||
| 724 | struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); | ||
| 725 | |||
| 726 | cpu_base->clock_was_set = 1; | ||
| 727 | __raise_softirq_irqoff(HRTIMER_SOFTIRQ); | ||
| 728 | } | ||
| 729 | |||
| 720 | #else | 730 | #else |
| 721 | 731 | ||
| 722 | static inline int hrtimer_hres_active(void) { return 0; } | 732 | static inline int hrtimer_hres_active(void) { return 0; } |
| @@ -1250,11 +1260,10 @@ void hrtimer_interrupt(struct clock_event_device *dev) | |||
| 1250 | cpu_base->nr_events++; | 1260 | cpu_base->nr_events++; |
| 1251 | dev->next_event.tv64 = KTIME_MAX; | 1261 | dev->next_event.tv64 = KTIME_MAX; |
| 1252 | 1262 | ||
| 1253 | entry_time = now = ktime_get(); | 1263 | raw_spin_lock(&cpu_base->lock); |
| 1264 | entry_time = now = hrtimer_update_base(cpu_base); | ||
| 1254 | retry: | 1265 | retry: |
| 1255 | expires_next.tv64 = KTIME_MAX; | 1266 | expires_next.tv64 = KTIME_MAX; |
| 1256 | |||
| 1257 | raw_spin_lock(&cpu_base->lock); | ||
| 1258 | /* | 1267 | /* |
| 1259 | * We set expires_next to KTIME_MAX here with cpu_base->lock | 1268 | * We set expires_next to KTIME_MAX here with cpu_base->lock |
| 1260 | * held to prevent that a timer is enqueued in our queue via | 1269 | * held to prevent that a timer is enqueued in our queue via |
| @@ -1330,8 +1339,12 @@ retry: | |||
| 1330 | * We need to prevent that we loop forever in the hrtimer | 1339 | * We need to prevent that we loop forever in the hrtimer |
| 1331 | * interrupt routine. We give it 3 attempts to avoid | 1340 | * interrupt routine. We give it 3 attempts to avoid |
| 1332 | * overreacting on some spurious event. | 1341 | * overreacting on some spurious event. |
| 1342 | * | ||
| 1343 | * Acquire base lock for updating the offsets and retrieving | ||
| 1344 | * the current time. | ||
| 1333 | */ | 1345 | */ |
| 1334 | now = ktime_get(); | 1346 | raw_spin_lock(&cpu_base->lock); |
| 1347 | now = hrtimer_update_base(cpu_base); | ||
| 1335 | cpu_base->nr_retries++; | 1348 | cpu_base->nr_retries++; |
| 1336 | if (++retries < 3) | 1349 | if (++retries < 3) |
| 1337 | goto retry; | 1350 | goto retry; |
| @@ -1343,6 +1356,7 @@ retry: | |||
| 1343 | */ | 1356 | */ |
| 1344 | cpu_base->nr_hangs++; | 1357 | cpu_base->nr_hangs++; |
| 1345 | cpu_base->hang_detected = 1; | 1358 | cpu_base->hang_detected = 1; |
| 1359 | raw_spin_unlock(&cpu_base->lock); | ||
| 1346 | delta = ktime_sub(now, entry_time); | 1360 | delta = ktime_sub(now, entry_time); |
| 1347 | if (delta.tv64 > cpu_base->max_hang_time.tv64) | 1361 | if (delta.tv64 > cpu_base->max_hang_time.tv64) |
| 1348 | cpu_base->max_hang_time = delta; | 1362 | cpu_base->max_hang_time = delta; |
| @@ -1395,6 +1409,13 @@ void hrtimer_peek_ahead_timers(void) | |||
| 1395 | 1409 | ||
| 1396 | static void run_hrtimer_softirq(struct softirq_action *h) | 1410 | static void run_hrtimer_softirq(struct softirq_action *h) |
| 1397 | { | 1411 | { |
| 1412 | struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); | ||
| 1413 | |||
| 1414 | if (cpu_base->clock_was_set) { | ||
| 1415 | cpu_base->clock_was_set = 0; | ||
| 1416 | clock_was_set(); | ||
| 1417 | } | ||
| 1418 | |||
| 1398 | hrtimer_peek_ahead_timers(); | 1419 | hrtimer_peek_ahead_timers(); |
| 1399 | } | 1420 | } |
| 1400 | 1421 | ||
diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 38ecdda3f55f..4b97bba7396e 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c | |||
| @@ -201,6 +201,7 @@ void rcu_note_context_switch(int cpu) | |||
| 201 | { | 201 | { |
| 202 | trace_rcu_utilization("Start context switch"); | 202 | trace_rcu_utilization("Start context switch"); |
| 203 | rcu_sched_qs(cpu); | 203 | rcu_sched_qs(cpu); |
| 204 | rcu_preempt_note_context_switch(cpu); | ||
| 204 | trace_rcu_utilization("End context switch"); | 205 | trace_rcu_utilization("End context switch"); |
| 205 | } | 206 | } |
| 206 | EXPORT_SYMBOL_GPL(rcu_note_context_switch); | 207 | EXPORT_SYMBOL_GPL(rcu_note_context_switch); |
diff --git a/kernel/rcutree.h b/kernel/rcutree.h index ea056495783e..19b61ac1079f 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h | |||
| @@ -444,6 +444,7 @@ DECLARE_PER_CPU(char, rcu_cpu_has_work); | |||
| 444 | /* Forward declarations for rcutree_plugin.h */ | 444 | /* Forward declarations for rcutree_plugin.h */ |
| 445 | static void rcu_bootup_announce(void); | 445 | static void rcu_bootup_announce(void); |
| 446 | long rcu_batches_completed(void); | 446 | long rcu_batches_completed(void); |
| 447 | static void rcu_preempt_note_context_switch(int cpu); | ||
| 447 | static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp); | 448 | static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp); |
| 448 | #ifdef CONFIG_HOTPLUG_CPU | 449 | #ifdef CONFIG_HOTPLUG_CPU |
| 449 | static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, | 450 | static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, |
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 5271a020887e..3e4899459f3d 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h | |||
| @@ -153,7 +153,7 @@ static void rcu_preempt_qs(int cpu) | |||
| 153 | * | 153 | * |
| 154 | * Caller must disable preemption. | 154 | * Caller must disable preemption. |
| 155 | */ | 155 | */ |
| 156 | void rcu_preempt_note_context_switch(void) | 156 | static void rcu_preempt_note_context_switch(int cpu) |
| 157 | { | 157 | { |
| 158 | struct task_struct *t = current; | 158 | struct task_struct *t = current; |
| 159 | unsigned long flags; | 159 | unsigned long flags; |
| @@ -164,7 +164,7 @@ void rcu_preempt_note_context_switch(void) | |||
| 164 | (t->rcu_read_unlock_special & RCU_READ_UNLOCK_BLOCKED) == 0) { | 164 | (t->rcu_read_unlock_special & RCU_READ_UNLOCK_BLOCKED) == 0) { |
| 165 | 165 | ||
| 166 | /* Possibly blocking in an RCU read-side critical section. */ | 166 | /* Possibly blocking in an RCU read-side critical section. */ |
| 167 | rdp = __this_cpu_ptr(rcu_preempt_state.rda); | 167 | rdp = per_cpu_ptr(rcu_preempt_state.rda, cpu); |
| 168 | rnp = rdp->mynode; | 168 | rnp = rdp->mynode; |
| 169 | raw_spin_lock_irqsave(&rnp->lock, flags); | 169 | raw_spin_lock_irqsave(&rnp->lock, flags); |
| 170 | t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BLOCKED; | 170 | t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BLOCKED; |
| @@ -228,7 +228,7 @@ void rcu_preempt_note_context_switch(void) | |||
| 228 | * means that we continue to block the current grace period. | 228 | * means that we continue to block the current grace period. |
| 229 | */ | 229 | */ |
| 230 | local_irq_save(flags); | 230 | local_irq_save(flags); |
| 231 | rcu_preempt_qs(smp_processor_id()); | 231 | rcu_preempt_qs(cpu); |
| 232 | local_irq_restore(flags); | 232 | local_irq_restore(flags); |
| 233 | } | 233 | } |
| 234 | 234 | ||
| @@ -1002,6 +1002,14 @@ void rcu_force_quiescent_state(void) | |||
| 1002 | EXPORT_SYMBOL_GPL(rcu_force_quiescent_state); | 1002 | EXPORT_SYMBOL_GPL(rcu_force_quiescent_state); |
| 1003 | 1003 | ||
| 1004 | /* | 1004 | /* |
| 1005 | * Because preemptible RCU does not exist, we never have to check for | ||
| 1006 | * CPUs being in quiescent states. | ||
| 1007 | */ | ||
| 1008 | static void rcu_preempt_note_context_switch(int cpu) | ||
| 1009 | { | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | /* | ||
| 1005 | * Because preemptible RCU does not exist, there are never any preempted | 1013 | * Because preemptible RCU does not exist, there are never any preempted |
| 1006 | * RCU readers. | 1014 | * RCU readers. |
| 1007 | */ | 1015 | */ |
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index d5594a4268d4..468bdd44c1ba 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
| @@ -2081,7 +2081,6 @@ context_switch(struct rq *rq, struct task_struct *prev, | |||
| 2081 | #endif | 2081 | #endif |
| 2082 | 2082 | ||
| 2083 | /* Here we just switch the register state and the stack. */ | 2083 | /* Here we just switch the register state and the stack. */ |
| 2084 | rcu_switch_from(prev); | ||
| 2085 | switch_to(prev, next, prev); | 2084 | switch_to(prev, next, prev); |
| 2086 | 2085 | ||
| 2087 | barrier(); | 2086 | barrier(); |
| @@ -2161,11 +2160,73 @@ unsigned long this_cpu_load(void) | |||
| 2161 | } | 2160 | } |
| 2162 | 2161 | ||
| 2163 | 2162 | ||
| 2163 | /* | ||
| 2164 | * Global load-average calculations | ||
| 2165 | * | ||
| 2166 | * We take a distributed and async approach to calculating the global load-avg | ||
| 2167 | * in order to minimize overhead. | ||
| 2168 | * | ||
| 2169 | * The global load average is an exponentially decaying average of nr_running + | ||
| 2170 | * nr_uninterruptible. | ||
| 2171 | * | ||
| 2172 | * Once every LOAD_FREQ: | ||
| 2173 | * | ||
| 2174 | * nr_active = 0; | ||
| 2175 | * for_each_possible_cpu(cpu) | ||
| 2176 | * nr_active += cpu_of(cpu)->nr_running + cpu_of(cpu)->nr_uninterruptible; | ||
| 2177 | * | ||
| 2178 | * avenrun[n] = avenrun[0] * exp_n + nr_active * (1 - exp_n) | ||
| 2179 | * | ||
| 2180 | * Due to a number of reasons the above turns in the mess below: | ||
| 2181 | * | ||
| 2182 | * - for_each_possible_cpu() is prohibitively expensive on machines with | ||
| 2183 | * serious number of cpus, therefore we need to take a distributed approach | ||
| 2184 | * to calculating nr_active. | ||
| 2185 | * | ||
| 2186 | * \Sum_i x_i(t) = \Sum_i x_i(t) - x_i(t_0) | x_i(t_0) := 0 | ||
| 2187 | * = \Sum_i { \Sum_j=1 x_i(t_j) - x_i(t_j-1) } | ||
| 2188 | * | ||
| 2189 | * So assuming nr_active := 0 when we start out -- true per definition, we | ||
| 2190 | * can simply take per-cpu deltas and fold those into a global accumulate | ||
| 2191 | * to obtain the same result. See calc_load_fold_active(). | ||
| 2192 | * | ||
| 2193 | * Furthermore, in order to avoid synchronizing all per-cpu delta folding | ||
| 2194 | * across the machine, we assume 10 ticks is sufficient time for every | ||
| 2195 | * cpu to have completed this task. | ||
| 2196 | * | ||
| 2197 | * This places an upper-bound on the IRQ-off latency of the machine. Then | ||
| 2198 | * again, being late doesn't loose the delta, just wrecks the sample. | ||
| 2199 | * | ||
| 2200 | * - cpu_rq()->nr_uninterruptible isn't accurately tracked per-cpu because | ||
| 2201 | * this would add another cross-cpu cacheline miss and atomic operation | ||
| 2202 | * to the wakeup path. Instead we increment on whatever cpu the task ran | ||
| 2203 | * when it went into uninterruptible state and decrement on whatever cpu | ||
| 2204 | * did the wakeup. This means that only the sum of nr_uninterruptible over | ||
| 2205 | * all cpus yields the correct result. | ||
| 2206 | * | ||
| 2207 | * This covers the NO_HZ=n code, for extra head-aches, see the comment below. | ||
| 2208 | */ | ||
| 2209 | |||
| 2164 | /* Variables and functions for calc_load */ | 2210 | /* Variables and functions for calc_load */ |
| 2165 | static atomic_long_t calc_load_tasks; | 2211 | static atomic_long_t calc_load_tasks; |
| 2166 | static unsigned long calc_load_update; | 2212 | static unsigned long calc_load_update; |
| 2167 | unsigned long avenrun[3]; | 2213 | unsigned long avenrun[3]; |
| 2168 | EXPORT_SYMBOL(avenrun); | 2214 | EXPORT_SYMBOL(avenrun); /* should be removed */ |
| 2215 | |||
| 2216 | /** | ||
| 2217 | * get_avenrun - get the load average array | ||
| 2218 | * @loads: pointer to dest load array | ||
| 2219 | * @offset: offset to add | ||
| 2220 | * @shift: shift count to shift the result left | ||
| 2221 | * | ||
| 2222 | * These values are estimates at best, so no need for locking. | ||
| 2223 | */ | ||
| 2224 | void get_avenrun(unsigned long *loads, unsigned long offset, int shift) | ||
| 2225 | { | ||
| 2226 | loads[0] = (avenrun[0] + offset) << shift; | ||
| 2227 | loads[1] = (avenrun[1] + offset) << shift; | ||
| 2228 | loads[2] = (avenrun[2] + offset) << shift; | ||
| 2229 | } | ||
| 2169 | 2230 | ||
| 2170 | static long calc_load_fold_active(struct rq *this_rq) | 2231 | static long calc_load_fold_active(struct rq *this_rq) |
| 2171 | { | 2232 | { |
| @@ -2182,6 +2243,9 @@ static long calc_load_fold_active(struct rq *this_rq) | |||
| 2182 | return delta; | 2243 | return delta; |
| 2183 | } | 2244 | } |
| 2184 | 2245 | ||
| 2246 | /* | ||
| 2247 | * a1 = a0 * e + a * (1 - e) | ||
| 2248 | */ | ||
| 2185 | static unsigned long | 2249 | static unsigned long |
| 2186 | calc_load(unsigned long load, unsigned long exp, unsigned long active) | 2250 | calc_load(unsigned long load, unsigned long exp, unsigned long active) |
| 2187 | { | 2251 | { |
| @@ -2193,30 +2257,118 @@ calc_load(unsigned long load, unsigned long exp, unsigned long active) | |||
| 2193 | 2257 | ||
| 2194 | #ifdef CONFIG_NO_HZ | 2258 | #ifdef CONFIG_NO_HZ |
| 2195 | /* | 2259 | /* |
| 2196 | * For NO_HZ we delay the active fold to the next LOAD_FREQ update. | 2260 | * Handle NO_HZ for the global load-average. |
| 2261 | * | ||
| 2262 | * Since the above described distributed algorithm to compute the global | ||
| 2263 | * load-average relies on per-cpu sampling from the tick, it is affected by | ||
| 2264 | * NO_HZ. | ||
| 2265 | * | ||
| 2266 | * The basic idea is to fold the nr_active delta into a global idle-delta upon | ||
| 2267 | * entering NO_HZ state such that we can include this as an 'extra' cpu delta | ||
| 2268 | * when we read the global state. | ||
| 2269 | * | ||
| 2270 | * Obviously reality has to ruin such a delightfully simple scheme: | ||
| 2271 | * | ||
| 2272 | * - When we go NO_HZ idle during the window, we can negate our sample | ||
| 2273 | * contribution, causing under-accounting. | ||
| 2274 | * | ||
| 2275 | * We avoid this by keeping two idle-delta counters and flipping them | ||
| 2276 | * when the window starts, thus separating old and new NO_HZ load. | ||
| 2277 | * | ||
| 2278 | * The only trick is the slight shift in index flip for read vs write. | ||
| 2279 | * | ||
| 2280 | * 0s 5s 10s 15s | ||
| 2281 | * +10 +10 +10 +10 | ||
| 2282 | * |-|-----------|-|-----------|-|-----------|-| | ||
| 2283 | * r:0 0 1 1 0 0 1 1 0 | ||
| 2284 | * w:0 1 1 0 0 1 1 0 0 | ||
| 2285 | * | ||
| 2286 | * This ensures we'll fold the old idle contribution in this window while | ||
| 2287 | * accumlating the new one. | ||
| 2288 | * | ||
| 2289 | * - When we wake up from NO_HZ idle during the window, we push up our | ||
| 2290 | * contribution, since we effectively move our sample point to a known | ||
| 2291 | * busy state. | ||
| 2292 | * | ||
| 2293 | * This is solved by pushing the window forward, and thus skipping the | ||
| 2294 | * sample, for this cpu (effectively using the idle-delta for this cpu which | ||
| 2295 | * was in effect at the time the window opened). This also solves the issue | ||
| 2296 | * of having to deal with a cpu having been in NOHZ idle for multiple | ||
| 2297 | * LOAD_FREQ intervals. | ||
| 2197 | * | 2298 | * |
| 2198 | * When making the ILB scale, we should try to pull this in as well. | 2299 | * When making the ILB scale, we should try to pull this in as well. |
| 2199 | */ | 2300 | */ |
| 2200 | static atomic_long_t calc_load_tasks_idle; | 2301 | static atomic_long_t calc_load_idle[2]; |
| 2302 | static int calc_load_idx; | ||
| 2201 | 2303 | ||
| 2202 | void calc_load_account_idle(struct rq *this_rq) | 2304 | static inline int calc_load_write_idx(void) |
| 2203 | { | 2305 | { |
| 2306 | int idx = calc_load_idx; | ||
| 2307 | |||
| 2308 | /* | ||
| 2309 | * See calc_global_nohz(), if we observe the new index, we also | ||
| 2310 | * need to observe the new update time. | ||
| 2311 | */ | ||
| 2312 | smp_rmb(); | ||
| 2313 | |||
| 2314 | /* | ||
| 2315 | * If the folding window started, make sure we start writing in the | ||
| 2316 | * next idle-delta. | ||
| 2317 | */ | ||
| 2318 | if (!time_before(jiffies, calc_load_update)) | ||
| 2319 | idx++; | ||
| 2320 | |||
| 2321 | return idx & 1; | ||
| 2322 | } | ||
| 2323 | |||
| 2324 | static inline int calc_load_read_idx(void) | ||
| 2325 | { | ||
| 2326 | return calc_load_idx & 1; | ||
| 2327 | } | ||
| 2328 | |||
| 2329 | void calc_load_enter_idle(void) | ||
| 2330 | { | ||
| 2331 | struct rq *this_rq = this_rq(); | ||
| 2204 | long delta; | 2332 | long delta; |
| 2205 | 2333 | ||
| 2334 | /* | ||
| 2335 | * We're going into NOHZ mode, if there's any pending delta, fold it | ||
| 2336 | * into the pending idle delta. | ||
| 2337 | */ | ||
| 2206 | delta = calc_load_fold_active(this_rq); | 2338 | delta = calc_load_fold_active(this_rq); |
| 2207 | if (delta) | 2339 | if (delta) { |
| 2208 | atomic_long_add(delta, &calc_load_tasks_idle); | 2340 | int idx = calc_load_write_idx(); |
| 2341 | atomic_long_add(delta, &calc_load_idle[idx]); | ||
| 2342 | } | ||
| 2209 | } | 2343 | } |
| 2210 | 2344 | ||
| 2211 | static long calc_load_fold_idle(void) | 2345 | void calc_load_exit_idle(void) |
| 2212 | { | 2346 | { |
| 2213 | long delta = 0; | 2347 | struct rq *this_rq = this_rq(); |
| 2348 | |||
| 2349 | /* | ||
| 2350 | * If we're still before the sample window, we're done. | ||
| 2351 | */ | ||
| 2352 | if (time_before(jiffies, this_rq->calc_load_update)) | ||
| 2353 | return; | ||
| 2214 | 2354 | ||
| 2215 | /* | 2355 | /* |
| 2216 | * Its got a race, we don't care... | 2356 | * We woke inside or after the sample window, this means we're already |
| 2357 | * accounted through the nohz accounting, so skip the entire deal and | ||
| 2358 | * sync up for the next window. | ||
| 2217 | */ | 2359 | */ |
| 2218 | if (atomic_long_read(&calc_load_tasks_idle)) | 2360 | this_rq->calc_load_update = calc_load_update; |
| 2219 | delta = atomic_long_xchg(&calc_load_tasks_idle, 0); | 2361 | if (time_before(jiffies, this_rq->calc_load_update + 10)) |
| 2362 | this_rq->calc_load_update += LOAD_FREQ; | ||
| 2363 | } | ||
| 2364 | |||
| 2365 | static long calc_load_fold_idle(void) | ||
| 2366 | { | ||
| 2367 | int idx = calc_load_read_idx(); | ||
| 2368 | long delta = 0; | ||
| 2369 | |||
| 2370 | if (atomic_long_read(&calc_load_idle[idx])) | ||
| 2371 | delta = atomic_long_xchg(&calc_load_idle[idx], 0); | ||
| 2220 | 2372 | ||
| 2221 | return delta; | 2373 | return delta; |
| 2222 | } | 2374 | } |
| @@ -2302,66 +2454,39 @@ static void calc_global_nohz(void) | |||
| 2302 | { | 2454 | { |
| 2303 | long delta, active, n; | 2455 | long delta, active, n; |
| 2304 | 2456 | ||
| 2305 | /* | 2457 | if (!time_before(jiffies, calc_load_update + 10)) { |
| 2306 | * If we crossed a calc_load_update boundary, make sure to fold | 2458 | /* |
| 2307 | * any pending idle changes, the respective CPUs might have | 2459 | * Catch-up, fold however many we are behind still |
| 2308 | * missed the tick driven calc_load_account_active() update | 2460 | */ |
| 2309 | * due to NO_HZ. | 2461 | delta = jiffies - calc_load_update - 10; |
| 2310 | */ | 2462 | n = 1 + (delta / LOAD_FREQ); |
| 2311 | delta = calc_load_fold_idle(); | ||
| 2312 | if (delta) | ||
| 2313 | atomic_long_add(delta, &calc_load_tasks); | ||
| 2314 | |||
| 2315 | /* | ||
| 2316 | * It could be the one fold was all it took, we done! | ||
| 2317 | */ | ||
| 2318 | if (time_before(jiffies, calc_load_update + 10)) | ||
| 2319 | return; | ||
| 2320 | |||
| 2321 | /* | ||
| 2322 | * Catch-up, fold however many we are behind still | ||
| 2323 | */ | ||
| 2324 | delta = jiffies - calc_load_update - 10; | ||
| 2325 | n = 1 + (delta / LOAD_FREQ); | ||
| 2326 | 2463 | ||
| 2327 | active = atomic_long_read(&calc_load_tasks); | 2464 | active = atomic_long_read(&calc_load_tasks); |
| 2328 | active = active > 0 ? active * FIXED_1 : 0; | 2465 | active = active > 0 ? active * FIXED_1 : 0; |
| 2329 | 2466 | ||
| 2330 | avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n); | 2467 | avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n); |
| 2331 | avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n); | 2468 | avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n); |
| 2332 | avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n); | 2469 | avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n); |
| 2333 | 2470 | ||
| 2334 | calc_load_update += n * LOAD_FREQ; | 2471 | calc_load_update += n * LOAD_FREQ; |
| 2335 | } | 2472 | } |
| 2336 | #else | ||
| 2337 | void calc_load_account_idle(struct rq *this_rq) | ||
| 2338 | { | ||
| 2339 | } | ||
| 2340 | 2473 | ||
| 2341 | static inline long calc_load_fold_idle(void) | 2474 | /* |
| 2342 | { | 2475 | * Flip the idle index... |
| 2343 | return 0; | 2476 | * |
| 2477 | * Make sure we first write the new time then flip the index, so that | ||
| 2478 | * calc_load_write_idx() will see the new time when it reads the new | ||
| 2479 | * index, this avoids a double flip messing things up. | ||
| 2480 | */ | ||
| 2481 | smp_wmb(); | ||
| 2482 | calc_load_idx++; | ||
| 2344 | } | 2483 | } |
| 2484 | #else /* !CONFIG_NO_HZ */ | ||
| 2345 | 2485 | ||
| 2346 | static void calc_global_nohz(void) | 2486 | static inline long calc_load_fold_idle(void) { return 0; } |
| 2347 | { | 2487 | static inline void calc_global_nohz(void) { } |
| 2348 | } | ||
| 2349 | #endif | ||
| 2350 | 2488 | ||
| 2351 | /** | 2489 | #endif /* CONFIG_NO_HZ */ |
| 2352 | * get_avenrun - get the load average array | ||
| 2353 | * @loads: pointer to dest load array | ||
| 2354 | * @offset: offset to add | ||
| 2355 | * @shift: shift count to shift the result left | ||
| 2356 | * | ||
| 2357 | * These values are estimates at best, so no need for locking. | ||
| 2358 | */ | ||
| 2359 | void get_avenrun(unsigned long *loads, unsigned long offset, int shift) | ||
| 2360 | { | ||
| 2361 | loads[0] = (avenrun[0] + offset) << shift; | ||
| 2362 | loads[1] = (avenrun[1] + offset) << shift; | ||
| 2363 | loads[2] = (avenrun[2] + offset) << shift; | ||
| 2364 | } | ||
| 2365 | 2490 | ||
| 2366 | /* | 2491 | /* |
| 2367 | * calc_load - update the avenrun load estimates 10 ticks after the | 2492 | * calc_load - update the avenrun load estimates 10 ticks after the |
| @@ -2369,11 +2494,18 @@ void get_avenrun(unsigned long *loads, unsigned long offset, int shift) | |||
| 2369 | */ | 2494 | */ |
| 2370 | void calc_global_load(unsigned long ticks) | 2495 | void calc_global_load(unsigned long ticks) |
| 2371 | { | 2496 | { |
| 2372 | long active; | 2497 | long active, delta; |
| 2373 | 2498 | ||
| 2374 | if (time_before(jiffies, calc_load_update + 10)) | 2499 | if (time_before(jiffies, calc_load_update + 10)) |
| 2375 | return; | 2500 | return; |
| 2376 | 2501 | ||
| 2502 | /* | ||
| 2503 | * Fold the 'old' idle-delta to include all NO_HZ cpus. | ||
| 2504 | */ | ||
| 2505 | delta = calc_load_fold_idle(); | ||
| 2506 | if (delta) | ||
| 2507 | atomic_long_add(delta, &calc_load_tasks); | ||
| 2508 | |||
| 2377 | active = atomic_long_read(&calc_load_tasks); | 2509 | active = atomic_long_read(&calc_load_tasks); |
| 2378 | active = active > 0 ? active * FIXED_1 : 0; | 2510 | active = active > 0 ? active * FIXED_1 : 0; |
| 2379 | 2511 | ||
| @@ -2384,12 +2516,7 @@ void calc_global_load(unsigned long ticks) | |||
| 2384 | calc_load_update += LOAD_FREQ; | 2516 | calc_load_update += LOAD_FREQ; |
| 2385 | 2517 | ||
| 2386 | /* | 2518 | /* |
| 2387 | * Account one period with whatever state we found before | 2519 | * In case we idled for multiple LOAD_FREQ intervals, catch up in bulk. |
| 2388 | * folding in the nohz state and ageing the entire idle period. | ||
| 2389 | * | ||
| 2390 | * This avoids loosing a sample when we go idle between | ||
| 2391 | * calc_load_account_active() (10 ticks ago) and now and thus | ||
| 2392 | * under-accounting. | ||
| 2393 | */ | 2520 | */ |
| 2394 | calc_global_nohz(); | 2521 | calc_global_nohz(); |
| 2395 | } | 2522 | } |
| @@ -2406,7 +2533,6 @@ static void calc_load_account_active(struct rq *this_rq) | |||
| 2406 | return; | 2533 | return; |
| 2407 | 2534 | ||
| 2408 | delta = calc_load_fold_active(this_rq); | 2535 | delta = calc_load_fold_active(this_rq); |
| 2409 | delta += calc_load_fold_idle(); | ||
| 2410 | if (delta) | 2536 | if (delta) |
| 2411 | atomic_long_add(delta, &calc_load_tasks); | 2537 | atomic_long_add(delta, &calc_load_tasks); |
| 2412 | 2538 | ||
| @@ -2414,6 +2540,10 @@ static void calc_load_account_active(struct rq *this_rq) | |||
| 2414 | } | 2540 | } |
| 2415 | 2541 | ||
| 2416 | /* | 2542 | /* |
| 2543 | * End of global load-average stuff | ||
| 2544 | */ | ||
| 2545 | |||
| 2546 | /* | ||
| 2417 | * The exact cpuload at various idx values, calculated at every tick would be | 2547 | * The exact cpuload at various idx values, calculated at every tick would be |
| 2418 | * load = (2^idx - 1) / 2^idx * load + 1 / 2^idx * cur_load | 2548 | * load = (2^idx - 1) / 2^idx * load + 1 / 2^idx * cur_load |
| 2419 | * | 2549 | * |
diff --git a/kernel/sched/idle_task.c b/kernel/sched/idle_task.c index b44d604b35d1..b6baf370cae9 100644 --- a/kernel/sched/idle_task.c +++ b/kernel/sched/idle_task.c | |||
| @@ -25,7 +25,6 @@ static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int fl | |||
| 25 | static struct task_struct *pick_next_task_idle(struct rq *rq) | 25 | static struct task_struct *pick_next_task_idle(struct rq *rq) |
| 26 | { | 26 | { |
| 27 | schedstat_inc(rq, sched_goidle); | 27 | schedstat_inc(rq, sched_goidle); |
| 28 | calc_load_account_idle(rq); | ||
| 29 | return rq->idle; | 28 | return rq->idle; |
| 30 | } | 29 | } |
| 31 | 30 | ||
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 6d52cea7f33d..55844f24435a 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h | |||
| @@ -942,8 +942,6 @@ static inline u64 sched_avg_period(void) | |||
| 942 | return (u64)sysctl_sched_time_avg * NSEC_PER_MSEC / 2; | 942 | return (u64)sysctl_sched_time_avg * NSEC_PER_MSEC / 2; |
| 943 | } | 943 | } |
| 944 | 944 | ||
| 945 | void calc_load_account_idle(struct rq *this_rq); | ||
| 946 | |||
| 947 | #ifdef CONFIG_SCHED_HRTICK | 945 | #ifdef CONFIG_SCHED_HRTICK |
| 948 | 946 | ||
| 949 | /* | 947 | /* |
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 869997833928..4a08472c3ca7 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
| @@ -406,6 +406,7 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts) | |||
| 406 | */ | 406 | */ |
| 407 | if (!ts->tick_stopped) { | 407 | if (!ts->tick_stopped) { |
| 408 | select_nohz_load_balancer(1); | 408 | select_nohz_load_balancer(1); |
| 409 | calc_load_enter_idle(); | ||
| 409 | 410 | ||
| 410 | ts->idle_tick = hrtimer_get_expires(&ts->sched_timer); | 411 | ts->idle_tick = hrtimer_get_expires(&ts->sched_timer); |
| 411 | ts->tick_stopped = 1; | 412 | ts->tick_stopped = 1; |
| @@ -597,6 +598,7 @@ void tick_nohz_idle_exit(void) | |||
| 597 | account_idle_ticks(ticks); | 598 | account_idle_ticks(ticks); |
| 598 | #endif | 599 | #endif |
| 599 | 600 | ||
| 601 | calc_load_exit_idle(); | ||
| 600 | touch_softlockup_watchdog(); | 602 | touch_softlockup_watchdog(); |
| 601 | /* | 603 | /* |
| 602 | * Cancel the scheduled timer and restore the tick | 604 | * Cancel the scheduled timer and restore the tick |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 6f46a00a1e8a..269b1fe5f2ae 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
| @@ -70,6 +70,12 @@ struct timekeeper { | |||
| 70 | /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */ | 70 | /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */ |
| 71 | struct timespec raw_time; | 71 | struct timespec raw_time; |
| 72 | 72 | ||
| 73 | /* Offset clock monotonic -> clock realtime */ | ||
| 74 | ktime_t offs_real; | ||
| 75 | |||
| 76 | /* Offset clock monotonic -> clock boottime */ | ||
| 77 | ktime_t offs_boot; | ||
| 78 | |||
| 73 | /* Seqlock for all timekeeper values */ | 79 | /* Seqlock for all timekeeper values */ |
| 74 | seqlock_t lock; | 80 | seqlock_t lock; |
| 75 | }; | 81 | }; |
| @@ -172,6 +178,14 @@ static inline s64 timekeeping_get_ns_raw(void) | |||
| 172 | return clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift); | 178 | return clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift); |
| 173 | } | 179 | } |
| 174 | 180 | ||
| 181 | static void update_rt_offset(void) | ||
| 182 | { | ||
| 183 | struct timespec tmp, *wtm = &timekeeper.wall_to_monotonic; | ||
| 184 | |||
| 185 | set_normalized_timespec(&tmp, -wtm->tv_sec, -wtm->tv_nsec); | ||
| 186 | timekeeper.offs_real = timespec_to_ktime(tmp); | ||
| 187 | } | ||
| 188 | |||
| 175 | /* must hold write on timekeeper.lock */ | 189 | /* must hold write on timekeeper.lock */ |
| 176 | static void timekeeping_update(bool clearntp) | 190 | static void timekeeping_update(bool clearntp) |
| 177 | { | 191 | { |
| @@ -179,6 +193,7 @@ static void timekeeping_update(bool clearntp) | |||
| 179 | timekeeper.ntp_error = 0; | 193 | timekeeper.ntp_error = 0; |
| 180 | ntp_clear(); | 194 | ntp_clear(); |
| 181 | } | 195 | } |
| 196 | update_rt_offset(); | ||
| 182 | update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic, | 197 | update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic, |
| 183 | timekeeper.clock, timekeeper.mult); | 198 | timekeeper.clock, timekeeper.mult); |
| 184 | } | 199 | } |
| @@ -604,6 +619,7 @@ void __init timekeeping_init(void) | |||
| 604 | } | 619 | } |
| 605 | set_normalized_timespec(&timekeeper.wall_to_monotonic, | 620 | set_normalized_timespec(&timekeeper.wall_to_monotonic, |
| 606 | -boot.tv_sec, -boot.tv_nsec); | 621 | -boot.tv_sec, -boot.tv_nsec); |
| 622 | update_rt_offset(); | ||
| 607 | timekeeper.total_sleep_time.tv_sec = 0; | 623 | timekeeper.total_sleep_time.tv_sec = 0; |
| 608 | timekeeper.total_sleep_time.tv_nsec = 0; | 624 | timekeeper.total_sleep_time.tv_nsec = 0; |
| 609 | write_sequnlock_irqrestore(&timekeeper.lock, flags); | 625 | write_sequnlock_irqrestore(&timekeeper.lock, flags); |
| @@ -612,6 +628,12 @@ void __init timekeeping_init(void) | |||
| 612 | /* time in seconds when suspend began */ | 628 | /* time in seconds when suspend began */ |
| 613 | static struct timespec timekeeping_suspend_time; | 629 | static struct timespec timekeeping_suspend_time; |
| 614 | 630 | ||
| 631 | static void update_sleep_time(struct timespec t) | ||
| 632 | { | ||
| 633 | timekeeper.total_sleep_time = t; | ||
| 634 | timekeeper.offs_boot = timespec_to_ktime(t); | ||
| 635 | } | ||
| 636 | |||
| 615 | /** | 637 | /** |
| 616 | * __timekeeping_inject_sleeptime - Internal function to add sleep interval | 638 | * __timekeeping_inject_sleeptime - Internal function to add sleep interval |
| 617 | * @delta: pointer to a timespec delta value | 639 | * @delta: pointer to a timespec delta value |
| @@ -630,8 +652,7 @@ static void __timekeeping_inject_sleeptime(struct timespec *delta) | |||
| 630 | timekeeper.xtime = timespec_add(timekeeper.xtime, *delta); | 652 | timekeeper.xtime = timespec_add(timekeeper.xtime, *delta); |
| 631 | timekeeper.wall_to_monotonic = | 653 | timekeeper.wall_to_monotonic = |
| 632 | timespec_sub(timekeeper.wall_to_monotonic, *delta); | 654 | timespec_sub(timekeeper.wall_to_monotonic, *delta); |
| 633 | timekeeper.total_sleep_time = timespec_add( | 655 | update_sleep_time(timespec_add(timekeeper.total_sleep_time, *delta)); |
| 634 | timekeeper.total_sleep_time, *delta); | ||
| 635 | } | 656 | } |
| 636 | 657 | ||
| 637 | 658 | ||
| @@ -963,6 +984,8 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift) | |||
| 963 | leap = second_overflow(timekeeper.xtime.tv_sec); | 984 | leap = second_overflow(timekeeper.xtime.tv_sec); |
| 964 | timekeeper.xtime.tv_sec += leap; | 985 | timekeeper.xtime.tv_sec += leap; |
| 965 | timekeeper.wall_to_monotonic.tv_sec -= leap; | 986 | timekeeper.wall_to_monotonic.tv_sec -= leap; |
| 987 | if (leap) | ||
| 988 | clock_was_set_delayed(); | ||
| 966 | } | 989 | } |
| 967 | 990 | ||
| 968 | /* Accumulate raw time */ | 991 | /* Accumulate raw time */ |
| @@ -1079,6 +1102,8 @@ static void update_wall_time(void) | |||
| 1079 | leap = second_overflow(timekeeper.xtime.tv_sec); | 1102 | leap = second_overflow(timekeeper.xtime.tv_sec); |
| 1080 | timekeeper.xtime.tv_sec += leap; | 1103 | timekeeper.xtime.tv_sec += leap; |
| 1081 | timekeeper.wall_to_monotonic.tv_sec -= leap; | 1104 | timekeeper.wall_to_monotonic.tv_sec -= leap; |
| 1105 | if (leap) | ||
| 1106 | clock_was_set_delayed(); | ||
| 1082 | } | 1107 | } |
| 1083 | 1108 | ||
| 1084 | timekeeping_update(false); | 1109 | timekeeping_update(false); |
| @@ -1246,6 +1271,40 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim, | |||
| 1246 | } while (read_seqretry(&timekeeper.lock, seq)); | 1271 | } while (read_seqretry(&timekeeper.lock, seq)); |
| 1247 | } | 1272 | } |
| 1248 | 1273 | ||
| 1274 | #ifdef CONFIG_HIGH_RES_TIMERS | ||
| 1275 | /** | ||
| 1276 | * ktime_get_update_offsets - hrtimer helper | ||
| 1277 | * @offs_real: pointer to storage for monotonic -> realtime offset | ||
| 1278 | * @offs_boot: pointer to storage for monotonic -> boottime offset | ||
| 1279 | * | ||
| 1280 | * Returns current monotonic time and updates the offsets | ||
| 1281 | * Called from hrtimer_interupt() or retrigger_next_event() | ||
| 1282 | */ | ||
| 1283 | ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot) | ||
| 1284 | { | ||
| 1285 | ktime_t now; | ||
| 1286 | unsigned int seq; | ||
| 1287 | u64 secs, nsecs; | ||
| 1288 | |||
| 1289 | do { | ||
| 1290 | seq = read_seqbegin(&timekeeper.lock); | ||
| 1291 | |||
| 1292 | secs = timekeeper.xtime.tv_sec; | ||
| 1293 | nsecs = timekeeper.xtime.tv_nsec; | ||
| 1294 | nsecs += timekeeping_get_ns(); | ||
| 1295 | /* If arch requires, add in gettimeoffset() */ | ||
| 1296 | nsecs += arch_gettimeoffset(); | ||
| 1297 | |||
| 1298 | *offs_real = timekeeper.offs_real; | ||
| 1299 | *offs_boot = timekeeper.offs_boot; | ||
| 1300 | } while (read_seqretry(&timekeeper.lock, seq)); | ||
| 1301 | |||
| 1302 | now = ktime_add_ns(ktime_set(secs, 0), nsecs); | ||
| 1303 | now = ktime_sub(now, *offs_real); | ||
| 1304 | return now; | ||
| 1305 | } | ||
| 1306 | #endif | ||
| 1307 | |||
| 1249 | /** | 1308 | /** |
| 1250 | * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format | 1309 | * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format |
| 1251 | */ | 1310 | */ |
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 1d0f6a8a0e5e..f765465bffe4 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
| @@ -1075,6 +1075,7 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int nr_pages, int cpu) | |||
| 1075 | rb_init_page(bpage->page); | 1075 | rb_init_page(bpage->page); |
| 1076 | 1076 | ||
| 1077 | INIT_LIST_HEAD(&cpu_buffer->reader_page->list); | 1077 | INIT_LIST_HEAD(&cpu_buffer->reader_page->list); |
| 1078 | INIT_LIST_HEAD(&cpu_buffer->new_pages); | ||
| 1078 | 1079 | ||
| 1079 | ret = rb_allocate_pages(cpu_buffer, nr_pages); | 1080 | ret = rb_allocate_pages(cpu_buffer, nr_pages); |
| 1080 | if (ret < 0) | 1081 | if (ret < 0) |
| @@ -1346,10 +1347,9 @@ rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned int nr_pages) | |||
| 1346 | * If something was added to this page, it was full | 1347 | * If something was added to this page, it was full |
| 1347 | * since it is not the tail page. So we deduct the | 1348 | * since it is not the tail page. So we deduct the |
| 1348 | * bytes consumed in ring buffer from here. | 1349 | * bytes consumed in ring buffer from here. |
| 1349 | * No need to update overruns, since this page is | 1350 | * Increment overrun to account for the lost events. |
| 1350 | * deleted from ring buffer and its entries are | ||
| 1351 | * already accounted for. | ||
| 1352 | */ | 1351 | */ |
| 1352 | local_add(page_entries, &cpu_buffer->overrun); | ||
| 1353 | local_sub(BUF_PAGE_SIZE, &cpu_buffer->entries_bytes); | 1353 | local_sub(BUF_PAGE_SIZE, &cpu_buffer->entries_bytes); |
| 1354 | } | 1354 | } |
| 1355 | 1355 | ||
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index e6906901debb..0f647d22cb4a 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c | |||
| @@ -414,7 +414,7 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, | |||
| 414 | { | 414 | { |
| 415 | struct list_head *p; | 415 | struct list_head *p; |
| 416 | struct snd_usb_endpoint *ep; | 416 | struct snd_usb_endpoint *ep; |
| 417 | int ret, is_playback = direction == SNDRV_PCM_STREAM_PLAYBACK; | 417 | int is_playback = direction == SNDRV_PCM_STREAM_PLAYBACK; |
| 418 | 418 | ||
| 419 | mutex_lock(&chip->mutex); | 419 | mutex_lock(&chip->mutex); |
| 420 | 420 | ||
| @@ -434,16 +434,6 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, | |||
| 434 | type == SND_USB_ENDPOINT_TYPE_DATA ? "data" : "sync", | 434 | type == SND_USB_ENDPOINT_TYPE_DATA ? "data" : "sync", |
| 435 | ep_num); | 435 | ep_num); |
| 436 | 436 | ||
| 437 | /* select the alt setting once so the endpoints become valid */ | ||
| 438 | ret = usb_set_interface(chip->dev, alts->desc.bInterfaceNumber, | ||
| 439 | alts->desc.bAlternateSetting); | ||
| 440 | if (ret < 0) { | ||
| 441 | snd_printk(KERN_ERR "%s(): usb_set_interface() failed, ret = %d\n", | ||
| 442 | __func__, ret); | ||
| 443 | ep = NULL; | ||
| 444 | goto __exit_unlock; | ||
| 445 | } | ||
| 446 | |||
| 447 | ep = kzalloc(sizeof(*ep), GFP_KERNEL); | 437 | ep = kzalloc(sizeof(*ep), GFP_KERNEL); |
| 448 | if (!ep) | 438 | if (!ep) |
| 449 | goto __exit_unlock; | 439 | goto __exit_unlock; |
| @@ -831,9 +821,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) | |||
| 831 | if (++ep->use_count != 1) | 821 | if (++ep->use_count != 1) |
| 832 | return 0; | 822 | return 0; |
| 833 | 823 | ||
| 834 | if (snd_BUG_ON(!test_bit(EP_FLAG_ACTIVATED, &ep->flags))) | ||
| 835 | return -EINVAL; | ||
| 836 | |||
| 837 | /* just to be sure */ | 824 | /* just to be sure */ |
| 838 | deactivate_urbs(ep, 0, 1); | 825 | deactivate_urbs(ep, 0, 1); |
| 839 | wait_clear_urbs(ep); | 826 | wait_clear_urbs(ep); |
| @@ -911,9 +898,6 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, | |||
| 911 | if (snd_BUG_ON(ep->use_count == 0)) | 898 | if (snd_BUG_ON(ep->use_count == 0)) |
| 912 | return; | 899 | return; |
| 913 | 900 | ||
| 914 | if (snd_BUG_ON(!test_bit(EP_FLAG_ACTIVATED, &ep->flags))) | ||
| 915 | return; | ||
| 916 | |||
| 917 | if (--ep->use_count == 0) { | 901 | if (--ep->use_count == 0) { |
| 918 | deactivate_urbs(ep, force, can_sleep); | 902 | deactivate_urbs(ep, force, can_sleep); |
| 919 | ep->data_subs = NULL; | 903 | ep->data_subs = NULL; |
| @@ -927,42 +911,6 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, | |||
| 927 | } | 911 | } |
| 928 | 912 | ||
| 929 | /** | 913 | /** |
| 930 | * snd_usb_endpoint_activate: activate an snd_usb_endpoint | ||
| 931 | * | ||
| 932 | * @ep: the endpoint to activate | ||
| 933 | * | ||
| 934 | * If the endpoint is not currently in use, this functions will select the | ||
| 935 | * correct alternate interface setting for the interface of this endpoint. | ||
| 936 | * | ||
| 937 | * In case of any active users, this functions does nothing. | ||
| 938 | * | ||
| 939 | * Returns an error if usb_set_interface() failed, 0 in all other | ||
| 940 | * cases. | ||
| 941 | */ | ||
| 942 | int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep) | ||
| 943 | { | ||
| 944 | if (ep->use_count != 0) | ||
| 945 | return 0; | ||
| 946 | |||
| 947 | if (!ep->chip->shutdown && | ||
| 948 | !test_and_set_bit(EP_FLAG_ACTIVATED, &ep->flags)) { | ||
| 949 | int ret; | ||
| 950 | |||
| 951 | ret = usb_set_interface(ep->chip->dev, ep->iface, ep->alt_idx); | ||
| 952 | if (ret < 0) { | ||
| 953 | snd_printk(KERN_ERR "%s() usb_set_interface() failed, ret = %d\n", | ||
| 954 | __func__, ret); | ||
| 955 | clear_bit(EP_FLAG_ACTIVATED, &ep->flags); | ||
| 956 | return ret; | ||
| 957 | } | ||
| 958 | |||
| 959 | return 0; | ||
| 960 | } | ||
| 961 | |||
| 962 | return -EBUSY; | ||
| 963 | } | ||
| 964 | |||
| 965 | /** | ||
| 966 | * snd_usb_endpoint_deactivate: deactivate an snd_usb_endpoint | 914 | * snd_usb_endpoint_deactivate: deactivate an snd_usb_endpoint |
| 967 | * | 915 | * |
| 968 | * @ep: the endpoint to deactivate | 916 | * @ep: the endpoint to deactivate |
| @@ -980,24 +928,15 @@ int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep) | |||
| 980 | if (!ep) | 928 | if (!ep) |
| 981 | return -EINVAL; | 929 | return -EINVAL; |
| 982 | 930 | ||
| 931 | deactivate_urbs(ep, 1, 1); | ||
| 932 | wait_clear_urbs(ep); | ||
| 933 | |||
| 983 | if (ep->use_count != 0) | 934 | if (ep->use_count != 0) |
| 984 | return 0; | 935 | return 0; |
| 985 | 936 | ||
| 986 | if (!ep->chip->shutdown && | 937 | clear_bit(EP_FLAG_ACTIVATED, &ep->flags); |
| 987 | test_and_clear_bit(EP_FLAG_ACTIVATED, &ep->flags)) { | ||
| 988 | int ret; | ||
| 989 | |||
| 990 | ret = usb_set_interface(ep->chip->dev, ep->iface, 0); | ||
| 991 | if (ret < 0) { | ||
| 992 | snd_printk(KERN_ERR "%s(): usb_set_interface() failed, ret = %d\n", | ||
| 993 | __func__, ret); | ||
| 994 | return ret; | ||
| 995 | } | ||
| 996 | 938 | ||
| 997 | return 0; | 939 | return 0; |
| 998 | } | ||
| 999 | |||
| 1000 | return -EBUSY; | ||
| 1001 | } | 940 | } |
| 1002 | 941 | ||
| 1003 | /** | 942 | /** |
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 54607f8c4f66..a1298f379428 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
| @@ -261,19 +261,6 @@ static void stop_endpoints(struct snd_usb_substream *subs, | |||
| 261 | force, can_sleep, wait); | 261 | force, can_sleep, wait); |
| 262 | } | 262 | } |
| 263 | 263 | ||
| 264 | static int activate_endpoints(struct snd_usb_substream *subs) | ||
| 265 | { | ||
| 266 | if (subs->sync_endpoint) { | ||
| 267 | int ret; | ||
| 268 | |||
| 269 | ret = snd_usb_endpoint_activate(subs->sync_endpoint); | ||
| 270 | if (ret < 0) | ||
| 271 | return ret; | ||
| 272 | } | ||
| 273 | |||
| 274 | return snd_usb_endpoint_activate(subs->data_endpoint); | ||
| 275 | } | ||
| 276 | |||
| 277 | static int deactivate_endpoints(struct snd_usb_substream *subs) | 264 | static int deactivate_endpoints(struct snd_usb_substream *subs) |
| 278 | { | 265 | { |
| 279 | int reta, retb; | 266 | int reta, retb; |
| @@ -314,6 +301,33 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) | |||
| 314 | if (fmt == subs->cur_audiofmt) | 301 | if (fmt == subs->cur_audiofmt) |
| 315 | return 0; | 302 | return 0; |
| 316 | 303 | ||
| 304 | /* close the old interface */ | ||
| 305 | if (subs->interface >= 0 && subs->interface != fmt->iface) { | ||
| 306 | err = usb_set_interface(subs->dev, subs->interface, 0); | ||
| 307 | if (err < 0) { | ||
| 308 | snd_printk(KERN_ERR "%d:%d:%d: return to setting 0 failed (%d)\n", | ||
| 309 | dev->devnum, fmt->iface, fmt->altsetting, err); | ||
| 310 | return -EIO; | ||
| 311 | } | ||
| 312 | subs->interface = -1; | ||
| 313 | subs->altset_idx = 0; | ||
| 314 | } | ||
| 315 | |||
| 316 | /* set interface */ | ||
| 317 | if (subs->interface != fmt->iface || | ||
| 318 | subs->altset_idx != fmt->altset_idx) { | ||
| 319 | err = usb_set_interface(dev, fmt->iface, fmt->altsetting); | ||
| 320 | if (err < 0) { | ||
| 321 | snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed (%d)\n", | ||
| 322 | dev->devnum, fmt->iface, fmt->altsetting, err); | ||
| 323 | return -EIO; | ||
| 324 | } | ||
| 325 | snd_printdd(KERN_INFO "setting usb interface %d:%d\n", | ||
| 326 | fmt->iface, fmt->altsetting); | ||
| 327 | subs->interface = fmt->iface; | ||
| 328 | subs->altset_idx = fmt->altset_idx; | ||
| 329 | } | ||
| 330 | |||
| 317 | subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip, | 331 | subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip, |
| 318 | alts, fmt->endpoint, subs->direction, | 332 | alts, fmt->endpoint, subs->direction, |
| 319 | SND_USB_ENDPOINT_TYPE_DATA); | 333 | SND_USB_ENDPOINT_TYPE_DATA); |
| @@ -387,7 +401,7 @@ add_sync_ep: | |||
| 387 | subs->data_endpoint->sync_master = subs->sync_endpoint; | 401 | subs->data_endpoint->sync_master = subs->sync_endpoint; |
| 388 | } | 402 | } |
| 389 | 403 | ||
| 390 | if ((err = snd_usb_init_pitch(subs->stream->chip, subs->interface, alts, fmt)) < 0) | 404 | if ((err = snd_usb_init_pitch(subs->stream->chip, fmt->iface, alts, fmt)) < 0) |
| 391 | return err; | 405 | return err; |
| 392 | 406 | ||
| 393 | subs->cur_audiofmt = fmt; | 407 | subs->cur_audiofmt = fmt; |
| @@ -450,7 +464,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, | |||
| 450 | struct usb_interface *iface; | 464 | struct usb_interface *iface; |
| 451 | iface = usb_ifnum_to_if(subs->dev, fmt->iface); | 465 | iface = usb_ifnum_to_if(subs->dev, fmt->iface); |
| 452 | alts = &iface->altsetting[fmt->altset_idx]; | 466 | alts = &iface->altsetting[fmt->altset_idx]; |
| 453 | ret = snd_usb_init_sample_rate(subs->stream->chip, subs->interface, alts, fmt, rate); | 467 | ret = snd_usb_init_sample_rate(subs->stream->chip, fmt->iface, alts, fmt, rate); |
| 454 | if (ret < 0) | 468 | if (ret < 0) |
| 455 | return ret; | 469 | return ret; |
| 456 | subs->cur_rate = rate; | 470 | subs->cur_rate = rate; |
| @@ -460,12 +474,6 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, | |||
| 460 | mutex_lock(&subs->stream->chip->shutdown_mutex); | 474 | mutex_lock(&subs->stream->chip->shutdown_mutex); |
| 461 | /* format changed */ | 475 | /* format changed */ |
| 462 | stop_endpoints(subs, 0, 0, 0); | 476 | stop_endpoints(subs, 0, 0, 0); |
| 463 | deactivate_endpoints(subs); | ||
| 464 | |||
| 465 | ret = activate_endpoints(subs); | ||
| 466 | if (ret < 0) | ||
| 467 | goto unlock; | ||
| 468 | |||
| 469 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt, | 477 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt, |
| 470 | subs->sync_endpoint); | 478 | subs->sync_endpoint); |
| 471 | if (ret < 0) | 479 | if (ret < 0) |
| @@ -500,6 +508,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) | |||
| 500 | subs->period_bytes = 0; | 508 | subs->period_bytes = 0; |
| 501 | mutex_lock(&subs->stream->chip->shutdown_mutex); | 509 | mutex_lock(&subs->stream->chip->shutdown_mutex); |
| 502 | stop_endpoints(subs, 0, 1, 1); | 510 | stop_endpoints(subs, 0, 1, 1); |
| 511 | deactivate_endpoints(subs); | ||
| 503 | mutex_unlock(&subs->stream->chip->shutdown_mutex); | 512 | mutex_unlock(&subs->stream->chip->shutdown_mutex); |
| 504 | return snd_pcm_lib_free_vmalloc_buffer(substream); | 513 | return snd_pcm_lib_free_vmalloc_buffer(substream); |
| 505 | } | 514 | } |
| @@ -938,16 +947,20 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) | |||
| 938 | 947 | ||
| 939 | static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) | 948 | static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) |
| 940 | { | 949 | { |
| 941 | int ret; | ||
| 942 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); | 950 | struct snd_usb_stream *as = snd_pcm_substream_chip(substream); |
| 943 | struct snd_usb_substream *subs = &as->substream[direction]; | 951 | struct snd_usb_substream *subs = &as->substream[direction]; |
| 944 | 952 | ||
| 945 | stop_endpoints(subs, 0, 0, 0); | 953 | stop_endpoints(subs, 0, 0, 0); |
| 946 | ret = deactivate_endpoints(subs); | 954 | |
| 955 | if (!as->chip->shutdown && subs->interface >= 0) { | ||
| 956 | usb_set_interface(subs->dev, subs->interface, 0); | ||
| 957 | subs->interface = -1; | ||
| 958 | } | ||
| 959 | |||
| 947 | subs->pcm_substream = NULL; | 960 | subs->pcm_substream = NULL; |
| 948 | snd_usb_autosuspend(subs->stream->chip); | 961 | snd_usb_autosuspend(subs->stream->chip); |
| 949 | 962 | ||
| 950 | return ret; | 963 | return 0; |
| 951 | } | 964 | } |
| 952 | 965 | ||
| 953 | /* Since a URB can handle only a single linear buffer, we must use double | 966 | /* Since a URB can handle only a single linear buffer, we must use double |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 35ae56864e4f..a1f4e3669142 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
| @@ -669,25 +669,26 @@ struct machine *machines__find(struct rb_root *self, pid_t pid) | |||
| 669 | struct machine *machines__findnew(struct rb_root *self, pid_t pid) | 669 | struct machine *machines__findnew(struct rb_root *self, pid_t pid) |
| 670 | { | 670 | { |
| 671 | char path[PATH_MAX]; | 671 | char path[PATH_MAX]; |
| 672 | const char *root_dir; | 672 | const char *root_dir = ""; |
| 673 | struct machine *machine = machines__find(self, pid); | 673 | struct machine *machine = machines__find(self, pid); |
| 674 | 674 | ||
| 675 | if (!machine || machine->pid != pid) { | 675 | if (machine && (machine->pid == pid)) |
| 676 | if (pid == HOST_KERNEL_ID || pid == DEFAULT_GUEST_KERNEL_ID) | 676 | goto out; |
| 677 | root_dir = ""; | 677 | |
| 678 | else { | 678 | if ((pid != HOST_KERNEL_ID) && |
| 679 | if (!symbol_conf.guestmount) | 679 | (pid != DEFAULT_GUEST_KERNEL_ID) && |
| 680 | goto out; | 680 | (symbol_conf.guestmount)) { |
| 681 | sprintf(path, "%s/%d", symbol_conf.guestmount, pid); | 681 | sprintf(path, "%s/%d", symbol_conf.guestmount, pid); |
| 682 | if (access(path, R_OK)) { | 682 | if (access(path, R_OK)) { |
| 683 | pr_err("Can't access file %s\n", path); | 683 | pr_err("Can't access file %s\n", path); |
| 684 | goto out; | 684 | machine = NULL; |
| 685 | } | 685 | goto out; |
| 686 | root_dir = path; | ||
| 687 | } | 686 | } |
| 688 | machine = machines__add(self, pid, root_dir); | 687 | root_dir = path; |
| 689 | } | 688 | } |
| 690 | 689 | ||
| 690 | machine = machines__add(self, pid, root_dir); | ||
| 691 | |||
| 691 | out: | 692 | out: |
| 692 | return machine; | 693 | return machine; |
| 693 | } | 694 | } |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index c3e399bcf18d..56142d0fb8d7 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
| @@ -926,7 +926,7 @@ static struct machine * | |||
| 926 | else | 926 | else |
| 927 | pid = event->ip.pid; | 927 | pid = event->ip.pid; |
| 928 | 928 | ||
| 929 | return perf_session__find_machine(session, pid); | 929 | return perf_session__findnew_machine(session, pid); |
| 930 | } | 930 | } |
| 931 | 931 | ||
| 932 | return perf_session__find_host_machine(session); | 932 | return perf_session__find_host_machine(session); |
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index df2fddbf0cd2..5dd3b5ec8411 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c | |||
| @@ -198,9 +198,8 @@ void print_trace_event(int cpu, void *data, int size) | |||
| 198 | record.data = data; | 198 | record.data = data; |
| 199 | 199 | ||
| 200 | trace_seq_init(&s); | 200 | trace_seq_init(&s); |
| 201 | pevent_print_event(pevent, &s, &record); | 201 | pevent_event_info(&s, event, &record); |
| 202 | trace_seq_do_printf(&s); | 202 | trace_seq_do_printf(&s); |
| 203 | printf("\n"); | ||
| 204 | } | 203 | } |
| 205 | 204 | ||
| 206 | void print_event(int cpu, void *data, int size, unsigned long long nsecs, | 205 | void print_event(int cpu, void *data, int size, unsigned long long nsecs, |
