diff --git a/[refs] b/[refs] index c2fdadd7cd91..e3ea7939ab2b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: fcedac670c3da0d17aaa5db1708694971e8024a9 +refs/heads/master: ce806a30470bcd846d148bf39d46de3ad7748228 diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 1b71f6ceae0a..d1d9ae6173b8 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -5910,7 +5910,7 @@ M: Ingo Molnar M: Peter Zijlstra T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git sched/core S: Maintained -F: kernel/sched/ +F: kernel/sched* F: include/linux/sched.h SCORE ARCHITECTURE diff --git a/trunk/Makefile b/trunk/Makefile index aa8e315f26ef..bf02707a5e9b 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 5 SUBLEVEL = 0 -EXTRAVERSION = -rc7 +EXTRAVERSION = -rc6 NAME = Saber-toothed Squirrel # *DOCUMENTATION* diff --git a/trunk/arch/arm/mach-exynos/pm_domains.c b/trunk/arch/arm/mach-exynos/pm_domains.c index 373c3c00d24c..e9fafcf163de 100644 --- a/trunk/arch/arm/mach-exynos/pm_domains.c +++ b/trunk/arch/arm/mach-exynos/pm_domains.c @@ -119,9 +119,7 @@ static __init void exynos_pm_add_dev_to_genpd(struct platform_device *pdev, struct exynos_pm_domain *pd) { if (pdev->dev.bus) { - if (!pm_genpd_add_device(&pd->pd, &pdev->dev)) - pm_genpd_dev_need_restore(&pdev->dev, true); - else + if (pm_genpd_add_device(&pd->pd, &pdev->dev)) pr_info("%s: error in adding %s device to %s power" "domain\n", __func__, dev_name(&pdev->dev), pd->name); @@ -153,12 +151,9 @@ static __init int exynos4_pm_init_power_domain(void) if (of_have_populated_dt()) return exynos_pm_dt_parse_domains(); - for (idx = 0; idx < ARRAY_SIZE(exynos4_pm_domains); idx++) { - struct exynos_pm_domain *pd = exynos4_pm_domains[idx]; - int on = __raw_readl(pd->base + 0x4) & S5P_INT_LOCAL_PWR_EN; - - pm_genpd_init(&pd->pd, NULL, !on); - } + for (idx = 0; idx < ARRAY_SIZE(exynos4_pm_domains); idx++) + pm_genpd_init(&exynos4_pm_domains[idx]->pd, NULL, + exynos4_pm_domains[idx]->is_off); #ifdef CONFIG_S5P_DEV_FIMD0 exynos_pm_add_dev_to_genpd(&s5p_device_fimd0, &exynos4_pd_lcd0); diff --git a/trunk/arch/arm/mach-s3c24xx/clock-s3c2440.c b/trunk/arch/arm/mach-s3c24xx/clock-s3c2440.c index cb2883d553b5..414364eb426c 100644 --- a/trunk/arch/arm/mach-s3c24xx/clock-s3c2440.c +++ b/trunk/arch/arm/mach-s3c24xx/clock-s3c2440.c @@ -106,7 +106,7 @@ static struct clk s3c2440_clk_cam_upll = { static struct clk s3c2440_clk_ac97 = { .name = "ac97", .enable = s3c2410_clkcon_enable, - .ctrlbit = S3C2440_CLKCON_AC97, + .ctrlbit = S3C2440_CLKCON_CAMERA, }; static unsigned long s3c2440_fclk_n_getrate(struct clk *clk) diff --git a/trunk/arch/arm/plat-samsung/adc.c b/trunk/arch/arm/plat-samsung/adc.c index b1e05ccff3ac..33ecd0c9f0c3 100644 --- a/trunk/arch/arm/plat-samsung/adc.c +++ b/trunk/arch/arm/plat-samsung/adc.c @@ -157,12 +157,10 @@ int s3c_adc_start(struct s3c_adc_client *client, return -EINVAL; } - spin_lock_irqsave(&adc->lock, flags); - - if (client->is_ts && adc->ts_pend) { - spin_unlock_irqrestore(&adc->lock, flags); + if (client->is_ts && adc->ts_pend) return -EAGAIN; - } + + spin_lock_irqsave(&adc->lock, flags); client->channel = channel; client->nr_samples = nr_samples; diff --git a/trunk/arch/arm/plat-samsung/devs.c b/trunk/arch/arm/plat-samsung/devs.c index 6303974c2ee0..1d214cb9d770 100644 --- a/trunk/arch/arm/plat-samsung/devs.c +++ b/trunk/arch/arm/plat-samsung/devs.c @@ -126,8 +126,7 @@ struct platform_device s3c_device_adc = { #ifdef CONFIG_CPU_S3C2440 static struct resource s3c_camif_resource[] = { [0] = DEFINE_RES_MEM(S3C2440_PA_CAMIF, S3C2440_SZ_CAMIF), - [1] = DEFINE_RES_IRQ(IRQ_S3C2440_CAM_C), - [2] = DEFINE_RES_IRQ(IRQ_S3C2440_CAM_P), + [1] = DEFINE_RES_IRQ(IRQ_CAM), }; struct platform_device s3c_device_camif = { diff --git a/trunk/arch/arm/plat-samsung/s5p-clock.c b/trunk/arch/arm/plat-samsung/s5p-clock.c index 48a159911037..031a61899bef 100644 --- a/trunk/arch/arm/plat-samsung/s5p-clock.c +++ b/trunk/arch/arm/plat-samsung/s5p-clock.c @@ -37,7 +37,6 @@ struct clk clk_ext_xtal_mux = { struct clk clk_xusbxti = { .name = "xusbxti", .id = -1, - .rate = 24000000, }; struct clk s5p_clk_27m = { diff --git a/trunk/arch/um/drivers/mconsole_kern.c b/trunk/arch/um/drivers/mconsole_kern.c index 43b39d61b538..88e466b159dc 100644 --- a/trunk/arch/um/drivers/mconsole_kern.c +++ b/trunk/arch/um/drivers/mconsole_kern.c @@ -705,6 +705,7 @@ static void stack_proc(void *arg) struct task_struct *from = current, *to = arg; to->thread.saved_task = from; + rcu_switch_from(from); switch_to(from, to, from); } diff --git a/trunk/arch/x86/kernel/vsyscall_64.c b/trunk/arch/x86/kernel/vsyscall_64.c index 5db36caf4289..7515cf0e1805 100644 --- a/trunk/arch/x86/kernel/vsyscall_64.c +++ b/trunk/arch/x86/kernel/vsyscall_64.c @@ -139,19 +139,6 @@ static int addr_to_vsyscall_nr(unsigned long addr) return nr; } -#ifdef CONFIG_SECCOMP -static int vsyscall_seccomp(struct task_struct *tsk, int syscall_nr) -{ - if (!seccomp_mode(&tsk->seccomp)) - return 0; - task_pt_regs(tsk)->orig_ax = syscall_nr; - task_pt_regs(tsk)->ax = syscall_nr; - return __secure_computing(syscall_nr); -} -#else -#define vsyscall_seccomp(_tsk, _nr) 0 -#endif - static bool write_ok_or_segv(unsigned long ptr, size_t size) { /* @@ -187,7 +174,6 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) int vsyscall_nr; int prev_sig_on_uaccess_error; long ret; - int skip; /* * No point in checking CS -- the only way to get here is a user mode @@ -219,6 +205,9 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) } tsk = current; + if (seccomp_mode(&tsk->seccomp)) + do_exit(SIGKILL); + /* * With a real vsyscall, page faults cause SIGSEGV. We want to * preserve that behavior to make writing exploits harder. @@ -233,13 +222,8 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) * address 0". */ ret = -EFAULT; - skip = 0; switch (vsyscall_nr) { case 0: - skip = vsyscall_seccomp(tsk, __NR_gettimeofday); - if (skip) - break; - if (!write_ok_or_segv(regs->di, sizeof(struct timeval)) || !write_ok_or_segv(regs->si, sizeof(struct timezone))) break; @@ -250,10 +234,6 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) break; case 1: - skip = vsyscall_seccomp(tsk, __NR_time); - if (skip) - break; - if (!write_ok_or_segv(regs->di, sizeof(time_t))) break; @@ -261,10 +241,6 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) break; case 2: - skip = vsyscall_seccomp(tsk, __NR_getcpu); - if (skip) - break; - if (!write_ok_or_segv(regs->di, sizeof(unsigned)) || !write_ok_or_segv(regs->si, sizeof(unsigned))) break; @@ -277,12 +253,6 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) current_thread_info()->sig_on_uaccess_error = prev_sig_on_uaccess_error; - if (skip) { - if ((long)regs->ax <= 0L) /* seccomp errno emulation */ - goto do_ret; - goto done; /* seccomp trace/trap */ - } - if (ret == -EFAULT) { /* Bad news -- userspace fed a bad pointer to a vsyscall. */ warn_bad_vsyscall(KERN_INFO, regs, @@ -301,11 +271,10 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) regs->ax = ret; -do_ret: /* Emulate a ret instruction. */ regs->ip = caller; regs->sp += 8; -done: + return true; sigsegv: diff --git a/trunk/drivers/acpi/acpica/nspredef.c b/trunk/drivers/acpi/acpica/nspredef.c index fe6626035495..23ce09686418 100644 --- a/trunk/drivers/acpi/acpica/nspredef.c +++ b/trunk/drivers/acpi/acpica/nspredef.c @@ -638,7 +638,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data, /* Create the new outer package and populate it */ status = - acpi_ns_wrap_with_package(data, return_object, + acpi_ns_wrap_with_package(data, *elements, return_object_ptr); if (ACPI_FAILURE(status)) { return (status); diff --git a/trunk/drivers/acpi/processor_core.c b/trunk/drivers/acpi/processor_core.c index eff722278ff5..c850de4c9a14 100644 --- a/trunk/drivers/acpi/processor_core.c +++ b/trunk/drivers/acpi/processor_core.c @@ -189,12 +189,10 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) * Processor (CPU3, 0x03, 0x00000410, 0x06) {} * } * - * Ignores apic_id and always returns 0 for the processor - * handle with acpi id 0 if nr_cpu_ids is 1. - * This should be the case if SMP tables are not found. + * Ignores apic_id and always return 0 for CPU0's handle. * Return -1 for other CPU's handle. */ - if (nr_cpu_ids <= 1 && acpi_id == 0) + if (acpi_id == 0) return acpi_id; else return apic_id; diff --git a/trunk/drivers/block/loop.c b/trunk/drivers/block/loop.c index 3bba65510d23..bbca966f8f66 100644 --- a/trunk/drivers/block/loop.c +++ b/trunk/drivers/block/loop.c @@ -1597,12 +1597,14 @@ static int loop_add(struct loop_device **l, int i) struct gendisk *disk; int err; - err = -ENOMEM; lo = kzalloc(sizeof(*lo), GFP_KERNEL); - if (!lo) + if (!lo) { + err = -ENOMEM; goto out; + } - if (!idr_pre_get(&loop_index_idr, GFP_KERNEL)) + err = idr_pre_get(&loop_index_idr, GFP_KERNEL); + if (err < 0) goto out_free_dev; if (i >= 0) { diff --git a/trunk/drivers/char/agp/intel-agp.c b/trunk/drivers/char/agp/intel-agp.c index b130df0a1958..0a4185279417 100644 --- a/trunk/drivers/char/agp/intel-agp.c +++ b/trunk/drivers/char/agp/intel-agp.c @@ -12,7 +12,6 @@ #include #include "agp.h" #include "intel-agp.h" -#include int intel_agp_enabled; EXPORT_SYMBOL(intel_agp_enabled); @@ -748,7 +747,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, bridge->capndx = cap_ptr; - if (intel_gmch_probe(pdev, NULL, bridge)) + if (intel_gmch_probe(pdev, bridge)) goto found_gmch; for (i = 0; intel_agp_chipsets[i].name != NULL; i++) { @@ -825,7 +824,7 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev) agp_remove_bridge(bridge); - intel_gmch_remove(); + intel_gmch_remove(pdev); agp_put_bridge(bridge); } @@ -903,6 +902,17 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), + ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB), + ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB), + ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB), + ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_HB), + ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_HB), + ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB), + ID(PCI_DEVICE_ID_INTEL_VALLEYVIEW_HB), + ID(PCI_DEVICE_ID_INTEL_HASWELL_HB), + ID(PCI_DEVICE_ID_INTEL_HASWELL_M_HB), + ID(PCI_DEVICE_ID_INTEL_HASWELL_S_HB), + ID(PCI_DEVICE_ID_INTEL_HASWELL_E_HB), { } }; diff --git a/trunk/drivers/char/agp/intel-agp.h b/trunk/drivers/char/agp/intel-agp.h index 57226424690c..8e2d9140f300 100644 --- a/trunk/drivers/char/agp/intel-agp.h +++ b/trunk/drivers/char/agp/intel-agp.h @@ -251,4 +251,7 @@ #define PCI_DEVICE_ID_INTEL_HASWELL_SDV 0x0c16 /* SDV */ #define PCI_DEVICE_ID_INTEL_HASWELL_E_HB 0x0c04 +int intel_gmch_probe(struct pci_dev *pdev, + struct agp_bridge_data *bridge); +void intel_gmch_remove(struct pci_dev *pdev); #endif diff --git a/trunk/drivers/char/agp/intel-gtt.c b/trunk/drivers/char/agp/intel-gtt.c index 9ed92ef5829b..1237e7575c3f 100644 --- a/trunk/drivers/char/agp/intel-gtt.c +++ b/trunk/drivers/char/agp/intel-gtt.c @@ -66,6 +66,7 @@ static struct _intel_private { struct pci_dev *bridge_dev; u8 __iomem *registers; phys_addr_t gtt_bus_addr; + phys_addr_t gma_bus_addr; u32 PGETBL_save; u32 __iomem *gtt; /* I915G */ bool clear_fake_agp; /* on first access via agp, fill with scratch */ @@ -75,7 +76,6 @@ static struct _intel_private { struct resource ifp_resource; int resource_valid; struct page *scratch_page; - int refcount; } intel_private; #define INTEL_GTT_GEN intel_private.driver->gen @@ -648,7 +648,6 @@ static void intel_gtt_cleanup(void) static int intel_gtt_init(void) { - u32 gma_addr; u32 gtt_map_size; int ret; @@ -695,15 +694,6 @@ static int intel_gtt_init(void) return ret; } - if (INTEL_GTT_GEN <= 2) - pci_read_config_dword(intel_private.pcidev, I810_GMADDR, - &gma_addr); - else - pci_read_config_dword(intel_private.pcidev, I915_GMADDR, - &gma_addr); - - intel_private.base.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); - return 0; } @@ -777,10 +767,20 @@ static void i830_write_entry(dma_addr_t addr, unsigned int entry, writel(addr | pte_flags, intel_private.gtt + entry); } -bool intel_enable_gtt(void) +static bool intel_enable_gtt(void) { + u32 gma_addr; u8 __iomem *reg; + if (INTEL_GTT_GEN <= 2) + pci_read_config_dword(intel_private.pcidev, I810_GMADDR, + &gma_addr); + else + pci_read_config_dword(intel_private.pcidev, I915_GMADDR, + &gma_addr); + + intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); + if (INTEL_GTT_GEN >= 6) return true; @@ -823,7 +823,6 @@ bool intel_enable_gtt(void) return true; } -EXPORT_SYMBOL(intel_enable_gtt); static int i830_setup(void) { @@ -861,7 +860,7 @@ static int intel_fake_agp_configure(void) return -EIO; intel_private.clear_fake_agp = true; - agp_bridge->gart_bus_addr = intel_private.base.gma_bus_addr; + agp_bridge->gart_bus_addr = intel_private.gma_bus_addr; return 0; } @@ -1183,17 +1182,9 @@ static void gen6_write_entry(dma_addr_t addr, unsigned int entry, static void valleyview_write_entry(dma_addr_t addr, unsigned int entry, unsigned int flags) { - unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; - unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; u32 pte_flags; - if (type_mask == AGP_USER_MEMORY) - pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID; - else { - pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; - if (gfdt) - pte_flags |= GEN6_PTE_GFDT; - } + pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID; /* gen6 has bit11-4 for physical addr bit39-32 */ addr |= (addr >> 28) & 0xff0; @@ -1253,7 +1244,6 @@ static int i9xx_setup(void) switch (INTEL_GTT_GEN) { case 5: case 6: - case 7: gtt_offset = MB(2); break; case 4: @@ -1389,6 +1379,7 @@ static const struct intel_gtt_driver valleyview_gtt_driver = { .write_entry = valleyview_write_entry, .dma_mask_size = 40, .check_flags = gen6_check_flags, + .chipset_flush = i9xx_chipset_flush, }; /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of @@ -1532,32 +1523,14 @@ static int find_gmch(u16 device) return 1; } -int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, - struct agp_bridge_data *bridge) +int intel_gmch_probe(struct pci_dev *pdev, + struct agp_bridge_data *bridge) { int i, mask; - - /* - * Can be called from the fake agp driver but also directly from - * drm/i915.ko. Hence we need to check whether everything is set up - * already. - */ - if (intel_private.driver) { - intel_private.refcount++; - return 1; - } + intel_private.driver = NULL; for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) { - if (gpu_pdev) { - if (gpu_pdev->device == - intel_gtt_chipsets[i].gmch_chip_id) { - intel_private.pcidev = pci_dev_get(gpu_pdev); - intel_private.driver = - intel_gtt_chipsets[i].gtt_driver; - - break; - } - } else if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { + if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { intel_private.driver = intel_gtt_chipsets[i].gtt_driver; break; @@ -1567,17 +1540,13 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, if (!intel_private.driver) return 0; - intel_private.refcount++; - - if (bridge) { - bridge->driver = &intel_fake_agp_driver; - bridge->dev_private_data = &intel_private; - bridge->dev = bridge_pdev; - } + bridge->driver = &intel_fake_agp_driver; + bridge->dev_private_data = &intel_private; + bridge->dev = pdev; - intel_private.bridge_dev = pci_dev_get(bridge_pdev); + intel_private.bridge_dev = pci_dev_get(pdev); - dev_info(&bridge_pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); + dev_info(&pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); mask = intel_private.driver->dma_mask_size; if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) @@ -1587,11 +1556,11 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, pci_set_consistent_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask)); - if (intel_gtt_init() != 0) { - intel_gmch_remove(); + /*if (bridge->driver == &intel_810_driver) + return 1;*/ + if (intel_gtt_init() != 0) return 0; - } return 1; } @@ -1610,16 +1579,12 @@ void intel_gtt_chipset_flush(void) } EXPORT_SYMBOL(intel_gtt_chipset_flush); -void intel_gmch_remove(void) +void intel_gmch_remove(struct pci_dev *pdev) { - if (--intel_private.refcount) - return; - if (intel_private.pcidev) pci_dev_put(intel_private.pcidev); if (intel_private.bridge_dev) pci_dev_put(intel_private.bridge_dev); - intel_private.driver = NULL; } EXPORT_SYMBOL(intel_gmch_remove); diff --git a/trunk/drivers/gpu/drm/ast/ast_mode.c b/trunk/drivers/gpu/drm/ast/ast_mode.c index 7282c081fb53..65f9d231af14 100644 --- a/trunk/drivers/gpu/drm/ast/ast_mode.c +++ b/trunk/drivers/gpu/drm/ast/ast_mode.c @@ -460,8 +460,8 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) } static bool ast_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { return true; } @@ -680,7 +680,7 @@ static void ast_encoder_dpms(struct drm_encoder *encoder, int mode) } static bool ast_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; diff --git a/trunk/drivers/gpu/drm/cirrus/cirrus_mode.c b/trunk/drivers/gpu/drm/cirrus/cirrus_mode.c index a44d31aa4e3c..100f6308c509 100644 --- a/trunk/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/trunk/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -97,7 +97,7 @@ static void cirrus_crtc_dpms(struct drm_crtc *crtc, int mode) * to just pass that straight through, so this does nothing */ static bool cirrus_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; @@ -429,8 +429,8 @@ void cirrus_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, static bool cirrus_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { return true; } diff --git a/trunk/drivers/gpu/drm/drm_bufs.c b/trunk/drivers/gpu/drm/drm_bufs.c index b356c719f2f1..348b367debeb 100644 --- a/trunk/drivers/gpu/drm/drm_bufs.c +++ b/trunk/drivers/gpu/drm/drm_bufs.c @@ -641,6 +641,8 @@ int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request) if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL; + if (dev->queue_count) + return -EBUSY; /* Not while in use */ /* Make sure buffers are located in AGP memory that we own */ valid = 0; @@ -702,6 +704,7 @@ int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request) buf->next = NULL; buf->waiting = 0; buf->pending = 0; + init_waitqueue_head(&buf->dma_wait); buf->file_priv = NULL; buf->dev_priv_size = dev->driver->dev_priv_size; @@ -793,11 +796,13 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request) order = drm_order(request->size); size = 1 << order; - DRM_DEBUG("count=%d, size=%d (%d), order=%d\n", - request->count, request->size, size, order); + DRM_DEBUG("count=%d, size=%d (%d), order=%d, queue_count=%d\n", + request->count, request->size, size, order, dev->queue_count); if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL; + if (dev->queue_count) + return -EBUSY; /* Not while in use */ alignment = (request->flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size) : size; @@ -899,6 +904,7 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request) buf->next = NULL; buf->waiting = 0; buf->pending = 0; + init_waitqueue_head(&buf->dma_wait); buf->file_priv = NULL; buf->dev_priv_size = dev->driver->dev_priv_size; @@ -1013,6 +1019,8 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL; + if (dev->queue_count) + return -EBUSY; /* Not while in use */ spin_lock(&dev->count_lock); if (dev->buf_use) { @@ -1063,6 +1071,7 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request buf->next = NULL; buf->waiting = 0; buf->pending = 0; + init_waitqueue_head(&buf->dma_wait); buf->file_priv = NULL; buf->dev_priv_size = dev->driver->dev_priv_size; @@ -1168,6 +1177,8 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL; + if (dev->queue_count) + return -EBUSY; /* Not while in use */ spin_lock(&dev->count_lock); if (dev->buf_use) { @@ -1217,6 +1228,7 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request buf->next = NULL; buf->waiting = 0; buf->pending = 0; + init_waitqueue_head(&buf->dma_wait); buf->file_priv = NULL; buf->dev_priv_size = dev->driver->dev_priv_size; diff --git a/trunk/drivers/gpu/drm/drm_debugfs.c b/trunk/drivers/gpu/drm/drm_debugfs.c index 70b13fc19396..1c7a1c0d3edd 100644 --- a/trunk/drivers/gpu/drm/drm_debugfs.c +++ b/trunk/drivers/gpu/drm/drm_debugfs.c @@ -46,6 +46,7 @@ static struct drm_info_list drm_debugfs_list[] = { {"name", drm_name_info, 0}, {"vm", drm_vm_info, 0}, {"clients", drm_clients_info, 0}, + {"queues", drm_queues_info, 0}, {"bufs", drm_bufs_info, 0}, {"gem_names", drm_gem_name_info, DRIVER_GEM}, #if DRM_DEBUG_CODE diff --git a/trunk/drivers/gpu/drm/drm_dma.c b/trunk/drivers/gpu/drm/drm_dma.c index 08f5e5309b22..cfb4e333ec0f 100644 --- a/trunk/drivers/gpu/drm/drm_dma.c +++ b/trunk/drivers/gpu/drm/drm_dma.c @@ -120,6 +120,11 @@ void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf) buf->pending = 0; buf->file_priv = NULL; buf->used = 0; + + if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) + && waitqueue_active(&buf->dma_wait)) { + wake_up_interruptible(&buf->dma_wait); + } } /** diff --git a/trunk/drivers/gpu/drm/drm_drv.c b/trunk/drivers/gpu/drm/drm_drv.c index 9238de4009fa..8a9d0792e4ec 100644 --- a/trunk/drivers/gpu/drm/drm_drv.c +++ b/trunk/drivers/gpu/drm/drm_drv.c @@ -182,6 +182,7 @@ static struct drm_ioctl_desc drm_ioctls[] = { int drm_lastclose(struct drm_device * dev) { struct drm_vma_entry *vma, *vma_temp; + int i; DRM_DEBUG("\n"); @@ -227,6 +228,16 @@ int drm_lastclose(struct drm_device * dev) kfree(vma); } + if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) { + for (i = 0; i < dev->queue_count; i++) { + kfree(dev->queuelist[i]); + dev->queuelist[i] = NULL; + } + kfree(dev->queuelist); + dev->queuelist = NULL; + } + dev->queue_count = 0; + if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && !drm_core_check_feature(dev, DRIVER_MODESET)) drm_dma_takedown(dev); @@ -475,7 +486,7 @@ long drm_ioctl(struct file *filp, kfree(kdata); atomic_dec(&dev->ioctl_count); if (retcode) - DRM_DEBUG("ret = %d\n", retcode); + DRM_DEBUG("ret = %x\n", retcode); return retcode; } diff --git a/trunk/drivers/gpu/drm/drm_fb_helper.c b/trunk/drivers/gpu/drm/drm_fb_helper.c index f546d1e8af82..5683b7fdd746 100644 --- a/trunk/drivers/gpu/drm/drm_fb_helper.c +++ b/trunk/drivers/gpu/drm/drm_fb_helper.c @@ -228,7 +228,7 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) int i, ret; for (i = 0; i < fb_helper->crtc_count; i++) { struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; - ret = mode_set->crtc->funcs->set_config(mode_set); + ret = drm_crtc_helper_set_config(mode_set); if (ret) error = true; } @@ -1353,7 +1353,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) struct drm_device *dev = fb_helper->dev; int count = 0; u32 max_width, max_height, bpp_sel; - int bound = 0, crtcs_bound = 0; + bool bound = false, crtcs_bound = false; struct drm_crtc *crtc; if (!fb_helper->fb) @@ -1362,12 +1362,12 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) mutex_lock(&dev->mode_config.mutex); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (crtc->fb) - crtcs_bound++; + crtcs_bound = true; if (crtc->fb == fb_helper->fb) - bound++; + bound = true; } - if (bound < crtcs_bound) { + if (!bound && crtcs_bound) { fb_helper->delayed_hotplug = true; mutex_unlock(&dev->mode_config.mutex); return 0; diff --git a/trunk/drivers/gpu/drm/drm_fops.c b/trunk/drivers/gpu/drm/drm_fops.c index 5062eec673f1..123de28f94ef 100644 --- a/trunk/drivers/gpu/drm/drm_fops.c +++ b/trunk/drivers/gpu/drm/drm_fops.c @@ -75,6 +75,10 @@ static int drm_setup(struct drm_device * dev) dev->sigdata.lock = NULL; + dev->queue_count = 0; + dev->queue_reserved = 0; + dev->queue_slots = 0; + dev->queuelist = NULL; dev->context_flag = 0; dev->interrupt_flag = 0; dev->dma_flag = 0; @@ -140,12 +144,12 @@ int drm_open(struct inode *inode, struct file *filp) } if (!retcode) { mutex_lock(&dev->struct_mutex); - if (dev->dev_mapping == NULL) - dev->dev_mapping = &inode->i_data; - /* ihold ensures nobody can remove inode with our i_data */ - ihold(container_of(dev->dev_mapping, struct inode, i_data)); - inode->i_mapping = dev->dev_mapping; - filp->f_mapping = dev->dev_mapping; + if (minor->type == DRM_MINOR_LEGACY) { + if (dev->dev_mapping == NULL) + dev->dev_mapping = inode->i_mapping; + else if (dev->dev_mapping != inode->i_mapping) + retcode = -ENODEV; + } mutex_unlock(&dev->struct_mutex); } @@ -366,16 +370,72 @@ int drm_fasync(int fd, struct file *filp, int on) } EXPORT_SYMBOL(drm_fasync); +/* + * Reclaim locked buffers; note that this may be a bad idea if the current + * context doesn't have the hw lock... + */ +static void drm_reclaim_locked_buffers(struct drm_device *dev, struct file *f) +{ + struct drm_file *file_priv = f->private_data; + + if (drm_i_have_hw_lock(dev, file_priv)) { + dev->driver->reclaim_buffers_locked(dev, file_priv); + } else { + unsigned long _end = jiffies + 3 * DRM_HZ; + int locked = 0; + + drm_idlelock_take(&file_priv->master->lock); + + /* + * Wait for a while. + */ + do { + spin_lock_bh(&file_priv->master->lock.spinlock); + locked = file_priv->master->lock.idle_has_lock; + spin_unlock_bh(&file_priv->master->lock.spinlock); + if (locked) + break; + schedule(); + } while (!time_after_eq(jiffies, _end)); + + if (!locked) { + DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n" + "\tdriver to use reclaim_buffers_idlelocked() instead.\n" + "\tI will go on reclaiming the buffers anyway.\n"); + } + + dev->driver->reclaim_buffers_locked(dev, file_priv); + drm_idlelock_release(&file_priv->master->lock); + } +} + static void drm_master_release(struct drm_device *dev, struct file *filp) { struct drm_file *file_priv = filp->private_data; + if (dev->driver->reclaim_buffers_locked && + file_priv->master->lock.hw_lock) + drm_reclaim_locked_buffers(dev, filp); + + if (dev->driver->reclaim_buffers_idlelocked && + file_priv->master->lock.hw_lock) { + drm_idlelock_take(&file_priv->master->lock); + dev->driver->reclaim_buffers_idlelocked(dev, file_priv); + drm_idlelock_release(&file_priv->master->lock); + } + + if (drm_i_have_hw_lock(dev, file_priv)) { DRM_DEBUG("File %p released, freeing lock for context %d\n", filp, _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock)); drm_lock_free(&file_priv->master->lock, _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock)); } + + if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && + !dev->driver->reclaim_buffers_locked) { + dev->driver->reclaim_buffers(dev, file_priv); + } } static void drm_events_release(struct drm_file *file_priv) @@ -445,9 +505,6 @@ int drm_release(struct inode *inode, struct file *filp) if (file_priv->minor->master) drm_master_release(dev, filp); - if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) - drm_core_reclaim_buffers(dev, file_priv); - drm_events_release(file_priv); if (dev->driver->driver_features & DRIVER_MODESET) @@ -509,9 +566,6 @@ int drm_release(struct inode *inode, struct file *filp) } } - BUG_ON(dev->dev_mapping == NULL); - iput(container_of(dev->dev_mapping, struct inode, i_data)); - /* drop the reference held my the file priv */ drm_master_put(&file_priv->master); file_priv->is_master = 0; diff --git a/trunk/drivers/gpu/drm/drm_gem.c b/trunk/drivers/gpu/drm/drm_gem.c index fbe0842038b5..d58e69da1fb5 100644 --- a/trunk/drivers/gpu/drm/drm_gem.c +++ b/trunk/drivers/gpu/drm/drm_gem.c @@ -354,7 +354,7 @@ drm_gem_create_mmap_offset(struct drm_gem_object *obj) /* Get a DRM GEM mmap offset allocated... */ list->file_offset_node = drm_mm_search_free(&mm->offset_manager, - obj->size / PAGE_SIZE, 0, false); + obj->size / PAGE_SIZE, 0, 0); if (!list->file_offset_node) { DRM_ERROR("failed to allocate offset for bo %d\n", obj->name); diff --git a/trunk/drivers/gpu/drm/drm_info.c b/trunk/drivers/gpu/drm/drm_info.c index 8928edbb94c7..ab1162da70f8 100644 --- a/trunk/drivers/gpu/drm/drm_info.c +++ b/trunk/drivers/gpu/drm/drm_info.c @@ -109,6 +109,42 @@ int drm_vm_info(struct seq_file *m, void *data) return 0; } +/** + * Called when "/proc/dri/.../queues" is read. + */ +int drm_queues_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + int i; + struct drm_queue *q; + + mutex_lock(&dev->struct_mutex); + seq_printf(m, " ctx/flags use fin" + " blk/rw/rwf wait flushed queued" + " locks\n\n"); + for (i = 0; i < dev->queue_count; i++) { + q = dev->queuelist[i]; + atomic_inc(&q->use_count); + seq_printf(m, "%5d/0x%03x %5d %5d" + " %5d/%c%c/%c%c%c %5Zd\n", + i, + q->flags, + atomic_read(&q->use_count), + atomic_read(&q->finalization), + atomic_read(&q->block_count), + atomic_read(&q->block_read) ? 'r' : '-', + atomic_read(&q->block_write) ? 'w' : '-', + waitqueue_active(&q->read_queue) ? 'r' : '-', + waitqueue_active(&q->write_queue) ? 'w' : '-', + waitqueue_active(&q->flush_queue) ? 'f' : '-', + DRM_BUFCOUNT(&q->waitlist)); + atomic_dec(&q->use_count); + } + mutex_unlock(&dev->struct_mutex); + return 0; +} + /** * Called when "/proc/dri/.../bufs" is read. */ @@ -199,7 +235,7 @@ int drm_clients_info(struct seq_file *m, void *data) } -static int drm_gem_one_name_info(int id, void *ptr, void *data) +int drm_gem_one_name_info(int id, void *ptr, void *data) { struct drm_gem_object *obj = ptr; struct seq_file *m = data; diff --git a/trunk/drivers/gpu/drm/drm_irq.c b/trunk/drivers/gpu/drm/drm_irq.c index 03f16f352fe2..c798eeae0a03 100644 --- a/trunk/drivers/gpu/drm/drm_irq.c +++ b/trunk/drivers/gpu/drm/drm_irq.c @@ -974,6 +974,7 @@ EXPORT_SYMBOL(drm_vblank_off); * drm_vblank_pre_modeset - account for vblanks across mode sets * @dev: DRM device * @crtc: CRTC in question + * @post: post or pre mode set? * * Account for vblank events across mode setting events, which will likely * reset the hardware frame counter. @@ -1036,10 +1037,6 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, if (!dev->num_crtcs) return 0; - /* KMS drivers handle this internally */ - if (drm_core_check_feature(dev, DRIVER_MODESET)) - return 0; - crtc = modeset->crtc; if (crtc >= dev->num_crtcs) return -EINVAL; diff --git a/trunk/drivers/gpu/drm/drm_lock.c b/trunk/drivers/gpu/drm/drm_lock.c index 32039553e172..521152041691 100644 --- a/trunk/drivers/gpu/drm/drm_lock.c +++ b/trunk/drivers/gpu/drm/drm_lock.c @@ -70,6 +70,10 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) lock->context, task_pid_nr(current), master->lock.hw_lock->lock, lock->flags); + if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE)) + if (lock->context < 0) + return -EINVAL; + add_wait_queue(&master->lock.lock_queue, &entry); spin_lock_bh(&master->lock.spinlock); master->lock.user_waiters++; diff --git a/trunk/drivers/gpu/drm/drm_mm.c b/trunk/drivers/gpu/drm/drm_mm.c index 9bb82f7f0061..961fb54f4266 100644 --- a/trunk/drivers/gpu/drm/drm_mm.c +++ b/trunk/drivers/gpu/drm/drm_mm.c @@ -118,53 +118,45 @@ static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node) static void drm_mm_insert_helper(struct drm_mm_node *hole_node, struct drm_mm_node *node, - unsigned long size, unsigned alignment, - unsigned long color) + unsigned long size, unsigned alignment) { struct drm_mm *mm = hole_node->mm; + unsigned long tmp = 0, wasted = 0; unsigned long hole_start = drm_mm_hole_node_start(hole_node); unsigned long hole_end = drm_mm_hole_node_end(hole_node); - unsigned long adj_start = hole_start; - unsigned long adj_end = hole_end; BUG_ON(!hole_node->hole_follows || node->allocated); - if (mm->color_adjust) - mm->color_adjust(hole_node, color, &adj_start, &adj_end); + if (alignment) + tmp = hole_start % alignment; - if (alignment) { - unsigned tmp = adj_start % alignment; - if (tmp) - adj_start += alignment - tmp; - } - - if (adj_start == hole_start) { + if (!tmp) { hole_node->hole_follows = 0; - list_del(&hole_node->hole_stack); - } + list_del_init(&hole_node->hole_stack); + } else + wasted = alignment - tmp; - node->start = adj_start; + node->start = hole_start + wasted; node->size = size; node->mm = mm; - node->color = color; node->allocated = 1; INIT_LIST_HEAD(&node->hole_stack); list_add(&node->node_list, &hole_node->node_list); - BUG_ON(node->start + node->size > adj_end); + BUG_ON(node->start + node->size > hole_end); - node->hole_follows = 0; if (node->start + node->size < hole_end) { list_add(&node->hole_stack, &mm->hole_stack); node->hole_follows = 1; + } else { + node->hole_follows = 0; } } struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node, unsigned long size, unsigned alignment, - unsigned long color, int atomic) { struct drm_mm_node *node; @@ -173,7 +165,7 @@ struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node, if (unlikely(node == NULL)) return NULL; - drm_mm_insert_helper(hole_node, node, size, alignment, color); + drm_mm_insert_helper(hole_node, node, size, alignment); return node; } @@ -189,11 +181,11 @@ int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, { struct drm_mm_node *hole_node; - hole_node = drm_mm_search_free(mm, size, alignment, false); + hole_node = drm_mm_search_free(mm, size, alignment, 0); if (!hole_node) return -ENOSPC; - drm_mm_insert_helper(hole_node, node, size, alignment, 0); + drm_mm_insert_helper(hole_node, node, size, alignment); return 0; } @@ -202,57 +194,50 @@ EXPORT_SYMBOL(drm_mm_insert_node); static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, struct drm_mm_node *node, unsigned long size, unsigned alignment, - unsigned long color, unsigned long start, unsigned long end) { struct drm_mm *mm = hole_node->mm; + unsigned long tmp = 0, wasted = 0; unsigned long hole_start = drm_mm_hole_node_start(hole_node); unsigned long hole_end = drm_mm_hole_node_end(hole_node); - unsigned long adj_start = hole_start; - unsigned long adj_end = hole_end; BUG_ON(!hole_node->hole_follows || node->allocated); - if (mm->color_adjust) - mm->color_adjust(hole_node, color, &adj_start, &adj_end); + if (hole_start < start) + wasted += start - hole_start; + if (alignment) + tmp = (hole_start + wasted) % alignment; - if (adj_start < start) - adj_start = start; - - if (alignment) { - unsigned tmp = adj_start % alignment; - if (tmp) - adj_start += alignment - tmp; - } + if (tmp) + wasted += alignment - tmp; - if (adj_start == hole_start) { + if (!wasted) { hole_node->hole_follows = 0; - list_del(&hole_node->hole_stack); + list_del_init(&hole_node->hole_stack); } - node->start = adj_start; + node->start = hole_start + wasted; node->size = size; node->mm = mm; - node->color = color; node->allocated = 1; INIT_LIST_HEAD(&node->hole_stack); list_add(&node->node_list, &hole_node->node_list); - BUG_ON(node->start + node->size > adj_end); + BUG_ON(node->start + node->size > hole_end); BUG_ON(node->start + node->size > end); - node->hole_follows = 0; if (node->start + node->size < hole_end) { list_add(&node->hole_stack, &mm->hole_stack); node->hole_follows = 1; + } else { + node->hole_follows = 0; } } struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node, unsigned long size, unsigned alignment, - unsigned long color, unsigned long start, unsigned long end, int atomic) @@ -263,7 +248,7 @@ struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node if (unlikely(node == NULL)) return NULL; - drm_mm_insert_helper_range(hole_node, node, size, alignment, color, + drm_mm_insert_helper_range(hole_node, node, size, alignment, start, end); return node; @@ -282,11 +267,11 @@ int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node, struct drm_mm_node *hole_node; hole_node = drm_mm_search_free_in_range(mm, size, alignment, - start, end, false); + start, end, 0); if (!hole_node) return -ENOSPC; - drm_mm_insert_helper_range(hole_node, node, size, alignment, 0, + drm_mm_insert_helper_range(hole_node, node, size, alignment, start, end); return 0; @@ -351,23 +336,27 @@ EXPORT_SYMBOL(drm_mm_put_block); static int check_free_hole(unsigned long start, unsigned long end, unsigned long size, unsigned alignment) { + unsigned wasted = 0; + if (end - start < size) return 0; if (alignment) { unsigned tmp = start % alignment; if (tmp) - start += alignment - tmp; + wasted = alignment - tmp; + } + + if (end >= start + size + wasted) { + return 1; } - return end >= start + size; + return 0; } -struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, - unsigned long size, - unsigned alignment, - unsigned long color, - bool best_match) +struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, + unsigned long size, + unsigned alignment, int best_match) { struct drm_mm_node *entry; struct drm_mm_node *best; @@ -379,17 +368,10 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, best_size = ~0UL; list_for_each_entry(entry, &mm->hole_stack, hole_stack) { - unsigned long adj_start = drm_mm_hole_node_start(entry); - unsigned long adj_end = drm_mm_hole_node_end(entry); - - if (mm->color_adjust) { - mm->color_adjust(entry, color, &adj_start, &adj_end); - if (adj_end <= adj_start) - continue; - } - BUG_ON(!entry->hole_follows); - if (!check_free_hole(adj_start, adj_end, size, alignment)) + if (!check_free_hole(drm_mm_hole_node_start(entry), + drm_mm_hole_node_end(entry), + size, alignment)) continue; if (!best_match) @@ -403,15 +385,14 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, return best; } -EXPORT_SYMBOL(drm_mm_search_free_generic); - -struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm, - unsigned long size, - unsigned alignment, - unsigned long color, - unsigned long start, - unsigned long end, - bool best_match) +EXPORT_SYMBOL(drm_mm_search_free); + +struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, + unsigned long size, + unsigned alignment, + unsigned long start, + unsigned long end, + int best_match) { struct drm_mm_node *entry; struct drm_mm_node *best; @@ -429,13 +410,6 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm, end : drm_mm_hole_node_end(entry); BUG_ON(!entry->hole_follows); - - if (mm->color_adjust) { - mm->color_adjust(entry, color, &adj_start, &adj_end); - if (adj_end <= adj_start) - continue; - } - if (!check_free_hole(adj_start, adj_end, size, alignment)) continue; @@ -450,7 +424,7 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm, return best; } -EXPORT_SYMBOL(drm_mm_search_free_in_range_generic); +EXPORT_SYMBOL(drm_mm_search_free_in_range); /** * Moves an allocation. To be used with embedded struct drm_mm_node. @@ -463,7 +437,6 @@ void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new) new->mm = old->mm; new->start = old->start; new->size = old->size; - new->color = old->color; old->allocated = 0; new->allocated = 1; @@ -479,12 +452,9 @@ EXPORT_SYMBOL(drm_mm_replace_node); * Warning: As long as the scan list is non-empty, no other operations than * adding/removing nodes to/from the scan list are allowed. */ -void drm_mm_init_scan(struct drm_mm *mm, - unsigned long size, - unsigned alignment, - unsigned long color) +void drm_mm_init_scan(struct drm_mm *mm, unsigned long size, + unsigned alignment) { - mm->scan_color = color; mm->scan_alignment = alignment; mm->scan_size = size; mm->scanned_blocks = 0; @@ -504,14 +474,11 @@ EXPORT_SYMBOL(drm_mm_init_scan); * Warning: As long as the scan list is non-empty, no other operations than * adding/removing nodes to/from the scan list are allowed. */ -void drm_mm_init_scan_with_range(struct drm_mm *mm, - unsigned long size, +void drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size, unsigned alignment, - unsigned long color, unsigned long start, unsigned long end) { - mm->scan_color = color; mm->scan_alignment = alignment; mm->scan_size = size; mm->scanned_blocks = 0; @@ -555,21 +522,17 @@ int drm_mm_scan_add_block(struct drm_mm_node *node) hole_start = drm_mm_hole_node_start(prev_node); hole_end = drm_mm_hole_node_end(prev_node); - - adj_start = hole_start; - adj_end = hole_end; - - if (mm->color_adjust) - mm->color_adjust(prev_node, mm->scan_color, &adj_start, &adj_end); - if (mm->scan_check_range) { - if (adj_start < mm->scan_start) - adj_start = mm->scan_start; - if (adj_end > mm->scan_end) - adj_end = mm->scan_end; + adj_start = hole_start < mm->scan_start ? + mm->scan_start : hole_start; + adj_end = hole_end > mm->scan_end ? + mm->scan_end : hole_end; + } else { + adj_start = hole_start; + adj_end = hole_end; } - if (check_free_hole(adj_start, adj_end, + if (check_free_hole(adj_start , adj_end, mm->scan_size, mm->scan_alignment)) { mm->scan_hit_start = hole_start; mm->scan_hit_size = hole_end; @@ -653,8 +616,6 @@ int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size) mm->head_node.size = start - mm->head_node.start; list_add_tail(&mm->head_node.hole_stack, &mm->hole_stack); - mm->color_adjust = NULL; - return 0; } EXPORT_SYMBOL(drm_mm_init); diff --git a/trunk/drivers/gpu/drm/drm_pci.c b/trunk/drivers/gpu/drm/drm_pci.c index 5320364582ce..13f3d936472f 100644 --- a/trunk/drivers/gpu/drm/drm_pci.c +++ b/trunk/drivers/gpu/drm/drm_pci.c @@ -465,52 +465,3 @@ void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver) DRM_INFO("Module unloaded\n"); } EXPORT_SYMBOL(drm_pci_exit); - -int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask) -{ - struct pci_dev *root; - int pos; - u32 lnkcap, lnkcap2; - - *mask = 0; - if (!dev->pdev) - return -EINVAL; - - if (!pci_is_pcie(dev->pdev)) - return -EINVAL; - - root = dev->pdev->bus->self; - - pos = pci_pcie_cap(root); - if (!pos) - return -EINVAL; - - /* we've been informed via and serverworks don't make the cut */ - if (root->vendor == PCI_VENDOR_ID_VIA || - root->vendor == PCI_VENDOR_ID_SERVERWORKS) - return -EINVAL; - - pci_read_config_dword(root, pos + PCI_EXP_LNKCAP, &lnkcap); - pci_read_config_dword(root, pos + PCI_EXP_LNKCAP2, &lnkcap2); - - lnkcap &= PCI_EXP_LNKCAP_SLS; - lnkcap2 &= 0xfe; - - if (lnkcap2) { /* PCIE GEN 3.0 */ - if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB) - *mask |= DRM_PCIE_SPEED_25; - if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB) - *mask |= DRM_PCIE_SPEED_50; - if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB) - *mask |= DRM_PCIE_SPEED_80; - } else { - if (lnkcap & 1) - *mask |= DRM_PCIE_SPEED_25; - if (lnkcap & 2) - *mask |= DRM_PCIE_SPEED_50; - } - - DRM_INFO("probing gen 2 caps for device %x:%x = %x/%x\n", root->vendor, root->device, lnkcap, lnkcap2); - return 0; -} -EXPORT_SYMBOL(drm_pcie_get_speed_cap_mask); diff --git a/trunk/drivers/gpu/drm/drm_proc.c b/trunk/drivers/gpu/drm/drm_proc.c index 371c695322d9..fff87221f9e9 100644 --- a/trunk/drivers/gpu/drm/drm_proc.c +++ b/trunk/drivers/gpu/drm/drm_proc.c @@ -53,6 +53,7 @@ static struct drm_info_list drm_proc_list[] = { {"name", drm_name_info, 0}, {"vm", drm_vm_info, 0}, {"clients", drm_clients_info, 0}, + {"queues", drm_queues_info, 0}, {"bufs", drm_bufs_info, 0}, {"gem_names", drm_gem_name_info, DRIVER_GEM}, #if DRM_DEBUG_CODE diff --git a/trunk/drivers/gpu/drm/drm_sysfs.c b/trunk/drivers/gpu/drm/drm_sysfs.c index 45ac8d6c92b7..45cf1dd3eb9c 100644 --- a/trunk/drivers/gpu/drm/drm_sysfs.c +++ b/trunk/drivers/gpu/drm/drm_sysfs.c @@ -134,7 +134,6 @@ void drm_sysfs_destroy(void) return; class_remove_file(drm_class, &class_attr_version.attr); class_destroy(drm_class); - drm_class = NULL; } /** @@ -555,9 +554,6 @@ void drm_sysfs_device_remove(struct drm_minor *minor) int drm_class_device_register(struct device *dev) { - if (!drm_class || IS_ERR(drm_class)) - return -ENOENT; - dev->class = drm_class; return device_register(dev); } diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 32a34c85899b..4afb625128d7 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -237,7 +237,7 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc) static bool exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { DRM_DEBUG_KMS("%s\n", __FILE__); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.h index 277653d5fda0..c82c90c443e7 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -174,7 +174,7 @@ struct exynos_drm_manager_ops { void (*apply)(struct device *subdrv_dev); void (*mode_fixup)(struct device *subdrv_dev, struct drm_connector *connector, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); void (*mode_set)(struct device *subdrv_dev, void *mode); void (*get_max_resol)(struct device *subdrv_dev, unsigned int *width, diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 4a13a747f5d4..23d5ad379f86 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -108,7 +108,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) static bool exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index 8ffcdf8b9e22..5d9d2c2f8f3f 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.c @@ -142,7 +142,7 @@ static void drm_hdmi_disable_vblank(struct device *subdrv_dev) static void drm_hdmi_mode_fixup(struct device *subdrv_dev, struct drm_connector *connector, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct drm_hdmi_context *ctx = to_context(subdrv_dev); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.h index a91c42088e42..bd8126996e52 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.h +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.h @@ -51,7 +51,7 @@ struct exynos_hdmi_ops { /* manager */ void (*mode_fixup)(void *ctx, struct drm_connector *connector, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); void (*mode_set)(void *ctx, void *mode); void (*get_max_resol)(void *ctx, unsigned int *width, diff --git a/trunk/drivers/gpu/drm/exynos/exynos_hdmi.c b/trunk/drivers/gpu/drm/exynos/exynos_hdmi.c index 066bde3f19c4..a137e9e39a33 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -1940,7 +1940,7 @@ static void hdmi_conf_apply(struct hdmi_context *hdata) } static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct drm_display_mode *m; diff --git a/trunk/drivers/gpu/drm/gma500/cdv_intel_crt.c b/trunk/drivers/gpu/drm/gma500/cdv_intel_crt.c index 8c175345d85c..187422018601 100644 --- a/trunk/drivers/gpu/drm/gma500/cdv_intel_crt.c +++ b/trunk/drivers/gpu/drm/gma500/cdv_intel_crt.c @@ -82,7 +82,7 @@ static int cdv_intel_crt_mode_valid(struct drm_connector *connector, } static bool cdv_intel_crt_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; diff --git a/trunk/drivers/gpu/drm/gma500/cdv_intel_display.c b/trunk/drivers/gpu/drm/gma500/cdv_intel_display.c index a68509ba22a8..c3e9a0f701df 100644 --- a/trunk/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/trunk/drivers/gpu/drm/gma500/cdv_intel_display.c @@ -913,7 +913,7 @@ static void cdv_intel_crtc_commit(struct drm_crtc *crtc) } static bool cdv_intel_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; diff --git a/trunk/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/trunk/drivers/gpu/drm/gma500/cdv_intel_hdmi.c index a86f87b9ddde..88b59d4a7b7f 100644 --- a/trunk/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +++ b/trunk/drivers/gpu/drm/gma500/cdv_intel_hdmi.c @@ -90,7 +90,7 @@ static void cdv_hdmi_mode_set(struct drm_encoder *encoder, } static bool cdv_hdmi_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; diff --git a/trunk/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/trunk/drivers/gpu/drm/gma500/cdv_intel_lvds.c index c7f9468b74ba..ff5b58eb878c 100644 --- a/trunk/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/trunk/drivers/gpu/drm/gma500/cdv_intel_lvds.c @@ -270,7 +270,7 @@ static int cdv_intel_lvds_mode_valid(struct drm_connector *connector, } static bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; diff --git a/trunk/drivers/gpu/drm/gma500/intel_bios.c b/trunk/drivers/gpu/drm/gma500/intel_bios.c index 8d7caf0f363e..973d7f6d66b7 100644 --- a/trunk/drivers/gpu/drm/gma500/intel_bios.c +++ b/trunk/drivers/gpu/drm/gma500/intel_bios.c @@ -427,7 +427,7 @@ parse_device_mapping(struct drm_psb_private *dev_priv, * * Returns 0 on success, nonzero on failure. */ -int psb_intel_init_bios(struct drm_device *dev) +bool psb_intel_init_bios(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; struct pci_dev *pdev = dev->pdev; diff --git a/trunk/drivers/gpu/drm/gma500/intel_bios.h b/trunk/drivers/gpu/drm/gma500/intel_bios.h index 2e95523b84b1..0a738663eb5a 100644 --- a/trunk/drivers/gpu/drm/gma500/intel_bios.h +++ b/trunk/drivers/gpu/drm/gma500/intel_bios.h @@ -431,7 +431,7 @@ struct bdb_driver_features { u8 custom_vbt_version; } __attribute__((packed)); -extern int psb_intel_init_bios(struct drm_device *dev); +extern bool psb_intel_init_bios(struct drm_device *dev); extern void psb_intel_destroy_bios(struct drm_device *dev); /* diff --git a/trunk/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c b/trunk/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c index d4813e03f5ee..b34ff097b979 100644 --- a/trunk/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c +++ b/trunk/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c @@ -684,7 +684,7 @@ void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode) } bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); diff --git a/trunk/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h b/trunk/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h index 2b40663e1696..6f762478b959 100644 --- a/trunk/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h +++ b/trunk/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, /* MDFLD DPI helper functions */ extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode); extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder); extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder); diff --git a/trunk/drivers/gpu/drm/gma500/mdfld_intel_display.c b/trunk/drivers/gpu/drm/gma500/mdfld_intel_display.c index dec6a9aea3c6..3f3cd619c79f 100644 --- a/trunk/drivers/gpu/drm/gma500/mdfld_intel_display.c +++ b/trunk/drivers/gpu/drm/gma500/mdfld_intel_display.c @@ -117,7 +117,7 @@ static void psb_intel_crtc_commit(struct drm_crtc *crtc) } static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; diff --git a/trunk/drivers/gpu/drm/gma500/oaktrail_crtc.c b/trunk/drivers/gpu/drm/gma500/oaktrail_crtc.c index cdafd2acc72f..f821c835ca90 100644 --- a/trunk/drivers/gpu/drm/gma500/oaktrail_crtc.c +++ b/trunk/drivers/gpu/drm/gma500/oaktrail_crtc.c @@ -487,7 +487,7 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, } static bool oaktrail_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; diff --git a/trunk/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/trunk/drivers/gpu/drm/gma500/oaktrail_hdmi.c index 2eb3dc4e9c9b..c10899c953b9 100644 --- a/trunk/drivers/gpu/drm/gma500/oaktrail_hdmi.c +++ b/trunk/drivers/gpu/drm/gma500/oaktrail_hdmi.c @@ -191,7 +191,7 @@ static int oaktrail_hdmi_mode_valid(struct drm_connector *connector, } static bool oaktrail_hdmi_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; diff --git a/trunk/drivers/gpu/drm/gma500/psb_drv.c b/trunk/drivers/gpu/drm/gma500/psb_drv.c index cd1dd1b14c76..caba6e08693c 100644 --- a/trunk/drivers/gpu/drm/gma500/psb_drv.c +++ b/trunk/drivers/gpu/drm/gma500/psb_drv.c @@ -632,6 +632,7 @@ static struct drm_driver driver = { .open = psb_driver_open, .preclose = psb_driver_preclose, .postclose = psb_driver_close, + .reclaim_buffers = drm_core_reclaim_buffers, .gem_init_object = psb_gem_init_object, .gem_free_object = psb_gem_free_object, diff --git a/trunk/drivers/gpu/drm/gma500/psb_intel_display.c b/trunk/drivers/gpu/drm/gma500/psb_intel_display.c index 30dc22a7156c..36c3c99612f6 100644 --- a/trunk/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/trunk/drivers/gpu/drm/gma500/psb_intel_display.c @@ -543,7 +543,7 @@ void psb_intel_encoder_destroy(struct drm_encoder *encoder) } static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; diff --git a/trunk/drivers/gpu/drm/gma500/psb_intel_drv.h b/trunk/drivers/gpu/drm/gma500/psb_intel_drv.h index ebe1a28f60e1..2515f83248cb 100644 --- a/trunk/drivers/gpu/drm/gma500/psb_intel_drv.h +++ b/trunk/drivers/gpu/drm/gma500/psb_intel_drv.h @@ -268,7 +268,7 @@ extern struct drm_framebuffer *psb_intel_framebuffer_create(struct drm_device *mode_cmd, void *mm_private); extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); extern int psb_intel_lvds_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode); diff --git a/trunk/drivers/gpu/drm/gma500/psb_intel_lvds.c b/trunk/drivers/gpu/drm/gma500/psb_intel_lvds.c index 37adc9edf974..c83f5b5d1057 100644 --- a/trunk/drivers/gpu/drm/gma500/psb_intel_lvds.c +++ b/trunk/drivers/gpu/drm/gma500/psb_intel_lvds.c @@ -375,7 +375,7 @@ int psb_intel_lvds_mode_valid(struct drm_connector *connector, } bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; diff --git a/trunk/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/trunk/drivers/gpu/drm/gma500/psb_intel_sdvo.c index 0466c7b985f8..d39b15be7649 100644 --- a/trunk/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/trunk/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) static bool psb_intel_sdvo_set_output_timings_from_mode(struct psb_intel_sdvo *psb_intel_sdvo, - const struct drm_display_mode *mode) + struct drm_display_mode *mode) { struct psb_intel_sdvo_dtd output_dtd; @@ -918,7 +918,7 @@ psb_intel_sdvo_set_output_timings_from_mode(struct psb_intel_sdvo *psb_intel_sdv static bool psb_intel_sdvo_set_input_timings_for_mode(struct psb_intel_sdvo *psb_intel_sdvo, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { /* 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, } static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder); diff --git a/trunk/drivers/gpu/drm/i2c/ch7006_drv.c b/trunk/drivers/gpu/drm/i2c/ch7006_drv.c index 36d952280c50..d3f2e8785010 100644 --- a/trunk/drivers/gpu/drm/i2c/ch7006_drv.c +++ b/trunk/drivers/gpu/drm/i2c/ch7006_drv.c @@ -88,7 +88,7 @@ static void ch7006_encoder_restore(struct drm_encoder *encoder) } static bool ch7006_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct ch7006_priv *priv = to_ch7006_priv(encoder); diff --git a/trunk/drivers/gpu/drm/i2c/ch7006_mode.c b/trunk/drivers/gpu/drm/i2c/ch7006_mode.c index 9b83574141a6..c860f24a5afc 100644 --- a/trunk/drivers/gpu/drm/i2c/ch7006_mode.c +++ b/trunk/drivers/gpu/drm/i2c/ch7006_mode.c @@ -172,7 +172,7 @@ struct ch7006_mode ch7006_modes[] = { }; struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, - const struct drm_display_mode *drm_mode) + struct drm_display_mode *drm_mode) { struct ch7006_priv *priv = to_ch7006_priv(encoder); struct ch7006_mode *mode; diff --git a/trunk/drivers/gpu/drm/i2c/ch7006_priv.h b/trunk/drivers/gpu/drm/i2c/ch7006_priv.h index 09599f4c0c9a..17667b7d57e7 100644 --- a/trunk/drivers/gpu/drm/i2c/ch7006_priv.h +++ b/trunk/drivers/gpu/drm/i2c/ch7006_priv.h @@ -111,7 +111,7 @@ extern struct ch7006_tv_norm_info ch7006_tv_norms[]; extern struct ch7006_mode ch7006_modes[]; struct ch7006_mode *ch7006_lookup_mode(struct drm_encoder *encoder, - const struct drm_display_mode *drm_mode); + struct drm_display_mode *drm_mode); void ch7006_setup_levels(struct drm_encoder *encoder); void ch7006_setup_subcarrier(struct drm_encoder *encoder); diff --git a/trunk/drivers/gpu/drm/i2c/sil164_drv.c b/trunk/drivers/gpu/drm/i2c/sil164_drv.c index 30b8ae5e5c4a..b7d45ab4ba69 100644 --- a/trunk/drivers/gpu/drm/i2c/sil164_drv.c +++ b/trunk/drivers/gpu/drm/i2c/sil164_drv.c @@ -254,7 +254,7 @@ sil164_encoder_restore(struct drm_encoder *encoder) static bool sil164_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; diff --git a/trunk/drivers/gpu/drm/i810/i810_dma.c b/trunk/drivers/gpu/drm/i810/i810_dma.c index 57d892eaaa6e..fa9439159ebd 100644 --- a/trunk/drivers/gpu/drm/i810/i810_dma.c +++ b/trunk/drivers/gpu/drm/i810/i810_dma.c @@ -881,7 +881,7 @@ static int i810_flush_queue(struct drm_device *dev) } /* Must be called with the lock held */ -void i810_driver_reclaim_buffers(struct drm_device *dev, +static void i810_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) { struct drm_device_dma *dma = dev->dma; @@ -1220,17 +1220,12 @@ void i810_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) if (dev_priv->page_flipping) i810_do_cleanup_pageflip(dev); } +} - if (file_priv->master && file_priv->master->lock.hw_lock) { - drm_idlelock_take(&file_priv->master->lock); - i810_driver_reclaim_buffers(dev, file_priv); - drm_idlelock_release(&file_priv->master->lock); - } else { - /* master disappeared, clean up stuff anyway and hope nothing - * goes wrong */ - i810_driver_reclaim_buffers(dev, file_priv); - } - +void i810_driver_reclaim_buffers_locked(struct drm_device *dev, + struct drm_file *file_priv) +{ + i810_reclaim_buffers(dev, file_priv); } int i810_driver_dma_quiescent(struct drm_device *dev) diff --git a/trunk/drivers/gpu/drm/i810/i810_drv.c b/trunk/drivers/gpu/drm/i810/i810_drv.c index f9924ad04d09..ec12f7dc717a 100644 --- a/trunk/drivers/gpu/drm/i810/i810_drv.c +++ b/trunk/drivers/gpu/drm/i810/i810_drv.c @@ -57,12 +57,13 @@ static const struct file_operations i810_driver_fops = { static struct drm_driver driver = { .driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | - DRIVER_HAVE_DMA, + DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE, .dev_priv_size = sizeof(drm_i810_buf_priv_t), .load = i810_driver_load, .lastclose = i810_driver_lastclose, .preclose = i810_driver_preclose, .device_is_agp = i810_driver_device_is_agp, + .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked, .dma_quiescent = i810_driver_dma_quiescent, .ioctls = i810_ioctls, .fops = &i810_driver_fops, diff --git a/trunk/drivers/gpu/drm/i810/i810_drv.h b/trunk/drivers/gpu/drm/i810/i810_drv.h index 6e0acad9e0f5..c9339f481795 100644 --- a/trunk/drivers/gpu/drm/i810/i810_drv.h +++ b/trunk/drivers/gpu/drm/i810/i810_drv.h @@ -116,12 +116,14 @@ typedef struct drm_i810_private { /* i810_dma.c */ extern int i810_driver_dma_quiescent(struct drm_device *dev); -void i810_driver_reclaim_buffers(struct drm_device *dev, - struct drm_file *file_priv); +extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev, + struct drm_file *file_priv); extern int i810_driver_load(struct drm_device *, unsigned long flags); extern void i810_driver_lastclose(struct drm_device *dev); extern void i810_driver_preclose(struct drm_device *dev, struct drm_file *file_priv); +extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev, + struct drm_file *file_priv); extern int i810_driver_device_is_agp(struct drm_device *dev); extern long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg); diff --git a/trunk/drivers/gpu/drm/i915/Makefile b/trunk/drivers/gpu/drm/i915/Makefile index b0bacdba6d7e..2e9268da58d8 100644 --- a/trunk/drivers/gpu/drm/i915/Makefile +++ b/trunk/drivers/gpu/drm/i915/Makefile @@ -7,7 +7,6 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \ i915_debugfs.o \ i915_suspend.o \ i915_gem.o \ - i915_gem_context.o \ i915_gem_debug.o \ i915_gem_evict.o \ i915_gem_execbuffer.o \ diff --git a/trunk/drivers/gpu/drm/i915/dvo.h b/trunk/drivers/gpu/drm/i915/dvo.h index 58914691a77b..8c2ad014c47f 100644 --- a/trunk/drivers/gpu/drm/i915/dvo.h +++ b/trunk/drivers/gpu/drm/i915/dvo.h @@ -86,7 +86,7 @@ struct intel_dvo_dev_ops { * buses with clock limitations. */ bool (*mode_fixup)(struct intel_dvo_device *dvo, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); /* diff --git a/trunk/drivers/gpu/drm/i915/i915_debugfs.c b/trunk/drivers/gpu/drm/i915/i915_debugfs.c index 2909b123baf5..5363e9c66c27 100644 --- a/trunk/drivers/gpu/drm/i915/i915_debugfs.c +++ b/trunk/drivers/gpu/drm/i915/i915_debugfs.c @@ -713,7 +713,6 @@ static int i915_error_state(struct seq_file *m, void *unused) seq_printf(m, "EIR: 0x%08x\n", error->eir); seq_printf(m, "IER: 0x%08x\n", error->ier); seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); - seq_printf(m, "CCID: 0x%08x\n", error->ccid); for (i = 0; i < dev_priv->num_fence_regs; i++) seq_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); @@ -1765,64 +1764,6 @@ static const struct file_operations i915_max_freq_fops = { .llseek = default_llseek, }; -static ssize_t -i915_min_freq_read(struct file *filp, char __user *ubuf, size_t max, - loff_t *ppos) -{ - struct drm_device *dev = filp->private_data; - drm_i915_private_t *dev_priv = dev->dev_private; - char buf[80]; - int len; - - len = snprintf(buf, sizeof(buf), - "min freq: %d\n", dev_priv->min_delay * 50); - - if (len > sizeof(buf)) - len = sizeof(buf); - - return simple_read_from_buffer(ubuf, max, ppos, buf, len); -} - -static ssize_t -i915_min_freq_write(struct file *filp, const char __user *ubuf, size_t cnt, - loff_t *ppos) -{ - struct drm_device *dev = filp->private_data; - struct drm_i915_private *dev_priv = dev->dev_private; - char buf[20]; - int val = 1; - - if (cnt > 0) { - if (cnt > sizeof(buf) - 1) - return -EINVAL; - - if (copy_from_user(buf, ubuf, cnt)) - return -EFAULT; - buf[cnt] = 0; - - val = simple_strtoul(buf, NULL, 0); - } - - DRM_DEBUG_DRIVER("Manually setting min freq to %d\n", val); - - /* - * Turbo will still be enabled, but won't go below the set value. - */ - dev_priv->min_delay = val / 50; - - gen6_set_rps(dev, val / 50); - - return cnt; -} - -static const struct file_operations i915_min_freq_fops = { - .owner = THIS_MODULE, - .open = simple_open, - .read = i915_min_freq_read, - .write = i915_min_freq_write, - .llseek = default_llseek, -}; - static ssize_t i915_cache_sharing_read(struct file *filp, char __user *ubuf, @@ -2055,12 +1996,6 @@ int i915_debugfs_init(struct drm_minor *minor) if (ret) return ret; - ret = i915_debugfs_create(minor->debugfs_root, minor, - "i915_min_freq", - &i915_min_freq_fops); - if (ret) - return ret; - ret = i915_debugfs_create(minor->debugfs_root, minor, "i915_cache_sharing", &i915_cache_sharing_fops); @@ -2093,8 +2028,6 @@ void i915_debugfs_cleanup(struct drm_minor *minor) 1, minor); drm_debugfs_remove_files((struct drm_info_list *) &i915_max_freq_fops, 1, minor); - drm_debugfs_remove_files((struct drm_info_list *) &i915_min_freq_fops, - 1, minor); drm_debugfs_remove_files((struct drm_info_list *) &i915_cache_sharing_fops, 1, minor); drm_debugfs_remove_files((struct drm_info_list *) &i915_ring_stop_fops, diff --git a/trunk/drivers/gpu/drm/i915/i915_dma.c b/trunk/drivers/gpu/drm/i915/i915_dma.c index f64ef4b723fd..36822b924eb1 100644 --- a/trunk/drivers/gpu/drm/i915/i915_dma.c +++ b/trunk/drivers/gpu/drm/i915/i915_dma.c @@ -1006,9 +1006,6 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_HAS_ALIASING_PPGTT: value = dev_priv->mm.aliasing_ppgtt ? 1 : 0; break; - case I915_PARAM_HAS_WAIT_TIMEOUT: - value = 1; - break; default: DRM_DEBUG_DRIVER("Unknown parameter %d\n", param->param); @@ -1085,8 +1082,8 @@ static int i915_set_status_page(struct drm_device *dev, void *data, ring->status_page.gfx_addr = hws->addr & (0x1ffff<<12); - dev_priv->dri1.gfx_hws_cpu_addr = - ioremap_wc(dev_priv->mm.gtt_base_addr + hws->addr, 4096); + dev_priv->dri1.gfx_hws_cpu_addr = ioremap_wc(dev->agp->base + hws->addr, + 4096); if (dev_priv->dri1.gfx_hws_cpu_addr == NULL) { i915_dma_cleanup(dev); ring->status_page.gfx_addr = 0; @@ -1414,7 +1411,7 @@ static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv) if (!ap) return; - ap->ranges[0].base = dev_priv->mm.gtt->gma_bus_addr; + ap->ranges[0].base = dev_priv->dev->agp->base; ap->ranges[0].size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; primary = @@ -1470,18 +1467,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto free_priv; } - ret = intel_gmch_probe(dev_priv->bridge_dev, dev->pdev, NULL); - if (!ret) { - DRM_ERROR("failed to set up gmch\n"); - ret = -EIO; - goto put_bridge; - } - dev_priv->mm.gtt = intel_gtt_get(); if (!dev_priv->mm.gtt) { DRM_ERROR("Failed to initialize GTT\n"); ret = -ENODEV; - goto put_gmch; + goto put_bridge; } i915_kick_out_firmware_fb(dev_priv); @@ -1508,22 +1498,19 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (!dev_priv->regs) { DRM_ERROR("failed to map registers\n"); ret = -EIO; - goto put_gmch; + goto put_bridge; } aperture_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; - dev_priv->mm.gtt_base_addr = dev_priv->mm.gtt->gma_bus_addr; dev_priv->mm.gtt_mapping = - io_mapping_create_wc(dev_priv->mm.gtt_base_addr, - aperture_size); + io_mapping_create_wc(dev->agp->base, aperture_size); if (dev_priv->mm.gtt_mapping == NULL) { ret = -EIO; goto out_rmmap; } - i915_mtrr_setup(dev_priv, dev_priv->mm.gtt_base_addr, - aperture_size); + i915_mtrr_setup(dev_priv, dev->agp->base, aperture_size); /* The i915 workqueue is primarily used for batched retirement of * requests (and thus managing bo) once the task has been completed @@ -1547,11 +1534,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto out_mtrrfree; } - /* This must be called before any calls to HAS_PCH_* */ - intel_detect_pch(dev); - intel_irq_init(dev); - intel_gt_init(dev); /* Try to make sure MCHBAR is enabled before poking at it */ intel_setup_mchbar(dev); @@ -1584,6 +1567,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (!IS_I945G(dev) && !IS_I945GM(dev)) pci_enable_msi(dev->pdev); + spin_lock_init(&dev_priv->gt_lock); spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->error_lock); spin_lock_init(&dev_priv->rps_lock); @@ -1602,6 +1586,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) /* Start out suspended */ dev_priv->mm.suspended = 1; + intel_detect_pch(dev); + if (drm_core_check_feature(dev, DRIVER_MODESET)) { ret = i915_load_modeset_init(dev); if (ret < 0) { @@ -1636,16 +1622,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) destroy_workqueue(dev_priv->wq); out_mtrrfree: if (dev_priv->mm.gtt_mtrr >= 0) { - mtrr_del(dev_priv->mm.gtt_mtrr, - dev_priv->mm.gtt_base_addr, - aperture_size); + mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base, + dev->agp->agp_info.aper_size * 1024 * 1024); dev_priv->mm.gtt_mtrr = -1; } io_mapping_free(dev_priv->mm.gtt_mapping); out_rmmap: pci_iounmap(dev->pdev, dev_priv->regs); -put_gmch: - intel_gmch_remove(); put_bridge: pci_dev_put(dev_priv->bridge_dev); free_priv: @@ -1677,9 +1660,8 @@ int i915_driver_unload(struct drm_device *dev) io_mapping_free(dev_priv->mm.gtt_mapping); if (dev_priv->mm.gtt_mtrr >= 0) { - mtrr_del(dev_priv->mm.gtt_mtrr, - dev_priv->mm.gtt_base_addr, - dev_priv->mm.gtt->gtt_mappable_entries * PAGE_SIZE); + mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base, + dev->agp->agp_info.aper_size * 1024 * 1024); dev_priv->mm.gtt_mtrr = -1; } @@ -1720,7 +1702,6 @@ int i915_driver_unload(struct drm_device *dev) mutex_lock(&dev->struct_mutex); i915_gem_free_all_phys_object(dev); i915_gem_cleanup_ringbuffer(dev); - i915_gem_context_fini(dev); mutex_unlock(&dev->struct_mutex); i915_gem_cleanup_aliasing_ppgtt(dev); i915_gem_cleanup_stolen(dev); @@ -1760,8 +1741,6 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file) spin_lock_init(&file_priv->mm.lock); INIT_LIST_HEAD(&file_priv->mm.request_list); - idr_init(&file_priv->context_idr); - return 0; } @@ -1794,7 +1773,6 @@ void i915_driver_lastclose(struct drm_device * dev) void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) { - i915_gem_context_close(dev, file_priv); i915_gem_release(dev, file_priv); } @@ -1848,9 +1826,6 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, intel_sprite_get_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_UNLOCKED), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/trunk/drivers/gpu/drm/i915/i915_drv.c b/trunk/drivers/gpu/drm/i915/i915_drv.c index ed22612bc847..9fe9ebe52a7a 100644 --- a/trunk/drivers/gpu/drm/i915/i915_drv.c +++ b/trunk/drivers/gpu/drm/i915/i915_drv.c @@ -32,7 +32,6 @@ #include "drm.h" #include "i915_drm.h" #include "i915_drv.h" -#include "i915_trace.h" #include "intel_drv.h" #include @@ -216,6 +215,7 @@ static const struct intel_device_info intel_ironlake_d_info = { .gen = 5, .need_gfx_hws = 1, .has_hotplug = 1, .has_bsd_ring = 1, + .has_pch_split = 1, }; static const struct intel_device_info intel_ironlake_m_info = { @@ -223,6 +223,7 @@ static const struct intel_device_info intel_ironlake_m_info = { .need_gfx_hws = 1, .has_hotplug = 1, .has_fbc = 1, .has_bsd_ring = 1, + .has_pch_split = 1, }; static const struct intel_device_info intel_sandybridge_d_info = { @@ -231,6 +232,7 @@ static const struct intel_device_info intel_sandybridge_d_info = { .has_bsd_ring = 1, .has_blt_ring = 1, .has_llc = 1, + .has_pch_split = 1, .has_force_wake = 1, }; @@ -241,6 +243,7 @@ static const struct intel_device_info intel_sandybridge_m_info = { .has_bsd_ring = 1, .has_blt_ring = 1, .has_llc = 1, + .has_pch_split = 1, .has_force_wake = 1, }; @@ -250,6 +253,7 @@ static const struct intel_device_info intel_ivybridge_d_info = { .has_bsd_ring = 1, .has_blt_ring = 1, .has_llc = 1, + .has_pch_split = 1, .has_force_wake = 1, }; @@ -260,6 +264,7 @@ static const struct intel_device_info intel_ivybridge_m_info = { .has_bsd_ring = 1, .has_blt_ring = 1, .has_llc = 1, + .has_pch_split = 1, .has_force_wake = 1, }; @@ -287,6 +292,7 @@ static const struct intel_device_info intel_haswell_d_info = { .has_bsd_ring = 1, .has_blt_ring = 1, .has_llc = 1, + .has_pch_split = 1, .has_force_wake = 1, }; @@ -296,6 +302,7 @@ static const struct intel_device_info intel_haswell_m_info = { .has_bsd_ring = 1, .has_blt_ring = 1, .has_llc = 1, + .has_pch_split = 1, .has_force_wake = 1, }; @@ -351,9 +358,6 @@ static const struct pci_device_id pciidlist[] = { /* aka */ INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */ INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */ INTEL_VGA_DEVICE(0x0c16, &intel_haswell_d_info), /* SDV */ - INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info), - INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info), - INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info), {0, 0, 0} }; @@ -425,6 +429,135 @@ bool i915_semaphore_is_enabled(struct drm_device *dev) return 1; } +void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) +{ + int count; + + count = 0; + while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1)) + udelay(10); + + I915_WRITE_NOTRACE(FORCEWAKE, 1); + POSTING_READ(FORCEWAKE); + + count = 0; + while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1) == 0) + udelay(10); +} + +void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) +{ + int count; + + count = 0; + while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1)) + udelay(10); + + I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1)); + POSTING_READ(FORCEWAKE_MT); + + count = 0; + while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1) == 0) + udelay(10); +} + +/* + * Generally this is called implicitly by the register read function. However, + * if some sequence requires the GT to not power down then this function should + * be called at the beginning of the sequence followed by a call to + * gen6_gt_force_wake_put() at the end of the sequence. + */ +void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) +{ + unsigned long irqflags; + + spin_lock_irqsave(&dev_priv->gt_lock, irqflags); + if (dev_priv->forcewake_count++ == 0) + dev_priv->display.force_wake_get(dev_priv); + spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); +} + +static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) +{ + u32 gtfifodbg; + gtfifodbg = I915_READ_NOTRACE(GTFIFODBG); + if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK, + "MMIO read or write has been dropped %x\n", gtfifodbg)) + I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK); +} + +void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) +{ + I915_WRITE_NOTRACE(FORCEWAKE, 0); + /* The below doubles as a POSTING_READ */ + gen6_gt_check_fifodbg(dev_priv); +} + +void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) +{ + I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1)); + /* The below doubles as a POSTING_READ */ + gen6_gt_check_fifodbg(dev_priv); +} + +/* + * see gen6_gt_force_wake_get() + */ +void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) +{ + unsigned long irqflags; + + spin_lock_irqsave(&dev_priv->gt_lock, irqflags); + if (--dev_priv->forcewake_count == 0) + dev_priv->display.force_wake_put(dev_priv); + spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); +} + +int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) +{ + int ret = 0; + + if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) { + int loop = 500; + u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); + while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) { + udelay(10); + fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); + } + if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES)) + ++ret; + dev_priv->gt_fifo_count = fifo; + } + dev_priv->gt_fifo_count--; + + return ret; +} + +void vlv_force_wake_get(struct drm_i915_private *dev_priv) +{ + int count; + + count = 0; + + /* Already awake? */ + if ((I915_READ(0x130094) & 0xa1) == 0xa1) + return; + + I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffffffff); + POSTING_READ(FORCEWAKE_VLV); + + count = 0; + while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1) == 0) + udelay(10); +} + +void vlv_force_wake_put(struct drm_i915_private *dev_priv) +{ + I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffff0000); + /* FIXME: confirm VLV behavior with Punit folks */ + POSTING_READ(FORCEWAKE_VLV); +} + static int i915_drm_freeze(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -504,7 +637,7 @@ static int i915_drm_thaw(struct drm_device *dev) /* KMS EnterVT equivalent */ if (drm_core_check_feature(dev, DRIVER_MODESET)) { - if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) + if (HAS_PCH_SPLIT(dev)) ironlake_init_pch_refclk(dev); mutex_lock(&dev->struct_mutex); @@ -661,9 +794,9 @@ static int gen6_do_reset(struct drm_device *dev) /* If reset with a user forcewake, try to restore, otherwise turn it off */ if (dev_priv->forcewake_count) - dev_priv->gt.force_wake_get(dev_priv); + dev_priv->display.force_wake_get(dev_priv); else - dev_priv->gt.force_wake_put(dev_priv); + dev_priv->display.force_wake_put(dev_priv); /* Restore fifo count */ dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); @@ -672,7 +805,7 @@ static int gen6_do_reset(struct drm_device *dev) return ret; } -int intel_gpu_reset(struct drm_device *dev) +static int intel_gpu_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int ret = -ENODEV; @@ -730,7 +863,10 @@ int i915_reset(struct drm_device *dev) if (!i915_try_reset) return 0; - mutex_lock(&dev->struct_mutex); + if (!mutex_trylock(&dev->struct_mutex)) + return -EBUSY; + + dev_priv->stop_rings = 0; i915_gem_reset(dev); @@ -773,17 +909,13 @@ int i915_reset(struct drm_device *dev) for_each_ring(ring, dev_priv, i) ring->init(ring); - i915_gem_context_init(dev); i915_gem_init_ppgtt(dev); - /* - * It would make sense to re-init all the other hw state, at - * least the rps/rc6/emon init done within modeset_init_hw. For - * some unknown reason, this blows up my ilk, so don't. - */ - mutex_unlock(&dev->struct_mutex); + if (drm_core_check_feature(dev, DRIVER_MODESET)) + intel_modeset_init_hw(dev); + drm_irq_uninstall(dev); drm_irq_install(dev); } else { @@ -793,12 +925,10 @@ int i915_reset(struct drm_device *dev) return 0; } + static int __devinit i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct intel_device_info *intel_info = - (struct intel_device_info *) ent->driver_data; - /* Only bind to function 0 of the device. Early generations * used function 1 as a placeholder for multi-head. This causes * us confusion instead, especially on the systems where both @@ -807,18 +937,6 @@ i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (PCI_FUNC(pdev->devfn)) return -ENODEV; - /* We've managed to ship a kms-enabled ddx that shipped with an XvMC - * implementation for gen3 (and only gen3) that used legacy drm maps - * (gasp!) to share buffers between X and the client. Hence we need to - * keep around the fake agp stuff for gen3, even when kms is enabled. */ - if (intel_info->gen != 3) { - driver.driver_features &= - ~(DRIVER_USE_AGP | DRIVER_REQUIRE_AGP); - } else if (!intel_agp_enabled) { - DRM_ERROR("drm/i915 can't work without intel_agp module!\n"); - return -ENODEV; - } - return drm_get_pci_dev(pdev, ent, &driver); } @@ -940,6 +1058,7 @@ static struct drm_driver driver = { .resume = i915_resume, .device_is_agp = i915_driver_device_is_agp, + .reclaim_buffers = drm_core_reclaim_buffers, .master_create = i915_master_create, .master_destroy = i915_master_destroy, #if defined(CONFIG_DEBUG_FS) @@ -978,6 +1097,11 @@ static struct pci_driver i915_pci_driver = { static int __init i915_init(void) { + if (!intel_agp_enabled) { + DRM_ERROR("drm/i915 can't work without intel_agp module!\n"); + return -ENODEV; + } + driver.num_ioctls = i915_max_ioctl; /* @@ -1025,84 +1149,6 @@ MODULE_LICENSE("GPL and additional rights"); ((reg) < 0x40000) && \ ((reg) != FORCEWAKE)) -static bool IS_DISPLAYREG(u32 reg) -{ - /* - * This should make it easier to transition modules over to the - * new register block scheme, since we can do it incrementally. - */ - if (reg >= 0x180000) - return false; - - if (reg >= RENDER_RING_BASE && - reg < RENDER_RING_BASE + 0xff) - return false; - if (reg >= GEN6_BSD_RING_BASE && - reg < GEN6_BSD_RING_BASE + 0xff) - return false; - if (reg >= BLT_RING_BASE && - reg < BLT_RING_BASE + 0xff) - return false; - - if (reg == PGTBL_ER) - return false; - - if (reg >= IPEIR_I965 && - reg < HWSTAM) - return false; - - if (reg == MI_MODE) - return false; - - if (reg == GFX_MODE_GEN7) - return false; - - if (reg == RENDER_HWS_PGA_GEN7 || - reg == BSD_HWS_PGA_GEN7 || - reg == BLT_HWS_PGA_GEN7) - return false; - - if (reg == GEN6_BSD_SLEEP_PSMI_CONTROL || - reg == GEN6_BSD_RNCID) - return false; - - if (reg == GEN6_BLITTER_ECOSKPD) - return false; - - if (reg >= 0x4000c && - reg <= 0x4002c) - return false; - - if (reg >= 0x4f000 && - reg <= 0x4f08f) - return false; - - if (reg >= 0x4f100 && - reg <= 0x4f11f) - return false; - - if (reg >= VLV_MASTER_IER && - reg <= GEN6_PMIER) - return false; - - if (reg >= FENCE_REG_SANDYBRIDGE_0 && - reg < (FENCE_REG_SANDYBRIDGE_0 + (16*8))) - return false; - - if (reg >= VLV_IIR_RW && - reg <= VLV_ISR) - return false; - - if (reg == FORCEWAKE_VLV || - reg == FORCEWAKE_ACK_VLV) - return false; - - if (reg == GEN6_GDRST) - return false; - - return true; -} - #define __i915_read(x, y) \ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ u##x val = 0; \ @@ -1110,13 +1156,11 @@ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ unsigned long irqflags; \ spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \ if (dev_priv->forcewake_count == 0) \ - dev_priv->gt.force_wake_get(dev_priv); \ + dev_priv->display.force_wake_get(dev_priv); \ val = read##y(dev_priv->regs + reg); \ if (dev_priv->forcewake_count == 0) \ - dev_priv->gt.force_wake_put(dev_priv); \ + dev_priv->display.force_wake_put(dev_priv); \ spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \ - } else if (IS_VALLEYVIEW(dev_priv->dev) && IS_DISPLAYREG(reg)) { \ - val = read##y(dev_priv->regs + reg + 0x180000); \ } else { \ val = read##y(dev_priv->regs + reg); \ } \ @@ -1137,11 +1181,7 @@ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \ if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ } \ - if (IS_VALLEYVIEW(dev_priv->dev) && IS_DISPLAYREG(reg)) { \ - write##y(val, dev_priv->regs + reg + 0x180000); \ - } else { \ - write##y(val, dev_priv->regs + reg); \ - } \ + write##y(val, dev_priv->regs + reg); \ if (unlikely(__fifo_ret)) { \ gen6_gt_check_fifodbg(dev_priv); \ } \ diff --git a/trunk/drivers/gpu/drm/i915/i915_drv.h b/trunk/drivers/gpu/drm/i915/i915_drv.h index 476c64c4844c..b0b676abde0d 100644 --- a/trunk/drivers/gpu/drm/i915/i915_drv.h +++ b/trunk/drivers/gpu/drm/i915/i915_drv.h @@ -79,10 +79,6 @@ enum port { #define for_each_pipe(p) for ((p) = 0; (p) < dev_priv->num_pipe; (p)++) -#define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \ - list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \ - if ((intel_encoder)->base.crtc == (__crtc)) - struct intel_pch_pll { int refcount; /* count of number of CRTCs sharing this PLL */ int active; /* count of number of active CRTCs (i.e. DPMS on) */ @@ -180,7 +176,6 @@ struct drm_i915_error_state { u32 eir; u32 pgtbl_er; u32 ier; - u32 ccid; bool waiting[I915_NUM_RINGS]; u32 pipestat[I915_MAX_PIPES]; u32 tail[I915_NUM_RINGS]; @@ -266,6 +261,8 @@ struct drm_i915_display_funcs { struct drm_i915_gem_object *obj); int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y); + void (*force_wake_get)(struct drm_i915_private *dev_priv); + void (*force_wake_put)(struct drm_i915_private *dev_priv); /* clock updates for mode set */ /* cursor updates */ /* render clock increase/decrease */ @@ -273,11 +270,6 @@ struct drm_i915_display_funcs { /* pll clock increase/decrease */ }; -struct drm_i915_gt_funcs { - void (*force_wake_get)(struct drm_i915_private *dev_priv); - void (*force_wake_put)(struct drm_i915_private *dev_priv); -}; - struct intel_device_info { u8 gen; u8 is_mobile:1; @@ -292,6 +284,7 @@ struct intel_device_info { u8 is_crestline:1; u8 is_ivybridge:1; u8 is_valleyview:1; + u8 has_pch_split:1; u8 has_force_wake:1; u8 is_haswell:1; u8 has_fbc:1; @@ -316,17 +309,6 @@ struct i915_hw_ppgtt { dma_addr_t scratch_page_dma_addr; }; - -/* This must match up with the value previously used for execbuf2.rsvd1. */ -#define DEFAULT_CONTEXT_ID 0 -struct i915_hw_context { - int id; - bool is_initialized; - struct drm_i915_file_private *file_priv; - struct intel_ring_buffer *ring; - struct drm_i915_gem_object *obj; -}; - enum no_fbc_reason { FBC_NO_OUTPUT, /* no outputs enabled to compress */ FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */ @@ -339,7 +321,6 @@ enum no_fbc_reason { }; enum intel_pch { - PCH_NONE = 0, /* No PCH present */ PCH_IBX, /* Ibexpeak PCH */ PCH_CPT, /* Cougarpoint PCH */ PCH_LPT, /* Lynxpoint PCH */ @@ -369,8 +350,6 @@ typedef struct drm_i915_private { int relative_constants_mode; void __iomem *regs; - - struct drm_i915_gt_funcs gt; /** gt_fifo_count and the subsequent register write are synchronized * with dev->struct_mutex. */ unsigned gt_fifo_count; @@ -673,14 +652,11 @@ typedef struct drm_i915_private { unsigned long gtt_end; struct io_mapping *gtt_mapping; - phys_addr_t gtt_base_addr; int gtt_mtrr; /** PPGTT used for aliasing the PPGTT with the GTT */ struct i915_hw_ppgtt *aliasing_ppgtt; - u32 *l3_remap_info; - struct shrinker inactive_shrinker; /** @@ -841,10 +817,6 @@ typedef struct drm_i915_private { struct drm_property *broadcast_rgb_property; struct drm_property *force_audio_property; - - struct work_struct parity_error_work; - bool hw_contexts_disabled; - uint32_t hw_context_size; } drm_i915_private_t; /* Iterate over initialised rings */ @@ -1054,7 +1026,6 @@ struct drm_i915_file_private { struct spinlock lock; struct list_head request_list; } mm; - struct idr context_idr; }; #define INTEL_INFO(dev) (((struct drm_i915_private *) (dev)->dev_private)->info) @@ -1100,8 +1071,7 @@ struct drm_i915_file_private { #define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc) #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) -#define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->gen >= 6) -#define HAS_ALIASING_PPGTT(dev) (INTEL_INFO(dev)->gen >=6 && !IS_VALLEYVIEW(dev)) +#define HAS_ALIASING_PPGTT(dev) (INTEL_INFO(dev)->gen >=6) #define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) #define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) @@ -1124,13 +1094,13 @@ struct drm_i915_file_private { #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) #define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) +#define HAS_PCH_SPLIT(dev) (INTEL_INFO(dev)->has_pch_split) #define HAS_PIPE_CONTROL(dev) (INTEL_INFO(dev)->gen >= 5) #define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type) #define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT) #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) -#define HAS_PCH_SPLIT(dev) (INTEL_PCH_TYPE(dev) != PCH_NONE) #define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake) @@ -1196,7 +1166,6 @@ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, extern int i915_emit_box(struct drm_device *dev, struct drm_clip_rect *box, int DR1, int DR4); -extern int intel_gpu_reset(struct drm_device *dev); extern int i915_reset(struct drm_device *dev); extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv); extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv); @@ -1209,7 +1178,6 @@ void i915_hangcheck_elapsed(unsigned long data); void i915_handle_error(struct drm_device *dev, bool wedged); extern void intel_irq_init(struct drm_device *dev); -extern void intel_gt_init(struct drm_device *dev); void i915_error_state_free(struct kref *error_ref); @@ -1269,8 +1237,6 @@ int i915_gem_get_tiling(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -int i915_gem_wait_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); void i915_gem_load(struct drm_device *dev); int i915_gem_init_object(struct drm_gem_object *obj); int __must_check i915_gem_flush_ring(struct intel_ring_buffer *ring, @@ -1340,8 +1306,6 @@ i915_gem_object_unpin_fence(struct drm_i915_gem_object *obj) void i915_gem_retire_requests(struct drm_device *dev); void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring); -int __must_check i915_gem_check_wedge(struct drm_i915_private *dev_priv, - bool interruptible); void i915_gem_reset(struct drm_device *dev); void i915_gem_clflush_object(struct drm_i915_gem_object *obj); @@ -1351,7 +1315,6 @@ int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj, int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj); int __must_check i915_gem_init(struct drm_device *dev); int __must_check i915_gem_init_hw(struct drm_device *dev); -void i915_gem_l3_remap(struct drm_device *dev); void i915_gem_init_swizzling(struct drm_device *dev); void i915_gem_init_ppgtt(struct drm_device *dev); void i915_gem_cleanup_ringbuffer(struct drm_device *dev); @@ -1360,8 +1323,8 @@ int __must_check i915_gem_idle(struct drm_device *dev); int __must_check i915_add_request(struct intel_ring_buffer *ring, struct drm_file *file, struct drm_i915_gem_request *request); -int __must_check i915_wait_seqno(struct intel_ring_buffer *ring, - uint32_t seqno); +int __must_check i915_wait_request(struct intel_ring_buffer *ring, + uint32_t seqno); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); int __must_check i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, @@ -1395,16 +1358,6 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, struct dma_buf *i915_gem_prime_export(struct drm_device *dev, struct drm_gem_object *gem_obj, int flags); -/* i915_gem_context.c */ -void i915_gem_context_init(struct drm_device *dev); -void i915_gem_context_fini(struct drm_device *dev); -void i915_gem_context_close(struct drm_device *dev, struct drm_file *file); -int i915_switch_context(struct intel_ring_buffer *ring, - struct drm_file *file, int to_id); -int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, - struct drm_file *file); -int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, - struct drm_file *file); /* i915_gem_gtt.c */ int __must_check i915_gem_init_aliasing_ppgtt(struct drm_device *dev); @@ -1522,12 +1475,20 @@ extern bool intel_fbc_enabled(struct drm_device *dev); extern void intel_disable_fbc(struct drm_device *dev); extern bool ironlake_set_drps(struct drm_device *dev, u8 val); extern void ironlake_init_pch_refclk(struct drm_device *dev); +extern void ironlake_enable_rc6(struct drm_device *dev); extern void gen6_set_rps(struct drm_device *dev, u8 val); extern void intel_detect_pch(struct drm_device *dev); extern int intel_trans_dp_port_sel(struct drm_crtc *crtc); extern int intel_enable_rc6(const struct drm_device *dev); extern bool i915_semaphore_is_enabled(struct drm_device *dev); +extern void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv); +extern void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv); +extern void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv); +extern void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv); + +extern void vlv_force_wake_get(struct drm_i915_private *dev_priv); +extern void vlv_force_wake_put(struct drm_i915_private *dev_priv); /* overlay */ #ifdef CONFIG_DEBUG_FS diff --git a/trunk/drivers/gpu/drm/i915/i915_gem.c b/trunk/drivers/gpu/drm/i915/i915_gem.c index 0fdb3d29cbbb..288d7b8f49ae 100644 --- a/trunk/drivers/gpu/drm/i915/i915_gem.c +++ b/trunk/drivers/gpu/drm/i915/i915_gem.c @@ -96,18 +96,9 @@ i915_gem_wait_for_error(struct drm_device *dev) if (!atomic_read(&dev_priv->mm.wedged)) return 0; - /* - * Only wait 10 seconds for the gpu reset to complete to avoid hanging - * userspace. If it takes that long something really bad is going on and - * we should simply try to bail out and fail as gracefully as possible. - */ - ret = wait_for_completion_interruptible_timeout(x, 10*HZ); - if (ret == 0) { - DRM_ERROR("Timed out waiting for the gpu reset to complete\n"); - return -EIO; - } else if (ret < 0) { + ret = wait_for_completion_interruptible(x); + if (ret) return ret; - } if (atomic_read(&dev_priv->mm.wedged)) { /* GPU is hung, bump the completion count to account for @@ -1131,7 +1122,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) obj->fault_mappable = true; - pfn = ((dev_priv->mm.gtt_base_addr + obj->gtt_offset) >> PAGE_SHIFT) + + pfn = ((dev->agp->base + obj->gtt_offset) >> PAGE_SHIFT) + page_offset; /* Finally, remap it using the new GTT offset */ @@ -1141,11 +1132,6 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) out: switch (ret) { case -EIO: - /* If this -EIO is due to a gpu hang, give the reset code a - * chance to clean up the mess. Otherwise return the proper - * SIGBUS. */ - if (!atomic_read(&dev_priv->mm.wedged)) - return VM_FAULT_SIGBUS; case -EAGAIN: /* Give the error handler a chance to run and move the * objects off the GPU active list. Next time we service the @@ -1582,21 +1568,6 @@ i915_add_request(struct intel_ring_buffer *ring, int was_empty; int ret; - /* - * Emit any outstanding flushes - execbuf can fail to emit the flush - * after having emitted the batchbuffer command. Hence we need to fix - * things up similar to emitting the lazy request. The difference here - * is that the flush _must_ happen before the next request, no matter - * what. - */ - if (ring->gpu_caches_dirty) { - ret = i915_gem_flush_ring(ring, 0, I915_GEM_GPU_DOMAINS); - if (ret) - return ret; - - ring->gpu_caches_dirty = false; - } - BUG_ON(request == NULL); seqno = i915_gem_next_request_seqno(ring); @@ -1642,9 +1613,6 @@ i915_add_request(struct intel_ring_buffer *ring, queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); } - - WARN_ON(!list_empty(&ring->gpu_write_list)); - return 0; } @@ -1859,11 +1827,14 @@ i915_gem_retire_work_handler(struct work_struct *work) */ idle = true; for_each_ring(ring, dev_priv, i) { - if (ring->gpu_caches_dirty) { + if (!list_empty(&ring->gpu_write_list)) { struct drm_i915_gem_request *request; + int ret; + ret = i915_gem_flush_ring(ring, + 0, I915_GEM_GPU_DOMAINS); request = kzalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL || + if (ret || request == NULL || i915_add_request(ring, NULL, request)) kfree(request); } @@ -1877,10 +1848,11 @@ i915_gem_retire_work_handler(struct work_struct *work) mutex_unlock(&dev->struct_mutex); } -int -i915_gem_check_wedge(struct drm_i915_private *dev_priv, - bool interruptible) +static int +i915_gem_check_wedge(struct drm_i915_private *dev_priv) { + BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); + if (atomic_read(&dev_priv->mm.wedged)) { struct completion *x = &dev_priv->error_completion; bool recovery_complete; @@ -1891,16 +1863,7 @@ i915_gem_check_wedge(struct drm_i915_private *dev_priv, recovery_complete = x->done > 0; spin_unlock_irqrestore(&x->wait.lock, flags); - /* Non-interruptible callers can't handle -EAGAIN, hence return - * -EIO unconditionally for these. */ - if (!interruptible) - return -EIO; - - /* Recovery complete, but still wedged means reset failure. */ - if (recovery_complete) - return -EIO; - - return -EAGAIN; + return recovery_complete ? -EIO : -EAGAIN; } return 0; @@ -1936,84 +1899,34 @@ i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno) return ret; } -/** - * __wait_seqno - wait until execution of seqno has finished - * @ring: the ring expected to report seqno - * @seqno: duh! - * @interruptible: do an interruptible wait (normally yes) - * @timeout: in - how long to wait (NULL forever); out - how much time remaining - * - * Returns 0 if the seqno was found within the alloted time. Else returns the - * errno with remaining time filled in timeout argument. - */ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, - bool interruptible, struct timespec *timeout) + bool interruptible) { drm_i915_private_t *dev_priv = ring->dev->dev_private; - struct timespec before, now, wait_time={1,0}; - unsigned long timeout_jiffies; - long end; - bool wait_forever = true; - int ret; + int ret = 0; if (i915_seqno_passed(ring->get_seqno(ring), seqno)) return 0; trace_i915_gem_request_wait_begin(ring, seqno); - - if (timeout != NULL) { - wait_time = *timeout; - wait_forever = false; - } - - timeout_jiffies = timespec_to_jiffies(&wait_time); - if (WARN_ON(!ring->irq_get(ring))) return -ENODEV; - /* Record current time in case interrupted by signal, or wedged * */ - getrawmonotonic(&before); - #define EXIT_COND \ (i915_seqno_passed(ring->get_seqno(ring), seqno) || \ atomic_read(&dev_priv->mm.wedged)) - do { - if (interruptible) - end = wait_event_interruptible_timeout(ring->irq_queue, - EXIT_COND, - timeout_jiffies); - else - end = wait_event_timeout(ring->irq_queue, EXIT_COND, - timeout_jiffies); - ret = i915_gem_check_wedge(dev_priv, interruptible); - if (ret) - end = ret; - } while (end == 0 && wait_forever); - - getrawmonotonic(&now); + if (interruptible) + ret = wait_event_interruptible(ring->irq_queue, + EXIT_COND); + else + wait_event(ring->irq_queue, EXIT_COND); ring->irq_put(ring); trace_i915_gem_request_wait_end(ring, seqno); #undef EXIT_COND - if (timeout) { - struct timespec sleep_time = timespec_sub(now, before); - *timeout = timespec_sub(*timeout, sleep_time); - } - - switch (end) { - case -EAGAIN: /* Wedged */ - case -ERESTARTSYS: /* Signal */ - return (int)end; - case 0: /* Timeout */ - if (timeout) - set_normalized_timespec(timeout, 0, 0); - return -ETIME; - default: /* Completed */ - WARN_ON(end < 0); /* We're not aware of other errors */ - return 0; - } + return ret; } /** @@ -2021,14 +1934,15 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, * request and object lists appropriately for that event. */ int -i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno) +i915_wait_request(struct intel_ring_buffer *ring, + uint32_t seqno) { drm_i915_private_t *dev_priv = ring->dev->dev_private; int ret = 0; BUG_ON(seqno == 0); - ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); + ret = i915_gem_check_wedge(dev_priv); if (ret) return ret; @@ -2036,7 +1950,9 @@ i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno) if (ret) return ret; - ret = __wait_seqno(ring, seqno, dev_priv->mm.interruptible, NULL); + ret = __wait_seqno(ring, seqno, dev_priv->mm.interruptible); + if (atomic_read(&dev_priv->mm.wedged)) + ret = -EAGAIN; return ret; } @@ -2059,32 +1975,7 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj) * it. */ if (obj->active) { - ret = i915_wait_seqno(obj->ring, obj->last_rendering_seqno); - if (ret) - return ret; - i915_gem_retire_requests_ring(obj->ring); - } - - return 0; -} - -/** - * Ensures that an object will eventually get non-busy by flushing any required - * write domains, emitting any outstanding lazy request and retiring and - * completed requests. - */ -static int -i915_gem_object_flush_active(struct drm_i915_gem_object *obj) -{ - int ret; - - if (obj->active) { - ret = i915_gem_object_flush_gpu_write_domain(obj); - if (ret) - return ret; - - ret = i915_gem_check_olr(obj->ring, - obj->last_rendering_seqno); + ret = i915_wait_request(obj->ring, obj->last_rendering_seqno); if (ret) return ret; i915_gem_retire_requests_ring(obj->ring); @@ -2093,90 +1984,6 @@ i915_gem_object_flush_active(struct drm_i915_gem_object *obj) return 0; } -/** - * i915_gem_wait_ioctl - implements DRM_IOCTL_I915_GEM_WAIT - * @DRM_IOCTL_ARGS: standard ioctl arguments - * - * Returns 0 if successful, else an error is returned with the remaining time in - * the timeout parameter. - * -ETIME: object is still busy after timeout - * -ERESTARTSYS: signal interrupted the wait - * -ENONENT: object doesn't exist - * Also possible, but rare: - * -EAGAIN: GPU wedged - * -ENOMEM: damn - * -ENODEV: Internal IRQ fail - * -E?: The add request failed - * - * The wait ioctl with a timeout of 0 reimplements the busy ioctl. With any - * non-zero timeout parameter the wait ioctl will wait for the given number of - * nanoseconds on an object becoming unbusy. Since the wait itself does so - * without holding struct_mutex the object may become re-busied before this - * function completes. A similar but shorter * race condition exists in the busy - * ioctl - */ -int -i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) -{ - struct drm_i915_gem_wait *args = data; - struct drm_i915_gem_object *obj; - struct intel_ring_buffer *ring = NULL; - struct timespec timeout_stack, *timeout = NULL; - u32 seqno = 0; - int ret = 0; - - if (args->timeout_ns >= 0) { - timeout_stack = ns_to_timespec(args->timeout_ns); - timeout = &timeout_stack; - } - - ret = i915_mutex_lock_interruptible(dev); - if (ret) - return ret; - - obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->bo_handle)); - if (&obj->base == NULL) { - mutex_unlock(&dev->struct_mutex); - return -ENOENT; - } - - /* Need to make sure the object gets inactive eventually. */ - ret = i915_gem_object_flush_active(obj); - if (ret) - goto out; - - if (obj->active) { - seqno = obj->last_rendering_seqno; - ring = obj->ring; - } - - if (seqno == 0) - goto out; - - /* Do this after OLR check to make sure we make forward progress polling - * on this IOCTL with a 0 timeout (like busy ioctl) - */ - if (!args->timeout_ns) { - ret = -ETIME; - goto out; - } - - drm_gem_object_unreference(&obj->base); - mutex_unlock(&dev->struct_mutex); - - ret = __wait_seqno(ring, seqno, true, timeout); - if (timeout) { - WARN_ON(!timespec_valid(timeout)); - args->timeout_ns = timespec_to_ns(timeout); - } - return ret; - -out: - drm_gem_object_unreference(&obj->base); - mutex_unlock(&dev->struct_mutex); - return ret; -} - /** * i915_gem_object_sync - sync an object to a ring. * @@ -2353,7 +2160,7 @@ static int i915_ring_idle(struct intel_ring_buffer *ring) return ret; } - return i915_wait_seqno(ring, i915_gem_next_request_seqno(ring)); + return i915_wait_request(ring, i915_gem_next_request_seqno(ring)); } int i915_gpu_idle(struct drm_device *dev) @@ -2371,10 +2178,6 @@ int i915_gpu_idle(struct drm_device *dev) /* Is the device fubar? */ if (WARN_ON(!list_empty(&ring->gpu_write_list))) return -EBUSY; - - ret = i915_switch_context(ring, NULL, DEFAULT_CONTEXT_ID); - if (ret) - return ret; } return 0; @@ -2561,7 +2364,7 @@ i915_gem_object_flush_fence(struct drm_i915_gem_object *obj) } if (obj->last_fenced_seqno) { - ret = i915_wait_seqno(obj->ring, obj->last_fenced_seqno); + ret = i915_wait_request(obj->ring, obj->last_fenced_seqno); if (ret) return ret; @@ -2748,8 +2551,8 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, if (map_and_fenceable) free_space = drm_mm_search_free_in_range(&dev_priv->mm.gtt_space, - size, alignment, - 0, dev_priv->mm.gtt_mappable_end, + size, alignment, 0, + dev_priv->mm.gtt_mappable_end, 0); else free_space = drm_mm_search_free(&dev_priv->mm.gtt_space, @@ -2760,7 +2563,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, obj->gtt_space = drm_mm_get_block_range_generic(free_space, size, alignment, 0, - 0, dev_priv->mm.gtt_mappable_end, + dev_priv->mm.gtt_mappable_end, 0); else obj->gtt_space = @@ -3227,7 +3030,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) if (seqno == 0) return 0; - ret = __wait_seqno(ring, seqno, true, NULL); + ret = __wait_seqno(ring, seqno, true); if (ret == 0) queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); @@ -3396,9 +3199,30 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, * become non-busy without any further actions, therefore emit any * necessary flushes here. */ - ret = i915_gem_object_flush_active(obj); - args->busy = obj->active; + if (args->busy) { + /* Unconditionally flush objects, even when the gpu still uses this + * object. Userspace calling this function indicates that it wants to + * use this buffer rather sooner than later, so issuing the required + * flush earlier is beneficial. + */ + if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { + ret = i915_gem_flush_ring(obj->ring, + 0, obj->base.write_domain); + } else { + ret = i915_gem_check_olr(obj->ring, + obj->last_rendering_seqno); + } + + /* Update the active list for the hardware's current position. + * Otherwise this only updates on a delayed timer or when irqs + * are actually unmasked, and our working set ends up being + * larger than required. + */ + i915_gem_retire_requests_ring(obj->ring); + + args->busy = obj->active; + } drm_gem_object_unreference(&obj->base); unlock: @@ -3611,38 +3435,6 @@ i915_gem_idle(struct drm_device *dev) return 0; } -void i915_gem_l3_remap(struct drm_device *dev) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - u32 misccpctl; - int i; - - if (!IS_IVYBRIDGE(dev)) - return; - - if (!dev_priv->mm.l3_remap_info) - return; - - misccpctl = I915_READ(GEN7_MISCCPCTL); - I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); - POSTING_READ(GEN7_MISCCPCTL); - - for (i = 0; i < GEN7_L3LOG_SIZE; i += 4) { - u32 remap = I915_READ(GEN7_L3LOG_BASE + i); - if (remap && remap != dev_priv->mm.l3_remap_info[i/4]) - DRM_DEBUG("0x%x was already programmed to %x\n", - GEN7_L3LOG_BASE + i, remap); - if (remap && !dev_priv->mm.l3_remap_info[i/4]) - DRM_DEBUG_DRIVER("Clearing remapped register\n"); - I915_WRITE(GEN7_L3LOG_BASE + i, dev_priv->mm.l3_remap_info[i/4]); - } - - /* Make sure all the writes land before disabling dop clock gating */ - POSTING_READ(GEN7_L3LOG_BASE); - - I915_WRITE(GEN7_MISCCPCTL, misccpctl); -} - void i915_gem_init_swizzling(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; @@ -3732,11 +3524,6 @@ i915_gem_init_hw(struct drm_device *dev) drm_i915_private_t *dev_priv = dev->dev_private; int ret; - if (!intel_enable_gtt()) - return -EIO; - - i915_gem_l3_remap(dev); - i915_gem_init_swizzling(dev); ret = intel_init_render_ring_buffer(dev); @@ -3757,11 +3544,6 @@ i915_gem_init_hw(struct drm_device *dev) dev_priv->next_seqno = 1; - /* - * XXX: There was some w/a described somewhere suggesting loading - * contexts before PPGTT. - */ - i915_gem_context_init(dev); i915_gem_init_ppgtt(dev); return 0; diff --git a/trunk/drivers/gpu/drm/i915/i915_gem_context.c b/trunk/drivers/gpu/drm/i915/i915_gem_context.c deleted file mode 100644 index 9ae3f2cf414e..000000000000 --- a/trunk/drivers/gpu/drm/i915/i915_gem_context.c +++ /dev/null @@ -1,533 +0,0 @@ -/* - * Copyright © 2011-2012 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * Authors: - * Ben Widawsky - * - */ - -/* - * This file implements HW context support. On gen5+ a HW context consists of an - * opaque GPU object which is referenced at times of context saves and restores. - * With RC6 enabled, the context is also referenced as the GPU enters and exists - * from RC6 (GPU has it's own internal power context, except on gen5). Though - * something like a context does exist for the media ring, the code only - * supports contexts for the render ring. - * - * In software, there is a distinction between contexts created by the user, - * and the default HW context. The default HW context is used by GPU clients - * that do not request setup of their own hardware context. The default - * context's state is never restored to help prevent programming errors. This - * would happen if a client ran and piggy-backed off another clients GPU state. - * The default context only exists to give the GPU some offset to load as the - * current to invoke a save of the context we actually care about. In fact, the - * code could likely be constructed, albeit in a more complicated fashion, to - * never use the default context, though that limits the driver's ability to - * swap out, and/or destroy other contexts. - * - * All other contexts are created as a request by the GPU client. These contexts - * store GPU state, and thus allow GPU clients to not re-emit state (and - * potentially query certain state) at any time. The kernel driver makes - * certain that the appropriate commands are inserted. - * - * The context life cycle is semi-complicated in that context BOs may live - * longer than the context itself because of the way the hardware, and object - * tracking works. Below is a very crude representation of the state machine - * describing the context life. - * refcount pincount active - * S0: initial state 0 0 0 - * S1: context created 1 0 0 - * S2: context is currently running 2 1 X - * S3: GPU referenced, but not current 2 0 1 - * S4: context is current, but destroyed 1 1 0 - * S5: like S3, but destroyed 1 0 1 - * - * The most common (but not all) transitions: - * S0->S1: client creates a context - * S1->S2: client submits execbuf with context - * S2->S3: other clients submits execbuf with context - * S3->S1: context object was retired - * S3->S2: clients submits another execbuf - * S2->S4: context destroy called with current context - * S3->S5->S0: destroy path - * S4->S5->S0: destroy path on current context - * - * There are two confusing terms used above: - * The "current context" means the context which is currently running on the - * GPU. The GPU has loaded it's state already and has stored away the gtt - * offset of the BO. The GPU is not actively referencing the data at this - * offset, but it will on the next context switch. The only way to avoid this - * is to do a GPU reset. - * - * An "active context' is one which was previously the "current context" and is - * on the active list waiting for the next context switch to occur. Until this - * happens, the object must remain at the same gtt offset. It is therefore - * possible to destroy a context, but it is still active. - * - */ - -#include "drmP.h" -#include "i915_drm.h" -#include "i915_drv.h" - -/* This is a HW constraint. The value below is the largest known requirement - * I've seen in a spec to date, and that was a workaround for a non-shipping - * part. It should be safe to decrease this, but it's more future proof as is. - */ -#define CONTEXT_ALIGN (64<<10) - -static struct i915_hw_context * -i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id); -static int do_switch(struct drm_i915_gem_object *from_obj, - struct i915_hw_context *to, u32 seqno); - -static int get_context_size(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - int ret; - u32 reg; - - switch (INTEL_INFO(dev)->gen) { - case 6: - reg = I915_READ(CXT_SIZE); - ret = GEN6_CXT_TOTAL_SIZE(reg) * 64; - break; - case 7: - reg = I915_READ(GEN7_CTX_SIZE); - ret = GEN7_CTX_TOTAL_SIZE(reg) * 64; - break; - default: - BUG(); - } - - return ret; -} - -static void do_destroy(struct i915_hw_context *ctx) -{ - struct drm_device *dev = ctx->obj->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - - if (ctx->file_priv) - idr_remove(&ctx->file_priv->context_idr, ctx->id); - else - BUG_ON(ctx != dev_priv->ring[RCS].default_context); - - drm_gem_object_unreference(&ctx->obj->base); - kfree(ctx); -} - -static struct i915_hw_context * -create_hw_context(struct drm_device *dev, - struct drm_i915_file_private *file_priv) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_hw_context *ctx; - int ret, id; - - ctx = kzalloc(sizeof(struct drm_i915_file_private), GFP_KERNEL); - if (ctx == NULL) - return ERR_PTR(-ENOMEM); - - ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size); - if (ctx->obj == NULL) { - kfree(ctx); - DRM_DEBUG_DRIVER("Context object allocated failed\n"); - return ERR_PTR(-ENOMEM); - } - - /* The ring associated with the context object is handled by the normal - * object tracking code. We give an initial ring value simple to pass an - * assertion in the context switch code. - */ - ctx->ring = &dev_priv->ring[RCS]; - - /* Default context will never have a file_priv */ - if (file_priv == NULL) - return ctx; - - ctx->file_priv = file_priv; - -again: - if (idr_pre_get(&file_priv->context_idr, GFP_KERNEL) == 0) { - ret = -ENOMEM; - DRM_DEBUG_DRIVER("idr allocation failed\n"); - goto err_out; - } - - ret = idr_get_new_above(&file_priv->context_idr, ctx, - DEFAULT_CONTEXT_ID + 1, &id); - if (ret == 0) - ctx->id = id; - - if (ret == -EAGAIN) - goto again; - else if (ret) - goto err_out; - - return ctx; - -err_out: - do_destroy(ctx); - return ERR_PTR(ret); -} - -static inline bool is_default_context(struct i915_hw_context *ctx) -{ - return (ctx == ctx->ring->default_context); -} - -/** - * The default context needs to exist per ring that uses contexts. It stores the - * context state of the GPU for applications that don't utilize HW contexts, as - * well as an idle case. - */ -static int create_default_context(struct drm_i915_private *dev_priv) -{ - struct i915_hw_context *ctx; - int ret; - - BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); - - ctx = create_hw_context(dev_priv->dev, NULL); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - - /* We may need to do things with the shrinker which require us to - * immediately switch back to the default context. This can cause a - * problem as pinning the default context also requires GTT space which - * may not be available. To avoid this we always pin the - * default context. - */ - dev_priv->ring[RCS].default_context = ctx; - ret = i915_gem_object_pin(ctx->obj, CONTEXT_ALIGN, false); - if (ret) { - do_destroy(ctx); - return ret; - } - - ret = do_switch(NULL, ctx, 0); - if (ret) { - i915_gem_object_unpin(ctx->obj); - do_destroy(ctx); - } else { - DRM_DEBUG_DRIVER("Default HW context loaded\n"); - } - - return ret; -} - -void i915_gem_context_init(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t ctx_size; - - if (!HAS_HW_CONTEXTS(dev)) { - dev_priv->hw_contexts_disabled = true; - return; - } - - /* If called from reset, or thaw... we've been here already */ - if (dev_priv->hw_contexts_disabled || - dev_priv->ring[RCS].default_context) - return; - - ctx_size = get_context_size(dev); - dev_priv->hw_context_size = get_context_size(dev); - dev_priv->hw_context_size = round_up(dev_priv->hw_context_size, 4096); - - if (ctx_size <= 0 || ctx_size > (1<<20)) { - dev_priv->hw_contexts_disabled = true; - return; - } - - if (create_default_context(dev_priv)) { - dev_priv->hw_contexts_disabled = true; - return; - } - - DRM_DEBUG_DRIVER("HW context support initialized\n"); -} - -void i915_gem_context_fini(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (dev_priv->hw_contexts_disabled) - return; - - /* The only known way to stop the gpu from accessing the hw context is - * to reset it. Do this as the very last operation to avoid confusing - * other code, leading to spurious errors. */ - intel_gpu_reset(dev); - - i915_gem_object_unpin(dev_priv->ring[RCS].default_context->obj); - - do_destroy(dev_priv->ring[RCS].default_context); -} - -static int context_idr_cleanup(int id, void *p, void *data) -{ - struct i915_hw_context *ctx = p; - - BUG_ON(id == DEFAULT_CONTEXT_ID); - - do_destroy(ctx); - - return 0; -} - -void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) -{ - struct drm_i915_file_private *file_priv = file->driver_priv; - - mutex_lock(&dev->struct_mutex); - idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL); - idr_destroy(&file_priv->context_idr); - mutex_unlock(&dev->struct_mutex); -} - -static struct i915_hw_context * -i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id) -{ - return (struct i915_hw_context *)idr_find(&file_priv->context_idr, id); -} - -static inline int -mi_set_context(struct intel_ring_buffer *ring, - struct i915_hw_context *new_context, - u32 hw_flags) -{ - int ret; - - /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB - * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value - * explicitly, so we rely on the value at ring init, stored in - * itlb_before_ctx_switch. - */ - if (IS_GEN6(ring->dev) && ring->itlb_before_ctx_switch) { - ret = ring->flush(ring, 0, 0); - if (ret) - return ret; - } - - ret = intel_ring_begin(ring, 6); - if (ret) - return ret; - - if (IS_GEN7(ring->dev)) - intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE); - else - intel_ring_emit(ring, MI_NOOP); - - intel_ring_emit(ring, MI_NOOP); - intel_ring_emit(ring, MI_SET_CONTEXT); - intel_ring_emit(ring, new_context->obj->gtt_offset | - MI_MM_SPACE_GTT | - MI_SAVE_EXT_STATE_EN | - MI_RESTORE_EXT_STATE_EN | - hw_flags); - /* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP */ - intel_ring_emit(ring, MI_NOOP); - - if (IS_GEN7(ring->dev)) - intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE); - else - intel_ring_emit(ring, MI_NOOP); - - intel_ring_advance(ring); - - return ret; -} - -static int do_switch(struct drm_i915_gem_object *from_obj, - struct i915_hw_context *to, - u32 seqno) -{ - struct intel_ring_buffer *ring = NULL; - u32 hw_flags = 0; - int ret; - - BUG_ON(to == NULL); - BUG_ON(from_obj != NULL && from_obj->pin_count == 0); - - ret = i915_gem_object_pin(to->obj, CONTEXT_ALIGN, false); - if (ret) - return ret; - - if (!to->obj->has_global_gtt_mapping) - i915_gem_gtt_bind_object(to->obj, to->obj->cache_level); - - if (!to->is_initialized || is_default_context(to)) - hw_flags |= MI_RESTORE_INHIBIT; - else if (WARN_ON_ONCE(from_obj == to->obj)) /* not yet expected */ - hw_flags |= MI_FORCE_RESTORE; - - ring = to->ring; - ret = mi_set_context(ring, to, hw_flags); - if (ret) { - i915_gem_object_unpin(to->obj); - return ret; - } - - /* The backing object for the context is done after switching to the - * *next* context. Therefore we cannot retire the previous context until - * the next context has already started running. In fact, the below code - * is a bit suboptimal because the retiring can occur simply after the - * MI_SET_CONTEXT instead of when the next seqno has completed. - */ - if (from_obj != NULL) { - from_obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION; - i915_gem_object_move_to_active(from_obj, ring, seqno); - /* As long as MI_SET_CONTEXT is serializing, ie. it flushes the - * whole damn pipeline, we don't need to explicitly mark the - * object dirty. The only exception is that the context must be - * correct in case the object gets swapped out. Ideally we'd be - * able to defer doing this until we know the object would be - * swapped, but there is no way to do that yet. - */ - from_obj->dirty = 1; - BUG_ON(from_obj->ring != to->ring); - i915_gem_object_unpin(from_obj); - } - - ring->last_context_obj = to->obj; - to->is_initialized = true; - - return 0; -} - -/** - * i915_switch_context() - perform a GPU context switch. - * @ring: ring for which we'll execute the context switch - * @file_priv: file_priv associated with the context, may be NULL - * @id: context id number - * @seqno: sequence number by which the new context will be switched to - * @flags: - * - * The context life cycle is simple. The context refcount is incremented and - * decremented by 1 and create and destroy. If the context is in use by the GPU, - * it will have a refoucnt > 1. This allows us to destroy the context abstract - * object while letting the normal object tracking destroy the backing BO. - */ -int i915_switch_context(struct intel_ring_buffer *ring, - struct drm_file *file, - int to_id) -{ - struct drm_i915_private *dev_priv = ring->dev->dev_private; - struct drm_i915_file_private *file_priv = NULL; - struct i915_hw_context *to; - struct drm_i915_gem_object *from_obj = ring->last_context_obj; - int ret; - - if (dev_priv->hw_contexts_disabled) - return 0; - - if (ring != &dev_priv->ring[RCS]) - return 0; - - if (file) - file_priv = file->driver_priv; - - if (to_id == DEFAULT_CONTEXT_ID) { - to = ring->default_context; - } else { - to = i915_gem_context_get(file_priv, to_id); - if (to == NULL) - return -ENOENT; - } - - if (from_obj == to->obj) - return 0; - - ret = do_switch(from_obj, to, i915_gem_next_request_seqno(to->ring)); - if (ret) - return ret; - - /* Just to make the code a little cleaner we take the object reference - * after the switch was successful. It would be more intuitive to ref - * the 'to' object before the switch but we know the refcount must be >0 - * if context_get() succeeded, and we hold struct mutex. So it's safe to - * do this here/now - */ - drm_gem_object_reference(&to->obj->base); - if (from_obj != NULL) - drm_gem_object_unreference(&from_obj->base); - return ret; -} - -int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, - struct drm_file *file) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_context_create *args = data; - struct drm_i915_file_private *file_priv = file->driver_priv; - struct i915_hw_context *ctx; - int ret; - - if (!(dev->driver->driver_features & DRIVER_GEM)) - return -ENODEV; - - if (dev_priv->hw_contexts_disabled) - return -ENODEV; - - ret = i915_mutex_lock_interruptible(dev); - if (ret) - return ret; - - ctx = create_hw_context(dev, file_priv); - mutex_unlock(&dev->struct_mutex); - - args->ctx_id = ctx->id; - DRM_DEBUG_DRIVER("HW context %d created\n", args->ctx_id); - - return PTR_RET(ctx); -} - -int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, - struct drm_file *file) -{ - struct drm_i915_gem_context_destroy *args = data; - struct drm_i915_file_private *file_priv = file->driver_priv; - struct i915_hw_context *ctx; - int ret; - - if (!(dev->driver->driver_features & DRIVER_GEM)) - return -ENODEV; - - ret = i915_mutex_lock_interruptible(dev); - if (ret) - return ret; - - ctx = i915_gem_context_get(file_priv, args->ctx_id); - if (!ctx) { - mutex_unlock(&dev->struct_mutex); - return -ENOENT; - } - - do_destroy(ctx); - - mutex_unlock(&dev->struct_mutex); - - DRM_DEBUG_DRIVER("HW context %d destroyed\n", args->ctx_id); - return 0; -} diff --git a/trunk/drivers/gpu/drm/i915/i915_gem_debug.c b/trunk/drivers/gpu/drm/i915/i915_gem_debug.c index bddf7bed183f..a4f6aaabca99 100644 --- a/trunk/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/trunk/drivers/gpu/drm/i915/i915_gem_debug.c @@ -132,8 +132,7 @@ i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, int handle) __func__, obj, obj->gtt_offset, handle, obj->size / 1024); - gtt_mapping = ioremap(dev_priv->mm.gtt_base_addr + obj->gtt_offset, - obj->base.size); + gtt_mapping = ioremap(dev->agp->base + obj->gtt_offset, obj->base.size); if (gtt_mapping == NULL) { DRM_ERROR("failed to map GTT space\n"); return; diff --git a/trunk/drivers/gpu/drm/i915/i915_gem_evict.c b/trunk/drivers/gpu/drm/i915/i915_gem_evict.c index eba0308f10e3..ae7c24e12e52 100644 --- a/trunk/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/trunk/drivers/gpu/drm/i915/i915_gem_evict.c @@ -78,12 +78,11 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, INIT_LIST_HEAD(&unwind_list); if (mappable) - drm_mm_init_scan_with_range(&dev_priv->mm.gtt_space, - min_size, alignment, 0, - 0, dev_priv->mm.gtt_mappable_end); + drm_mm_init_scan_with_range(&dev_priv->mm.gtt_space, min_size, + alignment, 0, + dev_priv->mm.gtt_mappable_end); else - drm_mm_init_scan(&dev_priv->mm.gtt_space, - min_size, alignment, 0); + drm_mm_init_scan(&dev_priv->mm.gtt_space, min_size, alignment); /* First see if there is a large enough contiguous idle region... */ list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list) { diff --git a/trunk/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/trunk/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 88e2e114189c..974a9f1068a3 100644 --- a/trunk/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/trunk/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -810,16 +810,33 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, return ret; } -static void +static int i915_gem_execbuffer_flush(struct drm_device *dev, uint32_t invalidate_domains, - uint32_t flush_domains) + uint32_t flush_domains, + uint32_t flush_rings) { + drm_i915_private_t *dev_priv = dev->dev_private; + int i, ret; + if (flush_domains & I915_GEM_DOMAIN_CPU) intel_gtt_chipset_flush(); if (flush_domains & I915_GEM_DOMAIN_GTT) wmb(); + + if ((flush_domains | invalidate_domains) & I915_GEM_GPU_DOMAINS) { + for (i = 0; i < I915_NUM_RINGS; i++) + if (flush_rings & (1 << i)) { + ret = i915_gem_flush_ring(&dev_priv->ring[i], + invalidate_domains, + flush_domains); + if (ret) + return ret; + } + } + + return 0; } static int @@ -868,9 +885,12 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring, i915_gem_object_set_to_gpu_domain(obj, ring, &cd); if (cd.invalidate_domains | cd.flush_domains) { - i915_gem_execbuffer_flush(ring->dev, - cd.invalidate_domains, - cd.flush_domains); + ret = i915_gem_execbuffer_flush(ring->dev, + cd.invalidate_domains, + cd.flush_domains, + cd.flush_rings); + if (ret) + return ret; } if (cd.flips) { @@ -885,11 +905,6 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring, return ret; } - /* Unconditionally invalidate gpu caches. */ - ret = i915_gem_flush_ring(ring, I915_GEM_GPU_DOMAINS, 0); - if (ret) - return ret; - return 0; } @@ -968,13 +983,26 @@ i915_gem_execbuffer_retire_commands(struct drm_device *dev, struct intel_ring_buffer *ring) { struct drm_i915_gem_request *request; + u32 invalidate; - /* Unconditionally force add_request to emit a full flush. */ - ring->gpu_caches_dirty = true; + /* + * Ensure that the commands in the batch buffer are + * finished before the interrupt fires. + * + * The sampler always gets flushed on i965 (sigh). + */ + invalidate = I915_GEM_DOMAIN_COMMAND; + if (INTEL_INFO(dev)->gen >= 4) + invalidate |= I915_GEM_DOMAIN_SAMPLER; + if (ring->flush(ring, invalidate, 0)) { + i915_gem_next_request_seqno(ring); + return; + } /* Add a breadcrumb for the completion of the batch buffer */ request = kzalloc(sizeof(*request), GFP_KERNEL); if (request == NULL || i915_add_request(ring, file, request)) { + i915_gem_next_request_seqno(ring); kfree(request); } } @@ -1016,7 +1044,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, struct drm_i915_gem_object *batch_obj; struct drm_clip_rect *cliprects = NULL; struct intel_ring_buffer *ring; - u32 ctx_id = i915_execbuffer2_get_context_id(*args); u32 exec_start, exec_len; u32 seqno; u32 mask; @@ -1038,19 +1065,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, break; case I915_EXEC_BSD: ring = &dev_priv->ring[VCS]; - if (ctx_id != 0) { - DRM_DEBUG("Ring %s doesn't support contexts\n", - ring->name); - return -EPERM; - } break; case I915_EXEC_BLT: ring = &dev_priv->ring[BCS]; - if (ctx_id != 0) { - DRM_DEBUG("Ring %s doesn't support contexts\n", - ring->name); - return -EPERM; - } break; default: DRM_DEBUG("execbuf with unknown ring: %d\n", @@ -1244,10 +1261,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, goto err; } - ret = i915_switch_context(ring, file, ctx_id); - if (ret) - goto err; - trace_i915_gem_ring_dispatch(ring, seqno); exec_start = batch_obj->gtt_offset + args->batch_start_offset; @@ -1354,7 +1367,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, exec2.num_cliprects = args->num_cliprects; exec2.cliprects_ptr = args->cliprects_ptr; exec2.flags = I915_EXEC_RENDER; - i915_execbuffer2_set_context_id(exec2, 0); ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list); if (!ret) { diff --git a/trunk/drivers/gpu/drm/i915/i915_irq.c b/trunk/drivers/gpu/drm/i915/i915_irq.c index 05014bc20ee8..ed3224c37423 100644 --- a/trunk/drivers/gpu/drm/i915/i915_irq.c +++ b/trunk/drivers/gpu/drm/i915/i915_irq.c @@ -375,86 +375,6 @@ static void gen6_pm_rps_work(struct work_struct *work) mutex_unlock(&dev_priv->dev->struct_mutex); } - -/** - * ivybridge_parity_work - Workqueue called when a parity error interrupt - * occurred. - * @work: workqueue struct - * - * Doesn't actually do anything except notify userspace. As a consequence of - * this event, userspace should try to remap the bad rows since statistically - * it is likely the same row is more likely to go bad again. - */ -static void ivybridge_parity_work(struct work_struct *work) -{ - drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, - parity_error_work); - u32 error_status, row, bank, subbank; - char *parity_event[5]; - uint32_t misccpctl; - unsigned long flags; - - /* We must turn off DOP level clock gating to access the L3 registers. - * In order to prevent a get/put style interface, acquire struct mutex - * any time we access those registers. - */ - mutex_lock(&dev_priv->dev->struct_mutex); - - misccpctl = I915_READ(GEN7_MISCCPCTL); - I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); - POSTING_READ(GEN7_MISCCPCTL); - - error_status = I915_READ(GEN7_L3CDERRST1); - row = GEN7_PARITY_ERROR_ROW(error_status); - bank = GEN7_PARITY_ERROR_BANK(error_status); - subbank = GEN7_PARITY_ERROR_SUBBANK(error_status); - - I915_WRITE(GEN7_L3CDERRST1, GEN7_PARITY_ERROR_VALID | - GEN7_L3CDERRST1_ENABLE); - POSTING_READ(GEN7_L3CDERRST1); - - I915_WRITE(GEN7_MISCCPCTL, misccpctl); - - spin_lock_irqsave(&dev_priv->irq_lock, flags); - dev_priv->gt_irq_mask &= ~GT_GEN7_L3_PARITY_ERROR_INTERRUPT; - I915_WRITE(GTIMR, dev_priv->gt_irq_mask); - spin_unlock_irqrestore(&dev_priv->irq_lock, flags); - - mutex_unlock(&dev_priv->dev->struct_mutex); - - parity_event[0] = "L3_PARITY_ERROR=1"; - parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row); - parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank); - parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank); - parity_event[4] = NULL; - - kobject_uevent_env(&dev_priv->dev->primary->kdev.kobj, - KOBJ_CHANGE, parity_event); - - DRM_DEBUG("Parity error: Row = %d, Bank = %d, Sub bank = %d.\n", - row, bank, subbank); - - kfree(parity_event[3]); - kfree(parity_event[2]); - kfree(parity_event[1]); -} - -static void ivybridge_handle_parity_error(struct drm_device *dev) -{ - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - unsigned long flags; - - if (!IS_IVYBRIDGE(dev)) - return; - - spin_lock_irqsave(&dev_priv->irq_lock, flags); - dev_priv->gt_irq_mask |= GT_GEN7_L3_PARITY_ERROR_INTERRUPT; - I915_WRITE(GTIMR, dev_priv->gt_irq_mask); - spin_unlock_irqrestore(&dev_priv->irq_lock, flags); - - queue_work(dev_priv->wq, &dev_priv->parity_error_work); -} - static void snb_gt_irq_handler(struct drm_device *dev, struct drm_i915_private *dev_priv, u32 gt_iir) @@ -474,9 +394,6 @@ static void snb_gt_irq_handler(struct drm_device *dev, DRM_ERROR("GT error interrupt 0x%08x\n", gt_iir); i915_handle_error(dev, false); } - - if (gt_iir & GT_GEN7_L3_PARITY_ERROR_INTERRUPT) - ivybridge_handle_parity_error(dev); } static void gen6_queue_rps_work(struct drm_i915_private *dev_priv, @@ -512,10 +429,15 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS) unsigned long irqflags; int pipe; u32 pipe_stats[I915_MAX_PIPES]; + u32 vblank_status; + int vblank = 0; bool blc_event; atomic_inc(&dev_priv->irq_received); + vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS | + PIPE_VBLANK_INTERRUPT_STATUS; + while (true) { iir = I915_READ(VLV_IIR); gt_iir = I915_READ(GTIIR); @@ -545,16 +467,6 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS) } spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); - for_each_pipe(pipe) { - if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) - drm_handle_vblank(dev, pipe); - - if (pipe_stats[pipe] & PLANE_FLIPDONE_INT_STATUS_VLV) { - intel_prepare_page_flip(dev, pipe); - intel_finish_page_flip(dev, pipe); - } - } - /* Consume port. Then clear IIR or we'll miss events */ if (iir & I915_DISPLAY_PORT_INTERRUPT) { u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); @@ -569,6 +481,19 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS) I915_READ(PORT_HOTPLUG_STAT); } + + if (iir & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT) { + drm_handle_vblank(dev, 0); + vblank++; + intel_finish_page_flip(dev, 0); + } + + if (iir & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT) { + drm_handle_vblank(dev, 1); + vblank++; + intel_finish_page_flip(dev, 0); + } + if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) blc_event = true; @@ -1179,7 +1104,6 @@ static void i915_capture_error_state(struct drm_device *dev) kref_init(&error->ref); error->eir = I915_READ(EIR); error->pgtbl_er = I915_READ(PGTBL_ER); - error->ccid = I915_READ(CCID); if (HAS_PCH_SPLIT(dev)) error->ier = I915_READ(DEIER) | I915_READ(GTIER); @@ -1502,20 +1426,23 @@ static int valleyview_enable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; - u32 imr; + u32 dpfl, imr; if (!i915_pipe_enabled(dev, pipe)) return -EINVAL; spin_lock_irqsave(&dev_priv->irq_lock, irqflags); + dpfl = I915_READ(VLV_DPFLIPSTAT); imr = I915_READ(VLV_IMR); - if (pipe == 0) + if (pipe == 0) { + dpfl |= PIPEA_VBLANK_INT_EN; imr &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; - else + } else { + dpfl |= PIPEA_VBLANK_INT_EN; imr &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; + } + I915_WRITE(VLV_DPFLIPSTAT, dpfl); I915_WRITE(VLV_IMR, imr); - i915_enable_pipestat(dev_priv, pipe, - PIPE_START_VBLANK_INTERRUPT_ENABLE); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); return 0; @@ -1565,17 +1492,20 @@ static void valleyview_disable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; - u32 imr; + u32 dpfl, imr; spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - i915_disable_pipestat(dev_priv, pipe, - PIPE_START_VBLANK_INTERRUPT_ENABLE); + dpfl = I915_READ(VLV_DPFLIPSTAT); imr = I915_READ(VLV_IMR); - if (pipe == 0) + if (pipe == 0) { + dpfl &= ~PIPEA_VBLANK_INT_EN; imr |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; - else + } else { + dpfl &= ~PIPEB_VBLANK_INT_EN; imr |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; + } I915_WRITE(VLV_IMR, imr); + I915_WRITE(VLV_DPFLIPSTAT, dpfl); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } @@ -1718,6 +1648,7 @@ static void ironlake_irq_preinstall(struct drm_device *dev) atomic_set(&dev_priv->irq_received, 0); + I915_WRITE(HWSTAM, 0xeffe); /* XXX hotplug from PCH */ @@ -1880,13 +1811,13 @@ static int ivybridge_irq_postinstall(struct drm_device *dev) DE_PIPEA_VBLANK_IVB); POSTING_READ(DEIER); - dev_priv->gt_irq_mask = ~GT_GEN7_L3_PARITY_ERROR_INTERRUPT; + dev_priv->gt_irq_mask = ~0; I915_WRITE(GTIIR, I915_READ(GTIIR)); I915_WRITE(GTIMR, dev_priv->gt_irq_mask); render_irqs = GT_USER_INTERRUPT | GEN6_BSD_USER_INTERRUPT | - GEN6_BLITTER_USER_INTERRUPT | GT_GEN7_L3_PARITY_ERROR_INTERRUPT; + GEN6_BLITTER_USER_INTERRUPT; I915_WRITE(GTIER, render_irqs); POSTING_READ(GTIER); @@ -1909,24 +1840,16 @@ static int ivybridge_irq_postinstall(struct drm_device *dev) static int valleyview_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + u32 render_irqs; u32 enable_mask; u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); - u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV; u16 msid; enable_mask = I915_DISPLAY_PORT_INTERRUPT; - enable_mask |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | - I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | + enable_mask |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; - /* - *Leave vblank interrupts masked initially. enable/disable will - * toggle them based on usage. - */ - dev_priv->irq_mask = (~enable_mask) | - I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | - I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; + dev_priv->irq_mask = ~enable_mask; dev_priv->pipestat[0] = 0; dev_priv->pipestat[1] = 0; @@ -1945,27 +1868,26 @@ static int valleyview_irq_postinstall(struct drm_device *dev) I915_WRITE(PIPESTAT(1), 0xffff); POSTING_READ(VLV_IER); - i915_enable_pipestat(dev_priv, 0, pipestat_enable); - i915_enable_pipestat(dev_priv, 1, pipestat_enable); - I915_WRITE(VLV_IIR, 0xffffffff); I915_WRITE(VLV_IIR, 0xffffffff); - dev_priv->gt_irq_mask = ~0; + render_irqs = GT_GEN6_BLT_FLUSHDW_NOTIFY_INTERRUPT | + GT_GEN6_BLT_CS_ERROR_INTERRUPT | + GT_GEN6_BLT_USER_INTERRUPT | + GT_GEN6_BSD_USER_INTERRUPT | + GT_GEN6_BSD_CS_ERROR_INTERRUPT | + GT_GEN7_L3_PARITY_ERROR_INTERRUPT | + GT_PIPE_NOTIFY | + GT_RENDER_CS_ERROR_INTERRUPT | + GT_SYNC_STATUS | + GT_USER_INTERRUPT; + + dev_priv->gt_irq_mask = ~render_irqs; I915_WRITE(GTIIR, I915_READ(GTIIR)); I915_WRITE(GTIIR, I915_READ(GTIIR)); - I915_WRITE(GTIMR, dev_priv->gt_irq_mask); - I915_WRITE(GTIER, GT_GEN6_BLT_FLUSHDW_NOTIFY_INTERRUPT | - GT_GEN6_BLT_CS_ERROR_INTERRUPT | - GT_GEN6_BLT_USER_INTERRUPT | - GT_GEN6_BSD_USER_INTERRUPT | - GT_GEN6_BSD_CS_ERROR_INTERRUPT | - GT_GEN7_L3_PARITY_ERROR_INTERRUPT | - GT_PIPE_NOTIFY | - GT_RENDER_CS_ERROR_INTERRUPT | - GT_SYNC_STATUS | - GT_USER_INTERRUPT); + I915_WRITE(GTIMR, 0); + I915_WRITE(GTIER, render_irqs); POSTING_READ(GTIER); /* ack & enable invalid PTE error interrupts */ @@ -2244,9 +2166,9 @@ static int i915_irq_postinstall(struct drm_device *dev) hotplug_en |= HDMIC_HOTPLUG_INT_EN; if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) hotplug_en |= HDMID_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I915) + if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) hotplug_en |= SDVOC_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I915) + if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) hotplug_en |= SDVOB_HOTPLUG_INT_EN; if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { hotplug_en |= CRT_HOTPLUG_INT_EN; @@ -2406,8 +2328,10 @@ static void i965_irq_preinstall(struct drm_device * dev) atomic_set(&dev_priv->irq_received, 0); - I915_WRITE(PORT_HOTPLUG_EN, 0); - I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); + if (I915_HAS_HOTPLUG(dev)) { + I915_WRITE(PORT_HOTPLUG_EN, 0); + I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); + } I915_WRITE(HWSTAM, 0xeffe); for_each_pipe(pipe) @@ -2420,13 +2344,11 @@ static void i965_irq_preinstall(struct drm_device * dev) static int i965_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u32 hotplug_en; u32 enable_mask; u32 error_mask; /* Unmask the interrupts that we always want on. */ dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT | - I915_DISPLAY_PORT_INTERRUPT | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | @@ -2442,6 +2364,13 @@ static int i965_irq_postinstall(struct drm_device *dev) dev_priv->pipestat[0] = 0; dev_priv->pipestat[1] = 0; + if (I915_HAS_HOTPLUG(dev)) { + /* Enable in IER... */ + enable_mask |= I915_DISPLAY_PORT_INTERRUPT; + /* and unmask in IMR */ + dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT; + } + /* * Enable some error detection, note the instruction error mask * bit is reserved, so we leave it masked. @@ -2461,40 +2390,36 @@ static int i965_irq_postinstall(struct drm_device *dev) I915_WRITE(IER, enable_mask); POSTING_READ(IER); - /* Note HDMI and DP share hotplug bits */ - hotplug_en = 0; - if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) - hotplug_en |= HDMIB_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) - hotplug_en |= HDMIC_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) - hotplug_en |= HDMID_HOTPLUG_INT_EN; - if (IS_G4X(dev)) { - if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_G4X) - hotplug_en |= SDVOC_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_G4X) - hotplug_en |= SDVOB_HOTPLUG_INT_EN; - } else { - if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I965) + if (I915_HAS_HOTPLUG(dev)) { + u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); + + /* Note HDMI and DP share bits */ + if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) + hotplug_en |= HDMIB_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) + hotplug_en |= HDMIC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) + hotplug_en |= HDMID_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) hotplug_en |= SDVOC_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I965) + if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) hotplug_en |= SDVOB_HOTPLUG_INT_EN; - } - if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { - hotplug_en |= CRT_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { + hotplug_en |= CRT_HOTPLUG_INT_EN; - /* Programming the CRT detection parameters tends - to generate a spurious hotplug event about three - seconds later. So just do it once. - */ - if (IS_G4X(dev)) - hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; - hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; - } + /* Programming the CRT detection parameters tends + to generate a spurious hotplug event about three + seconds later. So just do it once. + */ + if (IS_G4X(dev)) + hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; + hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; + } - /* Ignore TV since it's buggy */ + /* Ignore TV since it's buggy */ - I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); + I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); + } intel_opregion_enable_asle(dev); @@ -2552,7 +2477,8 @@ static irqreturn_t i965_irq_handler(DRM_IRQ_ARGS) ret = IRQ_HANDLED; /* Consume port. Then clear IIR or we'll miss events */ - if (iir & I915_DISPLAY_PORT_INTERRUPT) { + if ((I915_HAS_HOTPLUG(dev)) && + (iir & I915_DISPLAY_PORT_INTERRUPT)) { u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n", @@ -2625,8 +2551,10 @@ static void i965_irq_uninstall(struct drm_device * dev) if (!dev_priv) return; - I915_WRITE(PORT_HOTPLUG_EN, 0); - I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); + if (I915_HAS_HOTPLUG(dev)) { + I915_WRITE(PORT_HOTPLUG_EN, 0); + I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); + } I915_WRITE(HWSTAM, 0xffffffff); for_each_pipe(pipe) @@ -2647,7 +2575,6 @@ void intel_irq_init(struct drm_device *dev) INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); INIT_WORK(&dev_priv->error_work, i915_error_work_func); INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); - INIT_WORK(&dev_priv->parity_error_work, ivybridge_parity_work); dev->driver->get_vblank_counter = i915_get_vblank_counter; dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ diff --git a/trunk/drivers/gpu/drm/i915/i915_reg.h b/trunk/drivers/gpu/drm/i915/i915_reg.h index 1218069c7f66..48d5e8e051cf 100644 --- a/trunk/drivers/gpu/drm/i915/i915_reg.h +++ b/trunk/drivers/gpu/drm/i915/i915_reg.h @@ -217,9 +217,6 @@ #define MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19) #define MI_DISPLAY_FLIP_IVB_PLANE_C (4 << 19) #define MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19) -#define MI_ARB_ON_OFF MI_INSTR(0x08, 0) -#define MI_ARB_ENABLE (1<<0) -#define MI_ARB_DISABLE (0<<0) #define MI_SET_CONTEXT MI_INSTR(0x18, 0) #define MI_MM_SPACE_GTT (1<<8) @@ -302,7 +299,6 @@ #define DISPLAY_PLANE_B (1<<20) #define GFX_OP_PIPE_CONTROL(len) ((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2)) #define PIPE_CONTROL_CS_STALL (1<<20) -#define PIPE_CONTROL_TLB_INVALIDATE (1<<18) #define PIPE_CONTROL_QW_WRITE (1<<14) #define PIPE_CONTROL_DEPTH_STALL (1<<13) #define PIPE_CONTROL_WRITE_FLUSH (1<<12) @@ -912,7 +908,6 @@ #define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ #define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ #define DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */ -#define DPLL_LOCK_VLV (1<<15) #define DPLL_INTEGRATED_CLOCK_VLV (1<<13) #define SRX_INDEX 0x3c4 @@ -1458,10 +1453,6 @@ #define DDRMPLL1 0X12c20 #define PEG_BAND_GAP_DATA 0x14d68 -#define GEN6_GT_THREAD_STATUS_REG 0x13805c -#define GEN6_GT_THREAD_STATUS_CORE_MASK 0x7 -#define GEN6_GT_THREAD_STATUS_CORE_MASK_HSW (0x7 | (0x07 << 16)) - #define GEN6_GT_PERF_STATUS 0x145948 #define GEN6_RP_STATE_LIMITS 0x145994 #define GEN6_RP_STATE_CAP 0x145998 @@ -1471,27 +1462,6 @@ */ #define CCID 0x2180 #define CCID_EN (1<<0) -#define CXT_SIZE 0x21a0 -#define GEN6_CXT_POWER_SIZE(cxt_reg) ((cxt_reg >> 24) & 0x3f) -#define GEN6_CXT_RING_SIZE(cxt_reg) ((cxt_reg >> 18) & 0x3f) -#define GEN6_CXT_RENDER_SIZE(cxt_reg) ((cxt_reg >> 12) & 0x3f) -#define GEN6_CXT_EXTENDED_SIZE(cxt_reg) ((cxt_reg >> 6) & 0x3f) -#define GEN6_CXT_PIPELINE_SIZE(cxt_reg) ((cxt_reg >> 0) & 0x3f) -#define GEN6_CXT_TOTAL_SIZE(cxt_reg) (GEN6_CXT_POWER_SIZE(cxt_reg) + \ - GEN6_CXT_RING_SIZE(cxt_reg) + \ - GEN6_CXT_RENDER_SIZE(cxt_reg) + \ - GEN6_CXT_EXTENDED_SIZE(cxt_reg) + \ - GEN6_CXT_PIPELINE_SIZE(cxt_reg)) -#define GEN7_CTX_SIZE 0x21a8 -#define GEN7_CTX_RENDER_SIZE(ctx_reg) ((ctx_reg >> 16) & 0x3f) -#define GEN7_CTX_EXTENDED_SIZE(ctx_reg) ((ctx_reg >> 9) & 0x7f) -#define GEN7_CTX_GT1_SIZE(ctx_reg) ((ctx_reg >> 6) & 0x7) -#define GEN7_CTX_VFSTATE_SIZE(ctx_reg) ((ctx_reg >> 0) & 0x3f) -#define GEN7_CTX_TOTAL_SIZE(ctx_reg) (GEN7_CTX_RENDER_SIZE(ctx_reg) + \ - GEN7_CTX_EXTENDED_SIZE(ctx_reg) + \ - GEN7_CTX_GT1_SIZE(ctx_reg) + \ - GEN7_CTX_VFSTATE_SIZE(ctx_reg)) - /* * Overlay regs */ @@ -1596,34 +1566,20 @@ #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) #define PORT_HOTPLUG_STAT 0x61114 -/* HDMI/DP bits are gen4+ */ -#define DPB_HOTPLUG_LIVE_STATUS (1 << 29) -#define DPC_HOTPLUG_LIVE_STATUS (1 << 28) -#define DPD_HOTPLUG_LIVE_STATUS (1 << 27) -#define DPD_HOTPLUG_INT_STATUS (3 << 21) -#define DPC_HOTPLUG_INT_STATUS (3 << 19) -#define DPB_HOTPLUG_INT_STATUS (3 << 17) -/* HDMI bits are shared with the DP bits */ -#define HDMIB_HOTPLUG_LIVE_STATUS (1 << 29) -#define HDMIC_HOTPLUG_LIVE_STATUS (1 << 28) -#define HDMID_HOTPLUG_LIVE_STATUS (1 << 27) -#define HDMID_HOTPLUG_INT_STATUS (3 << 21) -#define HDMIC_HOTPLUG_INT_STATUS (3 << 19) -#define HDMIB_HOTPLUG_INT_STATUS (3 << 17) -/* CRT/TV common between gen3+ */ +#define HDMIB_HOTPLUG_INT_STATUS (1 << 29) +#define DPB_HOTPLUG_INT_STATUS (1 << 29) +#define HDMIC_HOTPLUG_INT_STATUS (1 << 28) +#define DPC_HOTPLUG_INT_STATUS (1 << 28) +#define HDMID_HOTPLUG_INT_STATUS (1 << 27) +#define DPD_HOTPLUG_INT_STATUS (1 << 27) #define CRT_HOTPLUG_INT_STATUS (1 << 11) #define TV_HOTPLUG_INT_STATUS (1 << 10) #define CRT_HOTPLUG_MONITOR_MASK (3 << 8) #define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) #define CRT_HOTPLUG_MONITOR_MONO (2 << 8) #define CRT_HOTPLUG_MONITOR_NONE (0 << 8) -/* SDVO is different across gen3/4 */ -#define SDVOC_HOTPLUG_INT_STATUS_G4X (1 << 3) -#define SDVOB_HOTPLUG_INT_STATUS_G4X (1 << 2) -#define SDVOC_HOTPLUG_INT_STATUS_I965 (3 << 4) -#define SDVOB_HOTPLUG_INT_STATUS_I965 (3 << 2) -#define SDVOC_HOTPLUG_INT_STATUS_I915 (1 << 7) -#define SDVOB_HOTPLUG_INT_STATUS_I915 (1 << 6) +#define SDVOC_HOTPLUG_INT_STATUS (1 << 7) +#define SDVOB_HOTPLUG_INT_STATUS (1 << 6) /* SDVO port control */ #define SDVOB 0x61140 @@ -1755,10 +1711,8 @@ #define VIDEO_DIP_PORT_C (2 << 29) #define VIDEO_DIP_PORT_D (3 << 29) #define VIDEO_DIP_PORT_MASK (3 << 29) -#define VIDEO_DIP_ENABLE_GCP (1 << 25) #define VIDEO_DIP_ENABLE_AVI (1 << 21) #define VIDEO_DIP_ENABLE_VENDOR (2 << 21) -#define VIDEO_DIP_ENABLE_GAMUT (4 << 21) #define VIDEO_DIP_ENABLE_SPD (8 << 21) #define VIDEO_DIP_SELECT_AVI (0 << 19) #define VIDEO_DIP_SELECT_VENDOR (1 << 19) @@ -1769,11 +1723,7 @@ #define VIDEO_DIP_FREQ_2VSYNC (2 << 16) #define VIDEO_DIP_FREQ_MASK (3 << 16) /* HSW and later: */ -#define VIDEO_DIP_ENABLE_VSC_HSW (1 << 20) -#define VIDEO_DIP_ENABLE_GCP_HSW (1 << 16) #define VIDEO_DIP_ENABLE_AVI_HSW (1 << 12) -#define VIDEO_DIP_ENABLE_VS_HSW (1 << 8) -#define VIDEO_DIP_ENABLE_GMP_HSW (1 << 4) #define VIDEO_DIP_ENABLE_SPD_HSW (1 << 0) /* Panel power sequencing */ @@ -1845,35 +1795,18 @@ #define PFIT_AUTO_RATIOS 0x61238 /* Backlight control */ -#define BLC_PWM_CTL2 0x61250 /* 965+ only */ -#define BLM_PWM_ENABLE (1 << 31) -#define BLM_COMBINATION_MODE (1 << 30) /* gen4 only */ -#define BLM_PIPE_SELECT (1 << 29) -#define BLM_PIPE_SELECT_IVB (3 << 29) -#define BLM_PIPE_A (0 << 29) -#define BLM_PIPE_B (1 << 29) -#define BLM_PIPE_C (2 << 29) /* ivb + */ -#define BLM_PIPE(pipe) ((pipe) << 29) -#define BLM_POLARITY_I965 (1 << 28) /* gen4 only */ -#define BLM_PHASE_IN_INTERUPT_STATUS (1 << 26) -#define BLM_PHASE_IN_ENABLE (1 << 25) -#define BLM_PHASE_IN_INTERUPT_ENABL (1 << 24) -#define BLM_PHASE_IN_TIME_BASE_SHIFT (16) -#define BLM_PHASE_IN_TIME_BASE_MASK (0xff << 16) -#define BLM_PHASE_IN_COUNT_SHIFT (8) -#define BLM_PHASE_IN_COUNT_MASK (0xff << 8) -#define BLM_PHASE_IN_INCR_SHIFT (0) -#define BLM_PHASE_IN_INCR_MASK (0xff << 0) #define BLC_PWM_CTL 0x61254 +#define BACKLIGHT_MODULATION_FREQ_SHIFT (17) +#define BLC_PWM_CTL2 0x61250 /* 965+ only */ +#define BLM_COMBINATION_MODE (1 << 30) /* * This is the most significant 15 bits of the number of backlight cycles in a * complete cycle of the modulated backlight control. * * The actual value is this field multiplied by two. */ -#define BACKLIGHT_MODULATION_FREQ_SHIFT (17) -#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) -#define BLM_LEGACY_MODE (1 << 16) /* gen2 only */ +#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) +#define BLM_LEGACY_MODE (1 << 16) /* * This is the number of cycles out of the backlight modulation cycle for which * the backlight is on. @@ -1883,24 +1816,9 @@ */ #define BACKLIGHT_DUTY_CYCLE_SHIFT (0) #define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) -#define BACKLIGHT_DUTY_CYCLE_MASK_PNV (0xfffe) -#define BLM_POLARITY_PNV (1 << 0) /* pnv only */ #define BLC_HIST_CTL 0x61260 -/* New registers for PCH-split platforms. Safe where new bits show up, the - * register layout machtes with gen4 BLC_PWM_CTL[12]. */ -#define BLC_PWM_CPU_CTL2 0x48250 -#define BLC_PWM_CPU_CTL 0x48254 - -/* PCH CTL1 is totally different, all but the below bits are reserved. CTL2 is - * like the normal CTL from gen4 and earlier. Hooray for confusing naming. */ -#define BLC_PWM_PCH_CTL1 0xc8250 -#define BLM_PCH_PWM_ENABLE (1 << 30) -#define BLM_PCH_OVERRIDE_ENABLE (1 << 30) -#define BLM_PCH_POLARITY (1 << 29) -#define BLC_PWM_PCH_CTL2 0xc8254 - /* TV port control */ #define TV_CTL 0x68000 /** Enables the TV encoder */ @@ -2665,13 +2583,13 @@ #define PIPESTAT(pipe) _PIPE(pipe, _PIPEASTAT, _PIPEBSTAT) #define VLV_DPFLIPSTAT 0x70028 -#define PIPEB_LINE_COMPARE_INT_EN (1<<29) +#define PIPEB_LINE_COMPARE_STATUS (1<<29) #define PIPEB_HLINE_INT_EN (1<<28) #define PIPEB_VBLANK_INT_EN (1<<27) #define SPRITED_FLIPDONE_INT_EN (1<<26) #define SPRITEC_FLIPDONE_INT_EN (1<<25) #define PLANEB_FLIPDONE_INT_EN (1<<24) -#define PIPEA_LINE_COMPARE_INT_EN (1<<21) +#define PIPEA_LINE_COMPARE_STATUS (1<<21) #define PIPEA_HLINE_INT_EN (1<<20) #define PIPEA_VBLANK_INT_EN (1<<19) #define SPRITEB_FLIPDONE_INT_EN (1<<18) @@ -2979,14 +2897,13 @@ #define DSPSIZE(plane) _PIPE(plane, _DSPASIZE, _DSPBSIZE) #define DSPSURF(plane) _PIPE(plane, _DSPASURF, _DSPBSURF) #define DSPTILEOFF(plane) _PIPE(plane, _DSPATILEOFF, _DSPBTILEOFF) -#define DSPLINOFF(plane) DSPADDR(plane) /* Display/Sprite base address macros */ #define DISP_BASEADDR_MASK (0xfffff000) #define I915_LO_DISPBASE(val) (val & ~DISP_BASEADDR_MASK) #define I915_HI_DISPBASE(val) (val & DISP_BASEADDR_MASK) #define I915_MODIFY_DISPBASE(reg, gfx_addr) \ - (I915_WRITE((reg), (gfx_addr) | I915_LO_DISPBASE(I915_READ(reg)))) + (I915_WRITE(reg, gfx_addr | I915_LO_DISPBASE(I915_READ(reg)))) /* VBIOS flags */ #define SWF00 0x71410 @@ -3854,9 +3771,6 @@ #define _FDI_RXA_TUSIZE2 0xf0038 #define _FDI_RXB_TUSIZE1 0xf1030 #define _FDI_RXB_TUSIZE2 0xf1038 -#define FDI_RX_TP1_TO_TP2_48 (2<<20) -#define FDI_RX_TP1_TO_TP2_64 (3<<20) -#define FDI_RX_FDI_DELAY_90 (0x90<<0) #define FDI_RX_MISC(pipe) _PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC) #define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE1, _FDI_RXB_TUSIZE1) #define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE2, _FDI_RXB_TUSIZE2) @@ -3910,6 +3824,7 @@ #define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16) /* or SDVOB */ +#define VLV_HDMIB 0x61140 #define HDMIB 0xe1140 #define PORT_ENABLE (1 << 31) #define TRANSCODER(pipe) ((pipe) << 30) @@ -3940,18 +3855,20 @@ #define PCH_LVDS 0xe1180 #define LVDS_DETECTED (1 << 1) -/* vlv has 2 sets of panel control regs. */ -#define PIPEA_PP_STATUS 0x61200 -#define PIPEA_PP_CONTROL 0x61204 -#define PIPEA_PP_ON_DELAYS 0x61208 -#define PIPEA_PP_OFF_DELAYS 0x6120c -#define PIPEA_PP_DIVISOR 0x61210 +#define BLC_PWM_CPU_CTL2 0x48250 +#define PWM_ENABLE (1 << 31) +#define PWM_PIPE_A (0 << 29) +#define PWM_PIPE_B (1 << 29) +#define BLC_PWM_CPU_CTL 0x48254 -#define PIPEB_PP_STATUS 0x61300 -#define PIPEB_PP_CONTROL 0x61304 -#define PIPEB_PP_ON_DELAYS 0x61308 -#define PIPEB_PP_OFF_DELAYS 0x6130c -#define PIPEB_PP_DIVISOR 0x61310 +#define BLC_PWM_PCH_CTL1 0xc8250 +#define PWM_PCH_ENABLE (1 << 31) +#define PWM_POLARITY_ACTIVE_LOW (1 << 29) +#define PWM_POLARITY_ACTIVE_HIGH (0 << 29) +#define PWM_POLARITY_ACTIVE_LOW2 (1 << 28) +#define PWM_POLARITY_ACTIVE_HIGH2 (0 << 28) + +#define BLC_PWM_PCH_CTL2 0xc8254 #define PCH_PP_STATUS 0xc7200 #define PCH_PP_CONTROL 0xc7204 @@ -4075,7 +3992,6 @@ #define FORCEWAKE 0xA18C #define FORCEWAKE_VLV 0x1300b0 #define FORCEWAKE_ACK_VLV 0x1300b4 -#define FORCEWAKE_ACK_HSW 0x130044 #define FORCEWAKE_ACK 0x130090 #define FORCEWAKE_MT 0xa188 /* multi-threaded */ #define FORCEWAKE_MT_ACK 0x130040 @@ -4096,15 +4012,10 @@ # define GEN6_CSUNIT_CLOCK_GATE_DISABLE (1 << 7) #define GEN6_UCGCTL2 0x9404 -# define GEN7_VDSUNIT_CLOCK_GATE_DISABLE (1 << 30) -# define GEN7_TDLUNIT_CLOCK_GATE_DISABLE (1 << 22) # define GEN6_RCZUNIT_CLOCK_GATE_DISABLE (1 << 13) # define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12) # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11) -#define GEN7_UCGCTL4 0x940c -#define GEN7_L3BANK2X_CLOCK_GATE_DISABLE (1<<25) - #define GEN6_RPNSWREQ 0xA008 #define GEN6_TURBO_DISABLE (1<<31) #define GEN6_FREQUENCY(x) ((x)<<25) @@ -4136,7 +4047,6 @@ #define GEN6_RP_UP_IDLE_MIN (0x1<<3) #define GEN6_RP_UP_BUSY_AVG (0x2<<3) #define GEN6_RP_UP_BUSY_CONT (0x4<<3) -#define GEN7_RP_DOWN_IDLE_AVG (0x2<<0) #define GEN6_RP_DOWN_IDLE_CONT (0x1<<0) #define GEN6_RP_UP_THRESHOLD 0xA02C #define GEN6_RP_DOWN_THRESHOLD 0xA030 @@ -4201,26 +4111,6 @@ #define GEN6_RC6 3 #define GEN6_RC7 4 -#define GEN7_MISCCPCTL (0x9424) -#define GEN7_DOP_CLOCK_GATE_ENABLE (1<<0) - -/* IVYBRIDGE DPF */ -#define GEN7_L3CDERRST1 0xB008 /* L3CD Error Status 1 */ -#define GEN7_L3CDERRST1_ROW_MASK (0x7ff<<14) -#define GEN7_PARITY_ERROR_VALID (1<<13) -#define GEN7_L3CDERRST1_BANK_MASK (3<<11) -#define GEN7_L3CDERRST1_SUBBANK_MASK (7<<8) -#define GEN7_PARITY_ERROR_ROW(reg) \ - ((reg & GEN7_L3CDERRST1_ROW_MASK) >> 14) -#define GEN7_PARITY_ERROR_BANK(reg) \ - ((reg & GEN7_L3CDERRST1_BANK_MASK) >> 11) -#define GEN7_PARITY_ERROR_SUBBANK(reg) \ - ((reg & GEN7_L3CDERRST1_SUBBANK_MASK) >> 8) -#define GEN7_L3CDERRST1_ENABLE (1<<7) - -#define GEN7_L3LOG_BASE 0xB070 -#define GEN7_L3LOG_SIZE 0x80 - #define G4X_AUD_VID_DID 0x62020 #define INTEL_AUDIO_DEVCL 0x808629FB #define INTEL_AUDIO_DEVBLC 0x80862801 @@ -4287,7 +4177,7 @@ PIPE_DDI_FUNC_CTL_B) #define PIPE_DDI_FUNC_ENABLE (1<<31) /* Those bits are ignored by pipe EDP since it can only connect to DDI A */ -#define PIPE_DDI_PORT_MASK (7<<28) +#define PIPE_DDI_PORT_MASK (0xf<<28) #define PIPE_DDI_SELECT_PORT(x) ((x)<<28) #define PIPE_DDI_MODE_SELECT_HDMI (0<<24) #define PIPE_DDI_MODE_SELECT_DVI (1<<24) @@ -4445,7 +4335,7 @@ #define PIPE_WM_LINETIME_B 0x45274 #define PIPE_WM_LINETIME(pipe) _PIPE(pipe, \ PIPE_WM_LINETIME_A, \ - PIPE_WM_LINETIME_B) + PIPE_WM_LINETIME_A) #define PIPE_WM_LINETIME_MASK (0x1ff) #define PIPE_WM_LINETIME_TIME(x) ((x)) #define PIPE_WM_LINETIME_IPS_LINETIME_MASK (0x1ff<<16) @@ -4457,9 +4347,4 @@ #define SFUSE_STRAP_DDIC_DETECTED (1<<1) #define SFUSE_STRAP_DDID_DETECTED (1<<0) -#define WM_DBG 0x45280 -#define WM_DBG_DISALLOW_MULTIPLE_LP (1<<0) -#define WM_DBG_DISALLOW_MAXFIFO (1<<1) -#define WM_DBG_DISALLOW_SPRITE (1<<2) - #endif /* _I915_REG_H_ */ diff --git a/trunk/drivers/gpu/drm/i915/i915_suspend.c b/trunk/drivers/gpu/drm/i915/i915_suspend.c index 4776ccf1b3cd..a748e5cabe14 100644 --- a/trunk/drivers/gpu/drm/i915/i915_suspend.c +++ b/trunk/drivers/gpu/drm/i915/i915_suspend.c @@ -828,7 +828,10 @@ int i915_save_state(struct drm_device *dev) dev_priv->saveIMR = I915_READ(IMR); } - intel_disable_gt_powersave(dev); + if (IS_IRONLAKE_M(dev)) + ironlake_disable_drps(dev); + if (INTEL_INFO(dev)->gen >= 6) + gen6_disable_rps(dev); /* Cache mode state */ dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); diff --git a/trunk/drivers/gpu/drm/i915/i915_sysfs.c b/trunk/drivers/gpu/drm/i915/i915_sysfs.c index 2f5388af8df9..79f83445afa0 100644 --- a/trunk/drivers/gpu/drm/i915/i915_sysfs.c +++ b/trunk/drivers/gpu/drm/i915/i915_sysfs.c @@ -29,7 +29,6 @@ #include #include #include -#include "intel_drv.h" #include "i915_drv.h" static u32 calc_residency(struct drm_device *dev, const u32 reg) @@ -93,134 +92,20 @@ static struct attribute_group rc6_attr_group = { .attrs = rc6_attrs }; -static int l3_access_valid(struct drm_device *dev, loff_t offset) -{ - if (!IS_IVYBRIDGE(dev)) - return -EPERM; - - if (offset % 4 != 0) - return -EINVAL; - - if (offset >= GEN7_L3LOG_SIZE) - return -ENXIO; - - return 0; -} - -static ssize_t -i915_l3_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t offset, size_t count) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); - struct drm_device *drm_dev = dminor->dev; - struct drm_i915_private *dev_priv = drm_dev->dev_private; - uint32_t misccpctl; - int i, ret; - - ret = l3_access_valid(drm_dev, offset); - if (ret) - return ret; - - ret = i915_mutex_lock_interruptible(drm_dev); - if (ret) - return ret; - - misccpctl = I915_READ(GEN7_MISCCPCTL); - I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); - - for (i = offset; count >= 4 && i < GEN7_L3LOG_SIZE; i += 4, count -= 4) - *((uint32_t *)(&buf[i])) = I915_READ(GEN7_L3LOG_BASE + i); - - I915_WRITE(GEN7_MISCCPCTL, misccpctl); - - mutex_unlock(&drm_dev->struct_mutex); - - return i - offset; -} - -static ssize_t -i915_l3_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t offset, size_t count) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); - struct drm_device *drm_dev = dminor->dev; - struct drm_i915_private *dev_priv = drm_dev->dev_private; - u32 *temp = NULL; /* Just here to make handling failures easy */ - int ret; - - ret = l3_access_valid(drm_dev, offset); - if (ret) - return ret; - - ret = i915_mutex_lock_interruptible(drm_dev); - if (ret) - return ret; - - if (!dev_priv->mm.l3_remap_info) { - temp = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL); - if (!temp) { - mutex_unlock(&drm_dev->struct_mutex); - return -ENOMEM; - } - } - - ret = i915_gpu_idle(drm_dev); - if (ret) { - kfree(temp); - mutex_unlock(&drm_dev->struct_mutex); - return ret; - } - - /* TODO: Ideally we really want a GPU reset here to make sure errors - * aren't propagated. Since I cannot find a stable way to reset the GPU - * at this point it is left as a TODO. - */ - if (temp) - dev_priv->mm.l3_remap_info = temp; - - memcpy(dev_priv->mm.l3_remap_info + (offset/4), - buf + (offset/4), - count); - - i915_gem_l3_remap(drm_dev); - - mutex_unlock(&drm_dev->struct_mutex); - - return count; -} - -static struct bin_attribute dpf_attrs = { - .attr = {.name = "l3_parity", .mode = (S_IRUSR | S_IWUSR)}, - .size = GEN7_L3LOG_SIZE, - .read = i915_l3_read, - .write = i915_l3_write, - .mmap = NULL -}; - void i915_setup_sysfs(struct drm_device *dev) { int ret; - if (INTEL_INFO(dev)->gen >= 6) { - ret = sysfs_merge_group(&dev->primary->kdev.kobj, - &rc6_attr_group); - if (ret) - DRM_ERROR("RC6 residency sysfs setup failed\n"); - } + /* ILK doesn't have any residency information */ + if (INTEL_INFO(dev)->gen < 6) + return; - if (IS_IVYBRIDGE(dev)) { - ret = device_create_bin_file(&dev->primary->kdev, &dpf_attrs); - if (ret) - DRM_ERROR("l3 parity sysfs setup failed\n"); - } + ret = sysfs_merge_group(&dev->primary->kdev.kobj, &rc6_attr_group); + if (ret) + DRM_ERROR("sysfs setup failed\n"); } void i915_teardown_sysfs(struct drm_device *dev) { - device_remove_bin_file(&dev->primary->kdev, &dpf_attrs); sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group); } diff --git a/trunk/drivers/gpu/drm/i915/i915_trace.h b/trunk/drivers/gpu/drm/i915/i915_trace.h index fe90b3a84a6d..dac7bba4d9da 100644 --- a/trunk/drivers/gpu/drm/i915/i915_trace.h +++ b/trunk/drivers/gpu/drm/i915/i915_trace.h @@ -311,33 +311,9 @@ DEFINE_EVENT(i915_gem_request, i915_gem_request_retire, TP_ARGS(ring, seqno) ); -TRACE_EVENT(i915_gem_request_wait_begin, +DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_begin, TP_PROTO(struct intel_ring_buffer *ring, u32 seqno), - TP_ARGS(ring, seqno), - - TP_STRUCT__entry( - __field(u32, dev) - __field(u32, ring) - __field(u32, seqno) - __field(bool, blocking) - ), - - /* NB: the blocking information is racy since mutex_is_locked - * doesn't check that the current thread holds the lock. The only - * other option would be to pass the boolean information of whether - * or not the class was blocking down through the stack which is - * less desirable. - */ - TP_fast_assign( - __entry->dev = ring->dev->primary->index; - __entry->ring = ring->id; - __entry->seqno = seqno; - __entry->blocking = mutex_is_locked(&ring->dev->struct_mutex); - ), - - TP_printk("dev=%u, ring=%u, seqno=%u, blocking=%s", - __entry->dev, __entry->ring, __entry->seqno, - __entry->blocking ? "yes (NB)" : "no") + TP_ARGS(ring, seqno) ); DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_end, diff --git a/trunk/drivers/gpu/drm/i915/intel_bios.c b/trunk/drivers/gpu/drm/i915/intel_bios.c index 8c6074154bf6..353459362f6f 100644 --- a/trunk/drivers/gpu/drm/i915/intel_bios.c +++ b/trunk/drivers/gpu/drm/i915/intel_bios.c @@ -692,7 +692,7 @@ static const struct dmi_system_id intel_no_opregion_vbt[] = { * * Returns 0 on success, nonzero on failure. */ -int +bool intel_parse_bios(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; diff --git a/trunk/drivers/gpu/drm/i915/intel_bios.h b/trunk/drivers/gpu/drm/i915/intel_bios.h index 31c2107e7825..dbda6e3bdf07 100644 --- a/trunk/drivers/gpu/drm/i915/intel_bios.h +++ b/trunk/drivers/gpu/drm/i915/intel_bios.h @@ -476,7 +476,7 @@ struct bdb_edp { } __attribute__ ((packed)); void intel_setup_bios(struct drm_device *dev); -int intel_parse_bios(struct drm_device *dev); +bool intel_parse_bios(struct drm_device *dev); /* * Driver<->VBIOS interaction occurs through scratch bits in diff --git a/trunk/drivers/gpu/drm/i915/intel_crt.c b/trunk/drivers/gpu/drm/i915/intel_crt.c index 48e3b76e0ab2..75a70c46ef1b 100644 --- a/trunk/drivers/gpu/drm/i915/intel_crt.c +++ b/trunk/drivers/gpu/drm/i915/intel_crt.c @@ -88,9 +88,6 @@ static void gmch_crt_dpms(struct drm_encoder *encoder, int mode) temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); temp &= ~ADPA_DAC_ENABLE; - if (IS_VALLEYVIEW(dev) && mode != DRM_MODE_DPMS_ON) - mode = DRM_MODE_DPMS_OFF; - switch (mode) { case DRM_MODE_DPMS_ON: temp |= ADPA_DAC_ENABLE; @@ -132,7 +129,7 @@ static int intel_crt_mode_valid(struct drm_connector *connector, } static bool intel_crt_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; @@ -233,42 +230,6 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) return ret; } -static bool valleyview_crt_detect_hotplug(struct drm_connector *connector) -{ - struct drm_device *dev = connector->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - u32 adpa; - bool ret; - u32 save_adpa; - - save_adpa = adpa = I915_READ(ADPA); - DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa); - - adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER; - - I915_WRITE(ADPA, adpa); - - if (wait_for((I915_READ(ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0, - 1000)) { - DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); - I915_WRITE(ADPA, save_adpa); - } - - /* Check the status to see if both blue and green are on now */ - adpa = I915_READ(ADPA); - if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0) - ret = true; - else - ret = false; - - DRM_DEBUG_KMS("valleyview hotplug adpa=0x%x, result %d\n", adpa, ret); - - /* FIXME: debug force function and remove */ - ret = true; - - return ret; -} - /** * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence. * @@ -288,9 +249,6 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) if (HAS_PCH_SPLIT(dev)) return intel_ironlake_crt_detect_hotplug(connector); - if (IS_VALLEYVIEW(dev)) - return valleyview_crt_detect_hotplug(connector); - /* * On 4 series desktop, CRT detect sequence need to be done twice * to get a reliable result. @@ -495,27 +453,18 @@ intel_crt_detect(struct drm_connector *connector, bool force) struct intel_load_detect_pipe tmp; if (I915_HAS_HOTPLUG(dev)) { - /* We can not rely on the HPD pin always being correctly wired - * up, for example many KVM do not pass it through, and so - * only trust an assertion that the monitor is connected. - */ if (intel_crt_detect_hotplug(connector)) { DRM_DEBUG_KMS("CRT detected via hotplug\n"); return connector_status_connected; - } else + } else { DRM_DEBUG_KMS("CRT not detected via hotplug\n"); + return connector_status_disconnected; + } } if (intel_crt_detect_ddc(connector)) return connector_status_connected; - /* Load detection is broken on HPD capable machines. Whoever wants a - * broken monitor (without edid) to work behind a broken kvm (that fails - * to have the right resistors for HP detection) needs to fix this up. - * For now just bail out. */ - if (I915_HAS_HOTPLUG(dev)) - return connector_status_disconnected; - if (!force) return connector->status; diff --git a/trunk/drivers/gpu/drm/i915/intel_ddi.c b/trunk/drivers/gpu/drm/i915/intel_ddi.c index 933c74859172..46d1e886c692 100644 --- a/trunk/drivers/gpu/drm/i915/intel_ddi.c +++ b/trunk/drivers/gpu/drm/i915/intel_ddi.c @@ -170,15 +170,6 @@ void hsw_fdi_link_train(struct drm_crtc *crtc) udelay(600); - /* We need to program FDI_RX_MISC with the default TP1 to TP2 - * values before enabling the receiver, and configure the delay - * for the FDI timing generator to 90h. Luckily, all the other - * bits are supposed to be zeroed, so we can write those values - * directly. - */ - I915_WRITE(FDI_RX_MISC(pipe), FDI_RX_TP1_TO_TP2_48 | - FDI_RX_FDI_DELAY_90); - /* Enable CPU FDI Receiver with auto-training */ reg = FDI_RX_CTL(pipe); I915_WRITE(reg, @@ -735,7 +726,8 @@ void intel_ddi_mode_set(struct drm_encoder *encoder, I915_WRITE(DDI_FUNC_CTL(pipe), temp); - intel_hdmi->set_infoframes(encoder, adjusted_mode); + intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); + intel_hdmi_set_spd_infoframe(encoder); } void intel_ddi_dpms(struct drm_encoder *encoder, int mode) diff --git a/trunk/drivers/gpu/drm/i915/intel_display.c b/trunk/drivers/gpu/drm/i915/intel_display.c index bc25a24a08c5..a8538ac0299d 100644 --- a/trunk/drivers/gpu/drm/i915/intel_display.c +++ b/trunk/drivers/gpu/drm/i915/intel_display.c @@ -98,11 +98,6 @@ intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *match_clock, intel_clock_t *best_clock); -static bool -intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *match_clock, - intel_clock_t *best_clock); - static inline u32 /* units of 100MHz */ intel_fdi_link_freq(struct drm_device *dev) { @@ -364,48 +359,6 @@ static const intel_limit_t intel_limits_ironlake_display_port = { .find_pll = intel_find_pll_ironlake_dp, }; -static const intel_limit_t intel_limits_vlv_dac = { - .dot = { .min = 25000, .max = 270000 }, - .vco = { .min = 4000000, .max = 6000000 }, - .n = { .min = 1, .max = 7 }, - .m = { .min = 22, .max = 450 }, /* guess */ - .m1 = { .min = 2, .max = 3 }, - .m2 = { .min = 11, .max = 156 }, - .p = { .min = 10, .max = 30 }, - .p1 = { .min = 2, .max = 3 }, - .p2 = { .dot_limit = 270000, - .p2_slow = 2, .p2_fast = 20 }, - .find_pll = intel_vlv_find_best_pll, -}; - -static const intel_limit_t intel_limits_vlv_hdmi = { - .dot = { .min = 20000, .max = 165000 }, - .vco = { .min = 5994000, .max = 4000000 }, - .n = { .min = 1, .max = 7 }, - .m = { .min = 60, .max = 300 }, /* guess */ - .m1 = { .min = 2, .max = 3 }, - .m2 = { .min = 11, .max = 156 }, - .p = { .min = 10, .max = 30 }, - .p1 = { .min = 2, .max = 3 }, - .p2 = { .dot_limit = 270000, - .p2_slow = 2, .p2_fast = 20 }, - .find_pll = intel_vlv_find_best_pll, -}; - -static const intel_limit_t intel_limits_vlv_dp = { - .dot = { .min = 162000, .max = 270000 }, - .vco = { .min = 5994000, .max = 4000000 }, - .n = { .min = 1, .max = 7 }, - .m = { .min = 60, .max = 300 }, /* guess */ - .m1 = { .min = 2, .max = 3 }, - .m2 = { .min = 11, .max = 156 }, - .p = { .min = 10, .max = 30 }, - .p1 = { .min = 2, .max = 3 }, - .p2 = { .dot_limit = 270000, - .p2_slow = 2, .p2_fast = 20 }, - .find_pll = intel_vlv_find_best_pll, -}; - u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg) { unsigned long flags; @@ -431,28 +384,6 @@ u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg) return val; } -static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg, - u32 val) -{ - unsigned long flags; - - spin_lock_irqsave(&dev_priv->dpio_lock, flags); - if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) { - DRM_ERROR("DPIO idle wait timed out\n"); - goto out_unlock; - } - - I915_WRITE(DPIO_DATA, val); - I915_WRITE(DPIO_REG, reg); - I915_WRITE(DPIO_PKT, DPIO_RID | DPIO_OP_WRITE | DPIO_PORTID | - DPIO_BYTE); - if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) - DRM_ERROR("DPIO write wait timed out\n"); - -out_unlock: - spin_unlock_irqrestore(&dev_priv->dpio_lock, flags); -} - static void vlv_init_dpio(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -503,7 +434,7 @@ static bool is_dual_link_lvds(struct drm_i915_private *dev_priv, * register is uninitialized. */ val = I915_READ(reg); - if (!(val & ~(LVDS_PIPE_MASK | LVDS_DETECTED))) + if (!(val & ~LVDS_DETECTED)) val = dev_priv->bios_lvds_val; dev_priv->lvds_val = val; } @@ -579,13 +510,6 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc, int refclk) limit = &intel_limits_pineview_lvds; else limit = &intel_limits_pineview_sdvo; - } else if (IS_VALLEYVIEW(dev)) { - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) - limit = &intel_limits_vlv_dac; - else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) - limit = &intel_limits_vlv_hdmi; - else - limit = &intel_limits_vlv_dp; } else if (!IS_GEN2(dev)) { if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) limit = &intel_limits_i9xx_lvds; @@ -627,10 +551,11 @@ static void intel_clock(struct drm_device *dev, int refclk, intel_clock_t *clock bool intel_pipe_has_type(struct drm_crtc *crtc, int type) { struct drm_device *dev = crtc->dev; + struct drm_mode_config *mode_config = &dev->mode_config; struct intel_encoder *encoder; - for_each_encoder_on_crtc(dev, crtc, encoder) - if (encoder->type == type) + list_for_each_entry(encoder, &mode_config->encoder_list, base.head) + if (encoder->base.crtc == crtc && encoder->type == type) return true; return false; @@ -858,73 +783,6 @@ intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, memcpy(best_clock, &clock, sizeof(intel_clock_t)); return true; } -static bool -intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *match_clock, - intel_clock_t *best_clock) -{ - u32 p1, p2, m1, m2, vco, bestn, bestm1, bestm2, bestp1, bestp2; - u32 m, n, fastclk; - u32 updrate, minupdate, fracbits, p; - unsigned long bestppm, ppm, absppm; - int dotclk, flag; - - dotclk = target * 1000; - bestppm = 1000000; - ppm = absppm = 0; - fastclk = dotclk / (2*100); - updrate = 0; - minupdate = 19200; - fracbits = 1; - n = p = p1 = p2 = m = m1 = m2 = vco = bestn = 0; - bestm1 = bestm2 = bestp1 = bestp2 = 0; - - /* based on hardware requirement, prefer smaller n to precision */ - for (n = limit->n.min; n <= ((refclk) / minupdate); n++) { - updrate = refclk / n; - for (p1 = limit->p1.max; p1 > limit->p1.min; p1--) { - for (p2 = limit->p2.p2_fast+1; p2 > 0; p2--) { - if (p2 > 10) - p2 = p2 - 1; - p = p1 * p2; - /* based on hardware requirement, prefer bigger m1,m2 values */ - for (m1 = limit->m1.min; m1 <= limit->m1.max; m1++) { - m2 = (((2*(fastclk * p * n / m1 )) + - refclk) / (2*refclk)); - m = m1 * m2; - vco = updrate * m; - if (vco >= limit->vco.min && vco < limit->vco.max) { - ppm = 1000000 * ((vco / p) - fastclk) / fastclk; - absppm = (ppm > 0) ? ppm : (-ppm); - if (absppm < 100 && ((p1 * p2) > (bestp1 * bestp2))) { - bestppm = 0; - flag = 1; - } - if (absppm < bestppm - 10) { - bestppm = absppm; - flag = 1; - } - if (flag) { - bestn = n; - bestm1 = m1; - bestm2 = m2; - bestp1 = p1; - bestp2 = p2; - flag = 0; - } - } - } - } - } - } - best_clock->n = bestn; - best_clock->m1 = bestm1; - best_clock->m2 = bestm2; - best_clock->p1 = bestp1; - best_clock->p2 = bestp2; - - return true; -} static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe) { @@ -1374,9 +1232,6 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val), "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); - - WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), - "IBX PCH dp port still using transcoder B\n"); } static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, @@ -1386,9 +1241,6 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, WARN(hdmi_pipe_enabled(dev_priv, val, pipe), "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); - - WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), - "IBX PCH hdmi port still using transcoder B\n"); } static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, @@ -1435,7 +1287,7 @@ static void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) u32 val; /* No really, not for ILK+ */ - BUG_ON(!IS_VALLEYVIEW(dev_priv->dev) && dev_priv->info->gen >= 5); + BUG_ON(dev_priv->info->gen >= 5); /* PLL is protected by panel, make sure we can write it */ if (IS_MOBILE(dev_priv->dev) && !IS_I830(dev_priv->dev)) @@ -1492,7 +1344,7 @@ intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value) unsigned long flags; spin_lock_irqsave(&dev_priv->dpio_lock, flags); - if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0, + if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_READY) == 0, 100)) { DRM_ERROR("timeout waiting for SBI to become ready\n"); goto out_unlock; @@ -1506,7 +1358,7 @@ intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value) SBI_BUSY | SBI_CTL_OP_CRWR); - if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0, + if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_READY | SBI_RESPONSE_SUCCESS)) == 0, 100)) { DRM_ERROR("timeout waiting for SBI to complete write transaction\n"); goto out_unlock; @@ -1520,10 +1372,10 @@ static u32 intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg) { unsigned long flags; - u32 value = 0; + u32 value; spin_lock_irqsave(&dev_priv->dpio_lock, flags); - if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0, + if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_READY) == 0, 100)) { DRM_ERROR("timeout waiting for SBI to become ready\n"); goto out_unlock; @@ -1535,7 +1387,7 @@ intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg) SBI_BUSY | SBI_CTL_OP_CRRD); - if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0, + if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_READY | SBI_RESPONSE_SUCCESS)) == 0, 100)) { DRM_ERROR("timeout waiting for SBI to complete read transaction\n"); goto out_unlock; @@ -1972,22 +1824,6 @@ void intel_unpin_fb_obj(struct drm_i915_gem_object *obj) i915_gem_object_unpin(obj); } -/* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel - * is assumed to be a power-of-two. */ -static unsigned long gen4_compute_dspaddr_offset_xtiled(int *x, int *y, - unsigned int bpp, - unsigned int pitch) -{ - int tile_rows, tiles; - - tile_rows = *y / 8; - *y %= 8; - tiles = *x / (512/bpp); - *x %= 512/bpp; - - return tile_rows * pitch * 8 + tiles * 4096; -} - static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y) { @@ -1997,7 +1833,7 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct intel_framebuffer *intel_fb; struct drm_i915_gem_object *obj; int plane = intel_crtc->plane; - unsigned long linear_offset; + unsigned long Start, Offset; u32 dspcntr; u32 reg; @@ -2044,28 +1880,18 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, I915_WRITE(reg, dspcntr); - linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); - - if (INTEL_INFO(dev)->gen >= 4) { - intel_crtc->dspaddr_offset = - gen4_compute_dspaddr_offset_xtiled(&x, &y, - fb->bits_per_pixel / 8, - fb->pitches[0]); - linear_offset -= intel_crtc->dspaddr_offset; - } else { - intel_crtc->dspaddr_offset = linear_offset; - } + Start = obj->gtt_offset; + Offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); - DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n", - obj->gtt_offset, linear_offset, x, y, fb->pitches[0]); + DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", + Start, Offset, x, y, fb->pitches[0]); I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); if (INTEL_INFO(dev)->gen >= 4) { - I915_MODIFY_DISPBASE(DSPSURF(plane), - obj->gtt_offset + intel_crtc->dspaddr_offset); + I915_MODIFY_DISPBASE(DSPSURF(plane), Start); I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); - I915_WRITE(DSPLINOFF(plane), linear_offset); + I915_WRITE(DSPADDR(plane), Offset); } else - I915_WRITE(DSPADDR(plane), obj->gtt_offset + linear_offset); + I915_WRITE(DSPADDR(plane), Start + Offset); POSTING_READ(reg); return 0; @@ -2080,7 +1906,7 @@ static int ironlake_update_plane(struct drm_crtc *crtc, struct intel_framebuffer *intel_fb; struct drm_i915_gem_object *obj; int plane = intel_crtc->plane; - unsigned long linear_offset; + unsigned long Start, Offset; u32 dspcntr; u32 reg; @@ -2135,20 +1961,15 @@ static int ironlake_update_plane(struct drm_crtc *crtc, I915_WRITE(reg, dspcntr); - linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); - intel_crtc->dspaddr_offset = - gen4_compute_dspaddr_offset_xtiled(&x, &y, - fb->bits_per_pixel / 8, - fb->pitches[0]); - linear_offset -= intel_crtc->dspaddr_offset; + Start = obj->gtt_offset; + Offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); - DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n", - obj->gtt_offset, linear_offset, x, y, fb->pitches[0]); + DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", + Start, Offset, x, y, fb->pitches[0]); I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); - I915_MODIFY_DISPBASE(DSPSURF(plane), - obj->gtt_offset + intel_crtc->dspaddr_offset); + I915_MODIFY_DISPBASE(DSPSURF(plane), Start); I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); - I915_WRITE(DSPLINOFF(plane), linear_offset); + I915_WRITE(DSPADDR(plane), Offset); POSTING_READ(reg); return 0; @@ -2835,13 +2656,16 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) static bool intel_crtc_driving_pch(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; + struct drm_mode_config *mode_config = &dev->mode_config; struct intel_encoder *encoder; /* * If there's a non-PCH eDP on this crtc, it must be DP_A, and that * must be driven by its own crtc; no sharing is possible. */ - for_each_encoder_on_crtc(dev, crtc, encoder) { + list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { + if (encoder->base.crtc != crtc) + continue; /* On Haswell, LPT PCH handles the VGA connection via FDI, and Haswell * CPU handles all others */ @@ -3730,12 +3554,16 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_encoder *encoder; struct drm_connector *connector; - struct intel_encoder *intel_encoder; unsigned int display_bpc = UINT_MAX, bpc; /* Walk the encoders & connectors on this crtc, get min bpc */ - for_each_encoder_on_crtc(dev, crtc, intel_encoder) { + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + struct intel_encoder *intel_encoder = to_intel_encoder(encoder); + + if (encoder->crtc != crtc) + continue; if (intel_encoder->type == INTEL_OUTPUT_LVDS) { unsigned int lvds_bpc; @@ -3767,7 +3595,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, /* Not one of the known troublemakers, check the EDID */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->encoder != &intel_encoder->base) + if (connector->encoder != encoder) continue; /* Don't use an invalid EDID bpc value */ @@ -3838,37 +3666,13 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, return display_bpc != bpc; } -static int vlv_get_refclk(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int refclk = 27000; /* for DP & HDMI */ - - return 100000; /* only one validated so far */ - - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { - refclk = 96000; - } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { - if (intel_panel_use_ssc(dev_priv)) - refclk = 100000; - else - refclk = 96000; - } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) { - refclk = 100000; - } - - return refclk; -} - static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; int refclk; - if (IS_VALLEYVIEW(dev)) { - refclk = vlv_get_refclk(crtc); - } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { refclk = dev_priv->lvds_ssc_freq * 1000; DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", @@ -3983,72 +3787,6 @@ static void intel_update_lvds(struct drm_crtc *crtc, intel_clock_t *clock, I915_WRITE(LVDS, temp); } -static void vlv_update_pll(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, - intel_clock_t *clock, intel_clock_t *reduced_clock, - int refclk, int num_connectors) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; - u32 dpll, mdiv, pdiv; - u32 bestn, bestm1, bestm2, bestp1, bestp2; - bool is_hdmi; - - is_hdmi = intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI); - - bestn = clock->n; - bestm1 = clock->m1; - bestm2 = clock->m2; - bestp1 = clock->p1; - bestp2 = clock->p2; - - /* Enable DPIO clock input */ - dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV | - DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV; - I915_WRITE(DPLL(pipe), dpll); - POSTING_READ(DPLL(pipe)); - - mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK)); - mdiv |= ((bestp1 << DPIO_P1_SHIFT) | (bestp2 << DPIO_P2_SHIFT)); - mdiv |= ((bestn << DPIO_N_SHIFT)); - mdiv |= (1 << DPIO_POST_DIV_SHIFT); - mdiv |= (1 << DPIO_K_SHIFT); - mdiv |= DPIO_ENABLE_CALIBRATION; - intel_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv); - - intel_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), 0x01000000); - - pdiv = DPIO_REFSEL_OVERRIDE | (5 << DPIO_PLL_MODESEL_SHIFT) | - (3 << DPIO_BIAS_CURRENT_CTL_SHIFT) | (1<<20) | - (8 << DPIO_DRIVER_CTL_SHIFT) | (5 << DPIO_CLK_BIAS_CTL_SHIFT); - intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), pdiv); - - intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe), 0x009f0051); - - dpll |= DPLL_VCO_ENABLE; - I915_WRITE(DPLL(pipe), dpll); - POSTING_READ(DPLL(pipe)); - if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1)) - DRM_ERROR("DPLL %d failed to lock\n", pipe); - - if (is_hdmi) { - u32 temp = intel_mode_get_pixel_multiplier(adjusted_mode); - - if (temp > 1) - temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; - else - temp = 0; - - I915_WRITE(DPLL_MD(pipe), temp); - POSTING_READ(DPLL_MD(pipe)); - } - - intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x641); /* ??? */ -} - static void i9xx_update_pll(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -4236,11 +3974,15 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, u32 dspcntr, pipeconf, vsyncshift; bool ok, has_reduced_clock = false, is_sdvo = false; bool is_lvds = false, is_tv = false, is_dp = false; + struct drm_mode_config *mode_config = &dev->mode_config; struct intel_encoder *encoder; const intel_limit_t *limit; int ret; - for_each_encoder_on_crtc(dev, crtc, encoder) { + list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { + if (encoder->base.crtc != crtc) + continue; + switch (encoder->type) { case INTEL_OUTPUT_LVDS: is_lvds = true; @@ -4302,9 +4044,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, if (IS_GEN2(dev)) i8xx_update_pll(crtc, adjusted_mode, &clock, num_connectors); - else if (IS_VALLEYVIEW(dev)) - vlv_update_pll(crtc, mode,adjusted_mode, &clock, NULL, - refclk, num_connectors); else i9xx_update_pll(crtc, mode, adjusted_mode, &clock, has_reduced_clock ? &reduced_clock : NULL, @@ -4543,11 +4282,15 @@ static int ironlake_get_refclk(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *encoder; + struct drm_mode_config *mode_config = &dev->mode_config; struct intel_encoder *edp_encoder = NULL; int num_connectors = 0; bool is_lvds = false; - for_each_encoder_on_crtc(dev, crtc, encoder) { + list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { + if (encoder->base.crtc != crtc) + continue; + switch (encoder->type) { case INTEL_OUTPUT_LVDS: is_lvds = true; @@ -4584,6 +4327,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf; bool ok, has_reduced_clock = false, is_sdvo = false; bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; + struct drm_mode_config *mode_config = &dev->mode_config; struct intel_encoder *encoder, *edp_encoder = NULL; const intel_limit_t *limit; int ret; @@ -4594,7 +4338,10 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, bool dither; bool is_cpu_edp = false, is_pch_edp = false; - for_each_encoder_on_crtc(dev, crtc, encoder) { + list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { + if (encoder->base.crtc != crtc) + continue; + switch (encoder->type) { case INTEL_OUTPUT_LVDS: is_lvds = true; @@ -4658,10 +4405,25 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, &clock, &reduced_clock); } - - if (is_sdvo && is_tv) - i9xx_adjust_sdvo_tv_clock(adjusted_mode, &clock); - + /* SDVO TV has fixed PLL values depend on its clock range, + this mirrors vbios setting. */ + if (is_sdvo && is_tv) { + if (adjusted_mode->clock >= 100000 + && adjusted_mode->clock < 140500) { + clock.p1 = 2; + clock.p2 = 10; + clock.n = 3; + clock.m1 = 16; + clock.m2 = 8; + } else if (adjusted_mode->clock >= 140500 + && adjusted_mode->clock <= 200000) { + clock.p1 = 1; + clock.p2 = 10; + clock.n = 6; + clock.m1 = 12; + clock.m2 = 8; + } + } /* FDI link */ pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); @@ -4669,8 +4431,16 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, /* CPU eDP doesn't require FDI link, so just set DP M/N according to current link config */ if (is_cpu_edp) { + target_clock = mode->clock; intel_edp_link_config(edp_encoder, &lane, &link_bw); } else { + /* [e]DP over FDI requires target mode clock + instead of link clock */ + if (is_dp) + target_clock = mode->clock; + else + target_clock = adjusted_mode->clock; + /* FDI is a binary signal running at ~2.7GHz, encoding * each output octet as 10 bits. The actual frequency * is stored as a divider into a 100MHz clock, and the @@ -4681,14 +4451,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; } - /* [e]DP over FDI requires target mode clock instead of link clock. */ - if (edp_encoder) - target_clock = intel_edp_target_clock(edp_encoder, mode); - else if (is_dp) - target_clock = mode->clock; - else - target_clock = adjusted_mode->clock; - /* determine panel color depth */ temp = I915_READ(PIPECONF(pipe)); temp &= ~PIPE_BPC_MASK; @@ -4900,8 +4662,16 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, if (is_lvds && has_reduced_clock && i915_powersave) { I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2); intel_crtc->lowfreq_avail = true; + if (HAS_PIPE_CXSR(dev)) { + DRM_DEBUG_KMS("enabling CxSR downclocking\n"); + pipeconf |= PIPECONF_CXSR_DOWNCLOCK; + } } else { I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp); + if (HAS_PIPE_CXSR(dev)) { + DRM_DEBUG_KMS("disabling CxSR downclocking\n"); + pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; + } } } @@ -6205,6 +5975,7 @@ static int intel_gen2_queue_flip(struct drm_device *dev, { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + unsigned long offset; u32 flip_mask; struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; int ret; @@ -6213,6 +5984,9 @@ static int intel_gen2_queue_flip(struct drm_device *dev, if (ret) goto err; + /* Offset into the new buffer for cases of shared fbs between CRTCs */ + offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8; + ret = intel_ring_begin(ring, 6); if (ret) goto err_unpin; @@ -6229,7 +6003,7 @@ static int intel_gen2_queue_flip(struct drm_device *dev, intel_ring_emit(ring, MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); intel_ring_emit(ring, fb->pitches[0]); - intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); + intel_ring_emit(ring, obj->gtt_offset + offset); intel_ring_emit(ring, 0); /* aux display base address, unused */ intel_ring_advance(ring); return 0; @@ -6247,6 +6021,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev, { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + unsigned long offset; u32 flip_mask; struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; int ret; @@ -6255,6 +6030,9 @@ static int intel_gen3_queue_flip(struct drm_device *dev, if (ret) goto err; + /* Offset into the new buffer for cases of shared fbs between CRTCs */ + offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8; + ret = intel_ring_begin(ring, 6); if (ret) goto err_unpin; @@ -6268,7 +6046,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev, intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); intel_ring_emit(ring, fb->pitches[0]); - intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); + intel_ring_emit(ring, obj->gtt_offset + offset); intel_ring_emit(ring, MI_NOOP); intel_ring_advance(ring); @@ -6306,9 +6084,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev, intel_ring_emit(ring, MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); intel_ring_emit(ring, fb->pitches[0]); - intel_ring_emit(ring, - (obj->gtt_offset + intel_crtc->dspaddr_offset) | - obj->tiling_mode); + intel_ring_emit(ring, obj->gtt_offset | obj->tiling_mode); /* XXX Enabling the panel-fitter across page-flip is so far * untested on non-native modes, so ignore it for now. @@ -6348,7 +6124,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev, intel_ring_emit(ring, MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode); - intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); + intel_ring_emit(ring, obj->gtt_offset); /* Contrary to the suggestions in the documentation, * "Enable Panel Fitter" does not seem to be required when page @@ -6411,7 +6187,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); - intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); + intel_ring_emit(ring, (obj->gtt_offset)); intel_ring_emit(ring, (MI_NOOP)); intel_ring_advance(ring); return 0; @@ -6443,19 +6219,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, unsigned long flags; int ret; - /* Can't change pixel format via MI display flips. */ - if (fb->pixel_format != crtc->fb->pixel_format) - return -EINVAL; - - /* - * TILEOFF/LINOFF registers can't be changed via MI display flips. - * Note that pitch changes could also affect these register. - */ - if (INTEL_INFO(dev)->gen > 3 && - (fb->offsets[0] != crtc->fb->offsets[0] || - fb->pitches[0] != crtc->fb->pitches[0])) - return -EINVAL; - work = kzalloc(sizeof *work, GFP_KERNEL); if (work == NULL) return -ENOMEM; @@ -6803,24 +6566,7 @@ static void intel_setup_outputs(struct drm_device *dev) if (!dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED)) intel_dp_init(dev, PCH_DP_D); - } else if (IS_VALLEYVIEW(dev)) { - int found; - - if (I915_READ(SDVOB) & PORT_DETECTED) { - /* SDVOB multiplex with HDMIB */ - found = intel_sdvo_init(dev, SDVOB, true); - if (!found) - intel_hdmi_init(dev, SDVOB); - if (!found && (I915_READ(DP_B) & DP_DETECTED)) - intel_dp_init(dev, DP_B); - } - - if (I915_READ(SDVOC) & PORT_DETECTED) - intel_hdmi_init(dev, SDVOC); - /* Shares lanes with HDMI on SDVOC */ - if (I915_READ(DP_C) & DP_DETECTED) - intel_dp_init(dev, DP_C); } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) { bool found = false; @@ -6877,7 +6623,7 @@ static void intel_setup_outputs(struct drm_device *dev) /* disable all the possible outputs/crtcs before entering KMS mode */ drm_helper_disable_unused_functions(dev); - if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) + if (HAS_PCH_SPLIT(dev)) ironlake_init_pch_refclk(dev); } @@ -7031,6 +6777,9 @@ static void intel_init_display(struct drm_device *dev) dev_priv->display.write_eld = ironlake_write_eld; } else dev_priv->display.update_wm = NULL; + } else if (IS_VALLEYVIEW(dev)) { + dev_priv->display.force_wake_get = vlv_force_wake_get; + dev_priv->display.force_wake_put = vlv_force_wake_put; } else if (IS_G4X(dev)) { dev_priv->display.write_eld = g4x_write_eld; } @@ -7174,13 +6923,20 @@ static void i915_disable_vga(struct drm_device *dev) void intel_modeset_init_hw(struct drm_device *dev) { - intel_prepare_ddi(dev); + struct drm_i915_private *dev_priv = dev->dev_private; intel_init_clock_gating(dev); - mutex_lock(&dev->struct_mutex); - intel_enable_gt_powersave(dev); - mutex_unlock(&dev->struct_mutex); + if (IS_IRONLAKE_M(dev)) { + ironlake_enable_drps(dev); + ironlake_enable_rc6(dev); + intel_init_emon(dev); + } + + if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) { + gen6_enable_rps(dev_priv); + gen6_update_ring_freq(dev_priv); + } } void intel_modeset_init(struct drm_device *dev) @@ -7202,6 +6958,8 @@ void intel_modeset_init(struct drm_device *dev) intel_init_pm(dev); + intel_prepare_ddi(dev); + intel_init_display(dev); if (IS_GEN2(dev)) { @@ -7214,7 +6972,7 @@ void intel_modeset_init(struct drm_device *dev) dev->mode_config.max_width = 8192; dev->mode_config.max_height = 8192; } - dev->mode_config.fb_base = dev_priv->mm.gtt_base_addr; + dev->mode_config.fb_base = dev->agp->base; DRM_DEBUG_KMS("%d display pipe%s available.\n", dev_priv->num_pipe, dev_priv->num_pipe > 1 ? "s" : ""); @@ -7267,9 +7025,13 @@ void intel_modeset_cleanup(struct drm_device *dev) intel_disable_fbc(dev); - intel_disable_gt_powersave(dev); + if (IS_IRONLAKE_M(dev)) + ironlake_disable_drps(dev); + if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) + gen6_disable_rps(dev); - ironlake_teardown_rc6(dev); + if (IS_IRONLAKE_M(dev)) + ironlake_disable_rc6(dev); if (IS_VALLEYVIEW(dev)) vlv_init_dpio(dev); diff --git a/trunk/drivers/gpu/drm/i915/intel_dp.c b/trunk/drivers/gpu/drm/i915/intel_dp.c index 2bc1505132c3..c0449324143c 100644 --- a/trunk/drivers/gpu/drm/i915/intel_dp.c +++ b/trunk/drivers/gpu/drm/i915/intel_dp.c @@ -155,18 +155,6 @@ intel_edp_link_config(struct intel_encoder *intel_encoder, *link_bw = 270000; } -int -intel_edp_target_clock(struct intel_encoder *intel_encoder, - struct drm_display_mode *mode) -{ - struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base); - - if (intel_dp->panel_fixed_mode) - return intel_dp->panel_fixed_mode->clock; - else - return mode->clock; -} - static int intel_dp_max_lane_count(struct intel_dp *intel_dp) { @@ -237,7 +225,7 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes) static bool intel_dp_adjust_dithering(struct intel_dp *intel_dp, struct drm_display_mode *mode, - bool adjust_mode) + struct drm_display_mode *adjusted_mode) { int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); int max_lanes = intel_dp_max_lane_count(intel_dp); @@ -251,8 +239,8 @@ intel_dp_adjust_dithering(struct intel_dp *intel_dp, if (mode_rate > max_rate) return false; - if (adjust_mode) - mode->private_flags + if (adjusted_mode) + adjusted_mode->private_flags |= INTEL_MODE_DP_FORCE_6BPC; return true; @@ -275,7 +263,7 @@ intel_dp_mode_valid(struct drm_connector *connector, return MODE_PANEL; } - if (!intel_dp_adjust_dithering(intel_dp, mode, false)) + if (!intel_dp_adjust_dithering(intel_dp, mode, NULL)) return MODE_CLOCK_HIGH; if (mode->clock < 10000) @@ -703,8 +691,7 @@ intel_dp_i2c_init(struct intel_dp *intel_dp, } static bool -intel_dp_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, +intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; @@ -719,23 +706,28 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode); intel_pch_panel_fitting(dev, DRM_MODE_SCALE_FULLSCREEN, mode, adjusted_mode); + /* + * the mode->clock is used to calculate the Data&Link M/N + * of the pipe. For the eDP the fixed clock should be used. + */ + mode->clock = intel_dp->panel_fixed_mode->clock; } - if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) + if (mode->flags & DRM_MODE_FLAG_DBLCLK) return false; DRM_DEBUG_KMS("DP link computation with max lane count %i " "max bw %02x pixel clock %iKHz\n", - max_lane_count, bws[max_clock], adjusted_mode->clock); + max_lane_count, bws[max_clock], mode->clock); - if (!intel_dp_adjust_dithering(intel_dp, adjusted_mode, true)) + if (!intel_dp_adjust_dithering(intel_dp, mode, adjusted_mode)) return false; bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24; - mode_rate = intel_dp_link_required(adjusted_mode->clock, bpp); + mode_rate = intel_dp_link_required(mode->clock, bpp); - for (clock = 0; clock <= max_clock; clock++) { - for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { + for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { + for (clock = 0; clock <= max_clock; clock++) { int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); if (mode_rate <= link_avail) { @@ -794,7 +786,8 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = crtc->dev; - struct intel_encoder *encoder; + struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_encoder *encoder; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int lane_count = 4; @@ -804,9 +797,13 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, /* * Find the lane count in the intel_encoder private */ - for_each_encoder_on_crtc(dev, crtc, encoder) { - struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + list_for_each_entry(encoder, &mode_config->encoder_list, head) { + struct intel_dp *intel_dp; + + if (encoder->crtc != crtc) + continue; + intel_dp = enc_to_intel_dp(encoder); if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT || intel_dp->base.type == INTEL_OUTPUT_EDP) { @@ -1925,7 +1922,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) DP |= DP_LINK_TRAIN_OFF; } - if (HAS_PCH_IBX(dev) && + if (!HAS_PCH_CPT(dev) && I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) { struct drm_crtc *crtc = intel_dp->base.base.crtc; @@ -2102,23 +2099,25 @@ g4x_dp_detect(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t bit; + uint32_t temp, bit; switch (intel_dp->output_reg) { case DP_B: - bit = DPB_HOTPLUG_LIVE_STATUS; + bit = DPB_HOTPLUG_INT_STATUS; break; case DP_C: - bit = DPC_HOTPLUG_LIVE_STATUS; + bit = DPC_HOTPLUG_INT_STATUS; break; case DP_D: - bit = DPD_HOTPLUG_LIVE_STATUS; + bit = DPD_HOTPLUG_INT_STATUS; break; default: return connector_status_unknown; } - if ((I915_READ(PORT_HOTPLUG_STAT) & bit) == 0) + temp = I915_READ(PORT_HOTPLUG_STAT); + + if ((temp & bit) == 0) return connector_status_disconnected; return intel_dp_detect_dpcd(intel_dp); @@ -2400,11 +2399,16 @@ int intel_trans_dp_port_sel(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; - struct intel_encoder *encoder; + struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_encoder *encoder; + + list_for_each_entry(encoder, &mode_config->encoder_list, head) { + struct intel_dp *intel_dp; - for_each_encoder_on_crtc(dev, crtc, encoder) { - struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + if (encoder->crtc != crtc) + continue; + intel_dp = enc_to_intel_dp(encoder); if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT || intel_dp->base.type == INTEL_OUTPUT_EDP) return intel_dp->output_reg; @@ -2516,19 +2520,19 @@ intel_dp_init(struct drm_device *dev, int output_reg) case DP_B: case PCH_DP_B: dev_priv->hotplug_supported_mask |= - DPB_HOTPLUG_INT_STATUS; + HDMIB_HOTPLUG_INT_STATUS; name = "DPDDC-B"; break; case DP_C: case PCH_DP_C: dev_priv->hotplug_supported_mask |= - DPC_HOTPLUG_INT_STATUS; + HDMIC_HOTPLUG_INT_STATUS; name = "DPDDC-C"; break; case DP_D: case PCH_DP_D: dev_priv->hotplug_supported_mask |= - DPD_HOTPLUG_INT_STATUS; + HDMID_HOTPLUG_INT_STATUS; name = "DPDDC-D"; break; } diff --git a/trunk/drivers/gpu/drm/i915/intel_drv.h b/trunk/drivers/gpu/drm/i915/intel_drv.h index b7859e7110a7..3e0918834e7e 100644 --- a/trunk/drivers/gpu/drm/i915/intel_drv.h +++ b/trunk/drivers/gpu/drm/i915/intel_drv.h @@ -169,7 +169,6 @@ struct intel_crtc { u8 lut_r[256], lut_g[256], lut_b[256]; int dpms_mode; bool active; /* is the crtc on? independent of the dpms mode */ - bool primary_disabled; /* is the crtc obscured by a plane? */ bool busy; /* is scanout buffer being updated frequently? */ struct timer_list idle_timer; bool lowfreq_avail; @@ -177,11 +176,6 @@ struct intel_crtc { struct intel_unpin_work *unpin_work; int fdi_lanes; - /* Display surface base address adjustement for pageflips. Note that on - * gen4+ this only adjusts up to a tile, offsets within a tile are - * handled in the hw itself (with the TILEOFF register). */ - unsigned long dspaddr_offset; - struct drm_i915_gem_object *cursor_bo; uint32_t cursor_addr; int16_t cursor_x, cursor_y; @@ -197,6 +191,7 @@ struct intel_plane { struct drm_plane base; enum pipe pipe; struct drm_i915_gem_object *obj; + bool primary_disabled; int max_downscale; u32 lut_r[1024], lut_g[1024], lut_b[1024]; void (*update_plane)(struct drm_plane *plane, @@ -306,8 +301,6 @@ struct intel_hdmi { enum hdmi_force_audio force_audio; void (*write_infoframe)(struct drm_encoder *encoder, struct dip_infoframe *frame); - void (*set_infoframes)(struct drm_encoder *encoder, - struct drm_display_mode *adjusted_mode); }; static inline struct drm_crtc * @@ -350,6 +343,9 @@ extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector) extern void intel_crt_init(struct drm_device *dev); extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder); +extern void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, + struct drm_display_mode *adjusted_mode); +extern void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder); extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if); extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob); @@ -364,8 +360,6 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); extern bool intel_dpd_is_edp(struct drm_device *dev); extern void intel_edp_link_config(struct intel_encoder *, int *, int *); -extern int intel_edp_target_clock(struct intel_encoder *, - struct drm_display_mode *mode); extern bool intel_encoder_is_pch_edp(struct drm_encoder *encoder); extern int intel_plane_init(struct drm_device *dev, enum pipe pipe); extern void intel_flush_display_plane(struct drm_i915_private *dev_priv, @@ -378,14 +372,13 @@ extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, struct drm_display_mode *adjusted_mode); extern void intel_pch_panel_fitting(struct drm_device *dev, int fitting_mode, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); extern u32 intel_panel_get_max_backlight(struct drm_device *dev); extern u32 intel_panel_get_backlight(struct drm_device *dev); extern void intel_panel_set_backlight(struct drm_device *dev, u32 level); extern int intel_panel_setup_backlight(struct drm_device *dev); -extern void intel_panel_enable_backlight(struct drm_device *dev, - enum pipe pipe); +extern void intel_panel_enable_backlight(struct drm_device *dev); extern void intel_panel_disable_backlight(struct drm_device *dev); extern void intel_panel_destroy_backlight(struct drm_device *dev); extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); @@ -430,6 +423,9 @@ extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, int regno); extern void intel_enable_clock_gating(struct drm_device *dev); +extern void ironlake_disable_rc6(struct drm_device *dev); +extern void ironlake_enable_drps(struct drm_device *dev); +extern void ironlake_disable_drps(struct drm_device *dev); extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_i915_gem_object *obj, @@ -496,10 +492,10 @@ extern void intel_update_fbc(struct drm_device *dev); extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv); extern void intel_gpu_ips_teardown(void); -extern void intel_enable_gt_powersave(struct drm_device *dev); -extern void intel_disable_gt_powersave(struct drm_device *dev); -extern void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv); -extern void ironlake_teardown_rc6(struct drm_device *dev); +extern void gen6_enable_rps(struct drm_i915_private *dev_priv); +extern void gen6_update_ring_freq(struct drm_i915_private *dev_priv); +extern void gen6_disable_rps(struct drm_device *dev); +extern void intel_init_emon(struct drm_device *dev); extern void intel_ddi_dpms(struct drm_encoder *encoder, int mode); extern void intel_ddi_mode_set(struct drm_encoder *encoder, diff --git a/trunk/drivers/gpu/drm/i915/intel_dvo.c b/trunk/drivers/gpu/drm/i915/intel_dvo.c index 36c542e5036b..60ba50b956f2 100644 --- a/trunk/drivers/gpu/drm/i915/intel_dvo.c +++ b/trunk/drivers/gpu/drm/i915/intel_dvo.c @@ -136,7 +136,7 @@ static int intel_dvo_mode_valid(struct drm_connector *connector, } static bool intel_dvo_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); diff --git a/trunk/drivers/gpu/drm/i915/intel_fb.c b/trunk/drivers/gpu/drm/i915/intel_fb.c index 97f673523b97..bf8690720a0c 100644 --- a/trunk/drivers/gpu/drm/i915/intel_fb.c +++ b/trunk/drivers/gpu/drm/i915/intel_fb.c @@ -65,7 +65,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev, struct drm_i915_private *dev_priv = dev->dev_private; struct fb_info *info; struct drm_framebuffer *fb; - struct drm_mode_fb_cmd2 mode_cmd = {}; + struct drm_mode_fb_cmd2 mode_cmd; struct drm_i915_gem_object *obj; struct device *device = &dev->pdev->dev; int size, ret; @@ -140,9 +140,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev, info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset; info->fix.smem_len = size; - info->screen_base = - ioremap_wc(dev_priv->mm.gtt_base_addr + obj->gtt_offset, - size); + info->screen_base = ioremap_wc(dev->agp->base + obj->gtt_offset, size); if (!info->screen_base) { ret = -ENOSPC; goto out_unpin; diff --git a/trunk/drivers/gpu/drm/i915/intel_hdmi.c b/trunk/drivers/gpu/drm/i915/intel_hdmi.c index 98f602427eb8..2ead3bf7c21d 100644 --- a/trunk/drivers/gpu/drm/i915/intel_hdmi.c +++ b/trunk/drivers/gpu/drm/i915/intel_hdmi.c @@ -37,19 +37,6 @@ #include "i915_drm.h" #include "i915_drv.h" -static void -assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi) -{ - struct drm_device *dev = intel_hdmi->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t enabled_bits; - - enabled_bits = IS_HASWELL(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE; - - WARN(I915_READ(intel_hdmi->sdvox_reg) & enabled_bits, - "HDMI port enabled, expecting disabled\n"); -} - struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) { return container_of(encoder, struct intel_hdmi, base.base); @@ -134,31 +121,36 @@ static void g4x_write_infoframe(struct drm_encoder *encoder, uint32_t *data = (uint32_t *)frame; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); u32 val = I915_READ(VIDEO_DIP_CTL); unsigned i, len = DIP_HEADER_SIZE + frame->len; - WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); + val &= ~VIDEO_DIP_PORT_MASK; + if (intel_hdmi->sdvox_reg == SDVOB) + val |= VIDEO_DIP_PORT_B; + else if (intel_hdmi->sdvox_reg == SDVOC) + val |= VIDEO_DIP_PORT_C; + else + return; val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ val |= g4x_infoframe_index(frame); val &= ~g4x_infoframe_enable(frame); + val |= VIDEO_DIP_ENABLE; I915_WRITE(VIDEO_DIP_CTL, val); - mmiowb(); for (i = 0; i < len; i += 4) { I915_WRITE(VIDEO_DIP_DATA, *data); data++; } - mmiowb(); val |= g4x_infoframe_enable(frame); val &= ~VIDEO_DIP_FREQ_MASK; val |= VIDEO_DIP_FREQ_VSYNC; I915_WRITE(VIDEO_DIP_CTL, val); - POSTING_READ(VIDEO_DIP_CTL); } static void ibx_write_infoframe(struct drm_encoder *encoder, @@ -168,32 +160,46 @@ static void ibx_write_infoframe(struct drm_encoder *encoder, struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); + struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); unsigned i, len = DIP_HEADER_SIZE + frame->len; u32 val = I915_READ(reg); - WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); + val &= ~VIDEO_DIP_PORT_MASK; + switch (intel_hdmi->sdvox_reg) { + case HDMIB: + val |= VIDEO_DIP_PORT_B; + break; + case HDMIC: + val |= VIDEO_DIP_PORT_C; + break; + case HDMID: + val |= VIDEO_DIP_PORT_D; + break; + default: + return; + } + + intel_wait_for_vblank(dev, intel_crtc->pipe); val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ val |= g4x_infoframe_index(frame); val &= ~g4x_infoframe_enable(frame); + val |= VIDEO_DIP_ENABLE; I915_WRITE(reg, val); - mmiowb(); for (i = 0; i < len; i += 4) { I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); data++; } - mmiowb(); val |= g4x_infoframe_enable(frame); val &= ~VIDEO_DIP_FREQ_MASK; val |= VIDEO_DIP_FREQ_VSYNC; I915_WRITE(reg, val); - POSTING_READ(reg); } static void cpt_write_infoframe(struct drm_encoder *encoder, @@ -207,31 +213,32 @@ static void cpt_write_infoframe(struct drm_encoder *encoder, unsigned i, len = DIP_HEADER_SIZE + frame->len; u32 val = I915_READ(reg); - WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); + intel_wait_for_vblank(dev, intel_crtc->pipe); val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ val |= g4x_infoframe_index(frame); /* The DIP control register spec says that we need to update the AVI * infoframe without clearing its enable bit */ - if (frame->type != DIP_TYPE_AVI) + if (frame->type == DIP_TYPE_AVI) + val |= VIDEO_DIP_ENABLE_AVI; + else val &= ~g4x_infoframe_enable(frame); + val |= VIDEO_DIP_ENABLE; + I915_WRITE(reg, val); - mmiowb(); for (i = 0; i < len; i += 4) { I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); data++; } - mmiowb(); val |= g4x_infoframe_enable(frame); val &= ~VIDEO_DIP_FREQ_MASK; val |= VIDEO_DIP_FREQ_VSYNC; I915_WRITE(reg, val); - POSTING_READ(reg); } static void vlv_write_infoframe(struct drm_encoder *encoder, @@ -245,28 +252,26 @@ static void vlv_write_infoframe(struct drm_encoder *encoder, unsigned i, len = DIP_HEADER_SIZE + frame->len; u32 val = I915_READ(reg); - WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); + intel_wait_for_vblank(dev, intel_crtc->pipe); val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ val |= g4x_infoframe_index(frame); val &= ~g4x_infoframe_enable(frame); + val |= VIDEO_DIP_ENABLE; I915_WRITE(reg, val); - mmiowb(); for (i = 0; i < len; i += 4) { I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data); data++; } - mmiowb(); val |= g4x_infoframe_enable(frame); val &= ~VIDEO_DIP_FREQ_MASK; val |= VIDEO_DIP_FREQ_VSYNC; I915_WRITE(reg, val); - POSTING_READ(reg); } static void hsw_write_infoframe(struct drm_encoder *encoder, @@ -284,19 +289,18 @@ static void hsw_write_infoframe(struct drm_encoder *encoder, if (data_reg == 0) return; + intel_wait_for_vblank(dev, intel_crtc->pipe); + val &= ~hsw_infoframe_enable(frame); I915_WRITE(ctl_reg, val); - mmiowb(); for (i = 0; i < len; i += 4) { I915_WRITE(data_reg + i, *data); data++; } - mmiowb(); val |= hsw_infoframe_enable(frame); I915_WRITE(ctl_reg, val); - POSTING_READ(ctl_reg); } static void intel_set_infoframe(struct drm_encoder *encoder, @@ -304,11 +308,14 @@ static void intel_set_infoframe(struct drm_encoder *encoder, { struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); + if (!intel_hdmi->has_hdmi_sink) + return; + intel_dip_infoframe_csum(frame); intel_hdmi->write_infoframe(encoder, frame); } -static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, +void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { struct dip_infoframe avi_if = { @@ -323,7 +330,7 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, intel_set_infoframe(encoder, &avi_if); } -static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) +void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) { struct dip_infoframe spd_if; @@ -338,223 +345,6 @@ static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) intel_set_infoframe(encoder, &spd_if); } -static void g4x_set_infoframes(struct drm_encoder *encoder, - struct drm_display_mode *adjusted_mode) -{ - struct drm_i915_private *dev_priv = encoder->dev->dev_private; - struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); - u32 reg = VIDEO_DIP_CTL; - u32 val = I915_READ(reg); - u32 port; - - assert_hdmi_port_disabled(intel_hdmi); - - /* If the registers were not initialized yet, they might be zeroes, - * which means we're selecting the AVI DIP and we're setting its - * frequency to once. This seems to really confuse the HW and make - * things stop working (the register spec says the AVI always needs to - * be sent every VSync). So here we avoid writing to the register more - * than we need and also explicitly select the AVI DIP and explicitly - * set its frequency to every VSync. Avoiding to write it twice seems to - * be enough to solve the problem, but being defensive shouldn't hurt us - * either. */ - val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; - - if (!intel_hdmi->has_hdmi_sink) { - if (!(val & VIDEO_DIP_ENABLE)) - return; - val &= ~VIDEO_DIP_ENABLE; - I915_WRITE(reg, val); - POSTING_READ(reg); - return; - } - - switch (intel_hdmi->sdvox_reg) { - case SDVOB: - port = VIDEO_DIP_PORT_B; - break; - case SDVOC: - port = VIDEO_DIP_PORT_C; - break; - default: - return; - } - - if (port != (val & VIDEO_DIP_PORT_MASK)) { - if (val & VIDEO_DIP_ENABLE) { - val &= ~VIDEO_DIP_ENABLE; - I915_WRITE(reg, val); - POSTING_READ(reg); - } - val &= ~VIDEO_DIP_PORT_MASK; - val |= port; - } - - val |= VIDEO_DIP_ENABLE; - val &= ~VIDEO_DIP_ENABLE_VENDOR; - - I915_WRITE(reg, val); - POSTING_READ(reg); - - intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); - intel_hdmi_set_spd_infoframe(encoder); -} - -static void ibx_set_infoframes(struct drm_encoder *encoder, - struct drm_display_mode *adjusted_mode) -{ - struct drm_i915_private *dev_priv = encoder->dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); - u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe); - u32 val = I915_READ(reg); - u32 port; - - assert_hdmi_port_disabled(intel_hdmi); - - /* See the big comment in g4x_set_infoframes() */ - val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; - - if (!intel_hdmi->has_hdmi_sink) { - if (!(val & VIDEO_DIP_ENABLE)) - return; - val &= ~VIDEO_DIP_ENABLE; - I915_WRITE(reg, val); - POSTING_READ(reg); - return; - } - - switch (intel_hdmi->sdvox_reg) { - case HDMIB: - port = VIDEO_DIP_PORT_B; - break; - case HDMIC: - port = VIDEO_DIP_PORT_C; - break; - case HDMID: - port = VIDEO_DIP_PORT_D; - break; - default: - return; - } - - if (port != (val & VIDEO_DIP_PORT_MASK)) { - if (val & VIDEO_DIP_ENABLE) { - val &= ~VIDEO_DIP_ENABLE; - I915_WRITE(reg, val); - POSTING_READ(reg); - } - val &= ~VIDEO_DIP_PORT_MASK; - val |= port; - } - - val |= VIDEO_DIP_ENABLE; - val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | - VIDEO_DIP_ENABLE_GCP); - - I915_WRITE(reg, val); - POSTING_READ(reg); - - intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); - intel_hdmi_set_spd_infoframe(encoder); -} - -static void cpt_set_infoframes(struct drm_encoder *encoder, - struct drm_display_mode *adjusted_mode) -{ - struct drm_i915_private *dev_priv = encoder->dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); - u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe); - u32 val = I915_READ(reg); - - assert_hdmi_port_disabled(intel_hdmi); - - /* See the big comment in g4x_set_infoframes() */ - val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; - - if (!intel_hdmi->has_hdmi_sink) { - if (!(val & VIDEO_DIP_ENABLE)) - return; - val &= ~(VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI); - I915_WRITE(reg, val); - POSTING_READ(reg); - return; - } - - /* Set both together, unset both together: see the spec. */ - val |= VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI; - val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | - VIDEO_DIP_ENABLE_GCP); - - I915_WRITE(reg, val); - POSTING_READ(reg); - - intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); - intel_hdmi_set_spd_infoframe(encoder); -} - -static void vlv_set_infoframes(struct drm_encoder *encoder, - struct drm_display_mode *adjusted_mode) -{ - struct drm_i915_private *dev_priv = encoder->dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); - u32 reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); - u32 val = I915_READ(reg); - - assert_hdmi_port_disabled(intel_hdmi); - - /* See the big comment in g4x_set_infoframes() */ - val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; - - if (!intel_hdmi->has_hdmi_sink) { - if (!(val & VIDEO_DIP_ENABLE)) - return; - val &= ~VIDEO_DIP_ENABLE; - I915_WRITE(reg, val); - POSTING_READ(reg); - return; - } - - val |= VIDEO_DIP_ENABLE; - val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | - VIDEO_DIP_ENABLE_GCP); - - I915_WRITE(reg, val); - POSTING_READ(reg); - - intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); - intel_hdmi_set_spd_infoframe(encoder); -} - -static void hsw_set_infoframes(struct drm_encoder *encoder, - struct drm_display_mode *adjusted_mode) -{ - struct drm_i915_private *dev_priv = encoder->dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); - u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->pipe); - u32 val = I915_READ(reg); - - assert_hdmi_port_disabled(intel_hdmi); - - if (!intel_hdmi->has_hdmi_sink) { - I915_WRITE(reg, 0); - POSTING_READ(reg); - return; - } - - val &= ~(VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_GCP_HSW | - VIDEO_DIP_ENABLE_VS_HSW | VIDEO_DIP_ENABLE_GMP_HSW); - - I915_WRITE(reg, val); - POSTING_READ(reg); - - intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); - intel_hdmi_set_spd_infoframe(encoder); -} - static void intel_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -565,7 +355,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); u32 sdvox; - sdvox = SDVO_ENCODING_HDMI; + sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE; if (!HAS_PCH_SPLIT(dev)) sdvox |= intel_hdmi->color_range; if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) @@ -592,13 +382,14 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, if (HAS_PCH_CPT(dev)) sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe); - else if (intel_crtc->pipe == PIPE_B) + else if (intel_crtc->pipe == 1) sdvox |= SDVO_PIPE_B_SELECT; I915_WRITE(intel_hdmi->sdvox_reg, sdvox); POSTING_READ(intel_hdmi->sdvox_reg); - intel_hdmi->set_infoframes(encoder, adjusted_mode); + intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); + intel_hdmi_set_spd_infoframe(encoder); } static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) @@ -614,36 +405,6 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) temp = I915_READ(intel_hdmi->sdvox_reg); - /* HW workaround for IBX, we need to move the port to transcoder A - * before disabling it. */ - if (HAS_PCH_IBX(dev)) { - struct drm_crtc *crtc = encoder->crtc; - int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1; - - if (mode != DRM_MODE_DPMS_ON) { - if (temp & SDVO_PIPE_B_SELECT) { - temp &= ~SDVO_PIPE_B_SELECT; - I915_WRITE(intel_hdmi->sdvox_reg, temp); - POSTING_READ(intel_hdmi->sdvox_reg); - - /* Again we need to write this twice. */ - I915_WRITE(intel_hdmi->sdvox_reg, temp); - POSTING_READ(intel_hdmi->sdvox_reg); - - /* Transcoder selection bits only update - * effectively on vblank. */ - if (crtc) - intel_wait_for_vblank(dev, pipe); - else - msleep(50); - } - } else { - /* Restore the transcoder select bit. */ - if (pipe == PIPE_B) - enable_bits |= SDVO_PIPE_B_SELECT; - } - } - /* HW workaround, need to toggle enable bit off and on for 12bpc, but * we do this anyway which shows more stable in testing. */ @@ -685,33 +446,12 @@ static int intel_hdmi_mode_valid(struct drm_connector *connector, } static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; } -static bool g4x_hdmi_connected(struct intel_hdmi *intel_hdmi) -{ - struct drm_device *dev = intel_hdmi->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t bit; - - switch (intel_hdmi->sdvox_reg) { - case SDVOB: - bit = HDMIB_HOTPLUG_LIVE_STATUS; - break; - case SDVOC: - bit = HDMIC_HOTPLUG_LIVE_STATUS; - break; - default: - bit = 0; - break; - } - - return I915_READ(PORT_HOTPLUG_STAT) & bit; -} - static enum drm_connector_status intel_hdmi_detect(struct drm_connector *connector, bool force) { @@ -720,9 +460,6 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) struct edid *edid; enum drm_connector_status status = connector_status_disconnected; - if (IS_G4X(connector->dev) && !g4x_hdmi_connected(intel_hdmi)) - return status; - intel_hdmi->has_hdmi_sink = false; intel_hdmi->has_audio = false; edid = drm_get_edid(connector, @@ -896,6 +633,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) struct intel_encoder *intel_encoder; struct intel_connector *intel_connector; struct intel_hdmi *intel_hdmi; + int i; intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL); if (!intel_hdmi) @@ -972,19 +710,26 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) if (!HAS_PCH_SPLIT(dev)) { intel_hdmi->write_infoframe = g4x_write_infoframe; - intel_hdmi->set_infoframes = g4x_set_infoframes; + I915_WRITE(VIDEO_DIP_CTL, 0); } else if (IS_VALLEYVIEW(dev)) { intel_hdmi->write_infoframe = vlv_write_infoframe; - intel_hdmi->set_infoframes = vlv_set_infoframes; + for_each_pipe(i) + I915_WRITE(VLV_TVIDEO_DIP_CTL(i), 0); } else if (IS_HASWELL(dev)) { + /* FIXME: Haswell has a new set of DIP frame registers, but we are + * just doing the minimal required for HDMI to work at this stage. + */ intel_hdmi->write_infoframe = hsw_write_infoframe; - intel_hdmi->set_infoframes = hsw_set_infoframes; + for_each_pipe(i) + I915_WRITE(HSW_TVIDEO_DIP_CTL(i), 0); } else if (HAS_PCH_IBX(dev)) { intel_hdmi->write_infoframe = ibx_write_infoframe; - intel_hdmi->set_infoframes = ibx_set_infoframes; + for_each_pipe(i) + I915_WRITE(TVIDEO_DIP_CTL(i), 0); } else { intel_hdmi->write_infoframe = cpt_write_infoframe; - intel_hdmi->set_infoframes = cpt_set_infoframes; + for_each_pipe(i) + I915_WRITE(TVIDEO_DIP_CTL(i), 0); } if (IS_HASWELL(dev)) diff --git a/trunk/drivers/gpu/drm/i915/intel_lvds.c b/trunk/drivers/gpu/drm/i915/intel_lvds.c index 49f09a8b05e9..08eb04c787e8 100644 --- a/trunk/drivers/gpu/drm/i915/intel_lvds.c +++ b/trunk/drivers/gpu/drm/i915/intel_lvds.c @@ -71,7 +71,6 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector) static void intel_lvds_enable(struct intel_lvds *intel_lvds) { struct drm_device *dev = intel_lvds->base.base.dev; - struct intel_crtc *intel_crtc = to_intel_crtc(intel_lvds->base.base.crtc); struct drm_i915_private *dev_priv = dev->dev_private; u32 ctl_reg, lvds_reg, stat_reg; @@ -108,7 +107,7 @@ static void intel_lvds_enable(struct intel_lvds *intel_lvds) if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000)) DRM_ERROR("timed out waiting for panel to power on\n"); - intel_panel_enable_backlight(dev, intel_crtc->pipe); + intel_panel_enable_backlight(dev); } static void intel_lvds_disable(struct intel_lvds *intel_lvds) @@ -229,14 +228,14 @@ static inline u32 panel_fitter_scaling(u32 source, u32 target) } static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct intel_lvds *intel_lvds = to_intel_lvds(encoder); - struct intel_encoder *tmp_encoder; + struct drm_encoder *tmp_encoder; u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; int pipe; @@ -247,8 +246,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, } /* Should never happen!! */ - for_each_encoder_on_crtc(dev, encoder->crtc, tmp_encoder) { - if (&tmp_encoder->base != encoder) { + list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, head) { + if (tmp_encoder != encoder && tmp_encoder->crtc == encoder->crtc) { DRM_ERROR("Can't enable LVDS and another " "encoder on the same pipe\n"); return false; @@ -778,14 +777,6 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_BOARD_NAME, "MS-7469"), }, }, - { - .callback = intel_no_lvds_dmi_callback, - .ident = "ZOTAC ZBOXSD-ID12/ID13", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ZOTAC"), - DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"), - }, - }, { } /* terminating entry */ }; @@ -976,8 +967,6 @@ bool intel_lvds_init(struct drm_device *dev) intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); if (HAS_PCH_SPLIT(dev)) intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); - else if (IS_GEN4(dev)) - intel_encoder->crtc_mask = (1 << 0) | (1 << 1); else intel_encoder->crtc_mask = (1 << 1); @@ -1085,14 +1074,35 @@ bool intel_lvds_init(struct drm_device *dev) goto failed; out: - /* - * Unlock registers and just - * leave them unlocked - */ if (HAS_PCH_SPLIT(dev)) { + u32 pwm; + + pipe = (I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT) ? 1 : 0; + + /* make sure PWM is enabled and locked to the LVDS pipe */ + pwm = I915_READ(BLC_PWM_CPU_CTL2); + if (pipe == 0 && (pwm & PWM_PIPE_B)) + I915_WRITE(BLC_PWM_CPU_CTL2, pwm & ~PWM_ENABLE); + if (pipe) + pwm |= PWM_PIPE_B; + else + pwm &= ~PWM_PIPE_B; + I915_WRITE(BLC_PWM_CPU_CTL2, pwm | PWM_ENABLE); + + pwm = I915_READ(BLC_PWM_PCH_CTL1); + pwm |= PWM_PCH_ENABLE; + I915_WRITE(BLC_PWM_PCH_CTL1, pwm); + /* + * Unlock registers and just + * leave them unlocked + */ I915_WRITE(PCH_PP_CONTROL, I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); } else { + /* + * Unlock registers and just + * leave them unlocked + */ I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); } diff --git a/trunk/drivers/gpu/drm/i915/intel_overlay.c b/trunk/drivers/gpu/drm/i915/intel_overlay.c index 830d0dd610e1..458743da3774 100644 --- a/trunk/drivers/gpu/drm/i915/intel_overlay.c +++ b/trunk/drivers/gpu/drm/i915/intel_overlay.c @@ -226,7 +226,7 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, } overlay->last_flip_req = request->seqno; overlay->flip_tail = tail; - ret = i915_wait_seqno(ring, overlay->last_flip_req); + ret = i915_wait_request(ring, overlay->last_flip_req); if (ret) return ret; i915_gem_retire_requests(dev); @@ -452,7 +452,7 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay) if (overlay->last_flip_req == 0) return 0; - ret = i915_wait_seqno(ring, overlay->last_flip_req); + ret = i915_wait_request(ring, overlay->last_flip_req); if (ret) return ret; i915_gem_retire_requests(dev); diff --git a/trunk/drivers/gpu/drm/i915/intel_panel.c b/trunk/drivers/gpu/drm/i915/intel_panel.c index 58c7ee7238b8..2a1625d84a69 100644 --- a/trunk/drivers/gpu/drm/i915/intel_panel.c +++ b/trunk/drivers/gpu/drm/i915/intel_panel.c @@ -56,7 +56,7 @@ intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, void intel_pch_panel_fitting(struct drm_device *dev, int fitting_mode, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -287,18 +287,9 @@ void intel_panel_disable_backlight(struct drm_device *dev) dev_priv->backlight_enabled = false; intel_panel_actually_set_backlight(dev, 0); - - if (INTEL_INFO(dev)->gen >= 4) { - uint32_t reg; - - reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; - - I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE); - } } -void intel_panel_enable_backlight(struct drm_device *dev, - enum pipe pipe) +void intel_panel_enable_backlight(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -307,33 +298,6 @@ void intel_panel_enable_backlight(struct drm_device *dev, dev_priv->backlight_enabled = true; intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); - - if (INTEL_INFO(dev)->gen >= 4) { - uint32_t reg, tmp; - - reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; - - - tmp = I915_READ(reg); - - /* Note that this can also get called through dpms changes. And - * we don't track the backlight dpms state, hence check whether - * we have to do anything first. */ - if (tmp & BLM_PWM_ENABLE) - return; - - if (dev_priv->num_pipe == 3) - tmp &= ~BLM_PIPE_SELECT_IVB; - else - tmp &= ~BLM_PIPE_SELECT; - - tmp |= BLM_PIPE(pipe); - tmp &= ~BLM_PWM_ENABLE; - - I915_WRITE(reg, tmp); - POSTING_READ(reg); - I915_WRITE(reg, tmp | BLM_PWM_ENABLE); - } } static void intel_panel_init_backlight(struct drm_device *dev) diff --git a/trunk/drivers/gpu/drm/i915/intel_pm.c b/trunk/drivers/gpu/drm/i915/intel_pm.c index 0bb69fd255a9..d0ce2a5b1d3f 100644 --- a/trunk/drivers/gpu/drm/i915/intel_pm.c +++ b/trunk/drivers/gpu/drm/i915/intel_pm.c @@ -387,6 +387,8 @@ void intel_update_fbc(struct drm_device *dev) struct drm_i915_gem_object *obj; int enable_fbc; + DRM_DEBUG_KMS("\n"); + if (!i915_powersave) return; @@ -403,9 +405,7 @@ void intel_update_fbc(struct drm_device *dev) * - going to an unsupported config (interlace, pixel multiply, etc.) */ list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { - if (tmp_crtc->enabled && - !to_intel_crtc(tmp_crtc)->primary_disabled && - tmp_crtc->fb) { + if (tmp_crtc->enabled && tmp_crtc->fb) { if (crtc) { DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; @@ -2182,7 +2182,7 @@ bool ironlake_set_drps(struct drm_device *dev, u8 val) return true; } -static void ironlake_enable_drps(struct drm_device *dev) +void ironlake_enable_drps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 rgvmodectl = I915_READ(MEMMODECTL); @@ -2246,7 +2246,7 @@ static void ironlake_enable_drps(struct drm_device *dev) getrawmonotonic(&dev_priv->last_time2); } -static void ironlake_disable_drps(struct drm_device *dev) +void ironlake_disable_drps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u16 rgvswctl = I915_READ16(MEMSWCTL); @@ -2299,11 +2299,10 @@ void gen6_set_rps(struct drm_device *dev, u8 val) dev_priv->cur_delay = val; } -static void gen6_disable_rps(struct drm_device *dev) +void gen6_disable_rps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - I915_WRITE(GEN6_RC_CONTROL, 0); I915_WRITE(GEN6_RPNSWREQ, 1 << 31); I915_WRITE(GEN6_PMINTRMSK, 0xffffffff); I915_WRITE(GEN6_PMIER, 0); @@ -2333,11 +2332,9 @@ int intel_enable_rc6(const struct drm_device *dev) if (INTEL_INFO(dev)->gen == 5) return 0; - /* On Haswell, only RC6 is available. So let's enable it by default to - * provide better testing and coverage since the beginning. - */ + /* Sorry Haswell, no RC6 for you for now. */ if (IS_HASWELL(dev)) - return INTEL_RC6_ENABLE; + return 0; /* * Disable rc6 on Sandybridge @@ -2350,9 +2347,8 @@ int intel_enable_rc6(const struct drm_device *dev) return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE); } -static void gen6_enable_rps(struct drm_device *dev) +void gen6_enable_rps(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = dev->dev_private; struct intel_ring_buffer *ring; u32 rp_state_cap; u32 gt_perf_status; @@ -2361,8 +2357,6 @@ static void gen6_enable_rps(struct drm_device *dev) int rc6_mode; int i; - WARN_ON(!mutex_is_locked(&dev->struct_mutex)); - /* Here begins a magic sequence of register writes to enable * auto-downclocking. * @@ -2370,6 +2364,7 @@ static void gen6_enable_rps(struct drm_device *dev) * userspace... */ I915_WRITE(GEN6_RC_STATE, 0); + mutex_lock(&dev_priv->dev->struct_mutex); /* Clear the DBG now so we don't confuse earlier errors */ if ((gtfifodbg = I915_READ(GTFIFODBG))) { @@ -2405,24 +2400,20 @@ static void gen6_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC6p_THRESHOLD, 100000); I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ - /* Check if we are enabling RC6 */ rc6_mode = intel_enable_rc6(dev_priv->dev); if (rc6_mode & INTEL_RC6_ENABLE) rc6_mask |= GEN6_RC_CTL_RC6_ENABLE; - /* We don't use those on Haswell */ - if (!IS_HASWELL(dev)) { - if (rc6_mode & INTEL_RC6p_ENABLE) - rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE; + if (rc6_mode & INTEL_RC6p_ENABLE) + rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE; - if (rc6_mode & INTEL_RC6pp_ENABLE) - rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; - } + if (rc6_mode & INTEL_RC6pp_ENABLE) + rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", - (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", - (rc6_mask & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", - (rc6_mask & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); + (rc6_mode & INTEL_RC6_ENABLE) ? "on" : "off", + (rc6_mode & INTEL_RC6p_ENABLE) ? "on" : "off", + (rc6_mode & INTEL_RC6pp_ENABLE) ? "on" : "off"); I915_WRITE(GEN6_RC_CONTROL, rc6_mask | @@ -2440,19 +2431,10 @@ static void gen6_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, dev_priv->max_delay << 24 | dev_priv->min_delay << 16); - - if (IS_HASWELL(dev)) { - I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); - I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); - I915_WRITE(GEN6_RP_UP_EI, 66000); - I915_WRITE(GEN6_RP_DOWN_EI, 350000); - } else { - I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000); - I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000); - I915_WRITE(GEN6_RP_UP_EI, 100000); - I915_WRITE(GEN6_RP_DOWN_EI, 5000000); - } - + I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000); + I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000); + I915_WRITE(GEN6_RP_UP_EI, 100000); + I915_WRITE(GEN6_RP_DOWN_EI, 5000000); I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); I915_WRITE(GEN6_RP_CONTROL, GEN6_RP_MEDIA_TURBO | @@ -2460,7 +2442,7 @@ static void gen6_enable_rps(struct drm_device *dev) GEN6_RP_MEDIA_IS_GFX | GEN6_RP_ENABLE | GEN6_RP_UP_BUSY_AVG | - (IS_HASWELL(dev) ? GEN7_RP_DOWN_IDLE_AVG : GEN6_RP_DOWN_IDLE_CONT)); + GEN6_RP_DOWN_IDLE_CONT); if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, 500)) @@ -2507,17 +2489,15 @@ static void gen6_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_PMINTRMSK, 0); gen6_gt_force_wake_put(dev_priv); + mutex_unlock(&dev_priv->dev->struct_mutex); } -static void gen6_update_ring_freq(struct drm_device *dev) +void gen6_update_ring_freq(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = dev->dev_private; int min_freq = 15; int gpu_freq, ia_freq, max_ia_freq; int scaling_factor = 180; - WARN_ON(!mutex_is_locked(&dev->struct_mutex)); - max_ia_freq = cpufreq_quick_get_max(0); /* * Default to measured freq if none found, PCU will ensure we don't go @@ -2529,6 +2509,8 @@ static void gen6_update_ring_freq(struct drm_device *dev) /* Convert from kHz to MHz */ max_ia_freq /= 1000; + mutex_lock(&dev_priv->dev->struct_mutex); + /* * For each potential GPU frequency, load a ring frequency we'd like * to use for memory access. We do this by specifying the IA frequency @@ -2559,9 +2541,11 @@ static void gen6_update_ring_freq(struct drm_device *dev) continue; } } + + mutex_unlock(&dev_priv->dev->struct_mutex); } -void ironlake_teardown_rc6(struct drm_device *dev) +static void ironlake_teardown_rc6(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -2578,7 +2562,7 @@ void ironlake_teardown_rc6(struct drm_device *dev) } } -static void ironlake_disable_rc6(struct drm_device *dev) +void ironlake_disable_rc6(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -2594,6 +2578,8 @@ static void ironlake_disable_rc6(struct drm_device *dev) I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); POSTING_READ(RSTDBYCTL); } + + ironlake_teardown_rc6(dev); } static int ironlake_setup_rc6(struct drm_device *dev) @@ -2615,7 +2601,7 @@ static int ironlake_setup_rc6(struct drm_device *dev) return 0; } -static void ironlake_enable_rc6(struct drm_device *dev) +void ironlake_enable_rc6(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; @@ -2627,11 +2613,12 @@ static void ironlake_enable_rc6(struct drm_device *dev) if (!intel_enable_rc6(dev)) return; - WARN_ON(!mutex_is_locked(&dev->struct_mutex)); - + mutex_lock(&dev->struct_mutex); ret = ironlake_setup_rc6(dev); - if (ret) + if (ret) { + mutex_unlock(&dev->struct_mutex); return; + } /* * GPU can automatically power down the render unit if given a page @@ -2640,6 +2627,7 @@ static void ironlake_enable_rc6(struct drm_device *dev) ret = intel_ring_begin(ring, 6); if (ret) { ironlake_teardown_rc6(dev); + mutex_unlock(&dev->struct_mutex); return; } @@ -2664,11 +2652,13 @@ static void ironlake_enable_rc6(struct drm_device *dev) if (ret) { DRM_ERROR("failed to enable ironlake power power savings\n"); ironlake_teardown_rc6(dev); + mutex_unlock(&dev->struct_mutex); return; } I915_WRITE(PWRCTXA, dev_priv->pwrctx->gtt_offset | PWRCTX_EN); I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); + mutex_unlock(&dev->struct_mutex); } static unsigned long intel_pxfreq(u32 vidfreq) @@ -3164,7 +3154,8 @@ void intel_gpu_ips_teardown(void) i915_mch_dev = NULL; spin_unlock(&mchdev_lock); } -static void intel_init_emon(struct drm_device *dev) + +void intel_init_emon(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 lcfuse; @@ -3235,28 +3226,6 @@ static void intel_init_emon(struct drm_device *dev) dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK); } -void intel_disable_gt_powersave(struct drm_device *dev) -{ - if (IS_IRONLAKE_M(dev)) { - ironlake_disable_drps(dev); - ironlake_disable_rc6(dev); - } else if (INTEL_INFO(dev)->gen >= 6 && !IS_VALLEYVIEW(dev)) { - gen6_disable_rps(dev); - } -} - -void intel_enable_gt_powersave(struct drm_device *dev) -{ - if (IS_IRONLAKE_M(dev)) { - ironlake_enable_drps(dev); - ironlake_enable_rc6(dev); - intel_init_emon(dev); - } else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) { - gen6_enable_rps(dev); - gen6_update_ring_freq(dev); - } -} - static void ironlake_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -3359,12 +3328,8 @@ static void gen6_init_clock_gating(struct drm_device *dev) * * According to the spec, bit 11 (RCCUNIT) must also be set, * but we didn't debug actual testcases to find it out. - * - * Also apply WaDisableVDSUnitClockGating and - * WaDisableRCPBUnitClockGating. */ I915_WRITE(GEN6_UCGCTL2, - GEN7_VDSUNIT_CLOCK_GATE_DISABLE | GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); @@ -3392,9 +3357,6 @@ static void gen6_init_clock_gating(struct drm_device *dev) ILK_DPARB_CLK_GATE | ILK_DPFD_CLK_GATE); - I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | - GEN6_MBCTL_ENABLE_BOOT_FETCH); - for_each_pipe(pipe) { I915_WRITE(DSPCNTR(pipe), I915_READ(DSPCNTR(pipe)) | @@ -3415,7 +3377,7 @@ static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv) I915_WRITE(GEN7_FF_THREAD_MODE, reg); } -static void haswell_init_clock_gating(struct drm_device *dev) +static void ivybridge_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int pipe; @@ -3465,24 +3427,13 @@ static void haswell_init_clock_gating(struct drm_device *dev) /* WaDisable4x2SubspanOptimization */ I915_WRITE(CACHE_MODE_1, _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); - - /* XXX: This is a workaround for early silicon revisions and should be - * removed later. - */ - I915_WRITE(WM_DBG, - I915_READ(WM_DBG) | - WM_DBG_DISALLOW_MULTIPLE_LP | - WM_DBG_DISALLOW_SPRITE | - WM_DBG_DISALLOW_MAXFIFO); - } -static void ivybridge_init_clock_gating(struct drm_device *dev) +static void valleyview_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int pipe; uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE; - uint32_t snpcr; I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); @@ -3490,77 +3441,10 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) I915_WRITE(WM2_LP_ILK, 0); I915_WRITE(WM1_LP_ILK, 0); - I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE); - - I915_WRITE(IVB_CHICKEN3, - CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE | - CHICKEN3_DGMG_DONE_FIX_DISABLE); - - /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */ - I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1, - GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC); - - /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */ - I915_WRITE(GEN7_L3CNTLREG1, - GEN7_WA_FOR_GEN7_L3_CONTROL); - I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, - GEN7_WA_L3_CHICKEN_MODE); - - /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock - * gating disable must be set. Failure to set it results in - * flickering pixels due to Z write ordering failures after - * some amount of runtime in the Mesa "fire" demo, and Unigine - * Sanctuary and Tropics, and apparently anything else with - * alpha test or pixel discard. - * - * According to the spec, bit 11 (RCCUNIT) must also be set, - * but we didn't debug actual testcases to find it out. - * - * According to the spec, bit 13 (RCZUNIT) must be set on IVB. + /* According to the spec, bit 13 (RCZUNIT) must be set on IVB. * This implements the WaDisableRCZUnitClockGating workaround. */ - I915_WRITE(GEN6_UCGCTL2, - GEN6_RCZUNIT_CLOCK_GATE_DISABLE | - GEN6_RCCUNIT_CLOCK_GATE_DISABLE); - - /* This is required by WaCatErrorRejectionIssue */ - I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, - I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | - GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); - - for_each_pipe(pipe) { - I915_WRITE(DSPCNTR(pipe), - I915_READ(DSPCNTR(pipe)) | - DISPPLANE_TRICKLE_FEED_DISABLE); - intel_flush_display_plane(dev_priv, pipe); - } - - I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | - GEN6_MBCTL_ENABLE_BOOT_FETCH); - - gen7_setup_fixed_func_scheduler(dev_priv); - - /* WaDisable4x2SubspanOptimization */ - I915_WRITE(CACHE_MODE_1, - _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); - - snpcr = I915_READ(GEN6_MBCUNIT_SNPCR); - snpcr &= ~GEN6_MBC_SNPCR_MASK; - snpcr |= GEN6_MBC_SNPCR_MED; - I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr); -} - -static void valleyview_init_clock_gating(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - int pipe; - uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE; - - I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); - - I915_WRITE(WM3_LP_ILK, 0); - I915_WRITE(WM2_LP_ILK, 0); - I915_WRITE(WM1_LP_ILK, 0); + I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE); I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE); @@ -3581,35 +3465,6 @@ static void valleyview_init_clock_gating(struct drm_device *dev) I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); - I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | - GEN6_MBCTL_ENABLE_BOOT_FETCH); - - - /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock - * gating disable must be set. Failure to set it results in - * flickering pixels due to Z write ordering failures after - * some amount of runtime in the Mesa "fire" demo, and Unigine - * Sanctuary and Tropics, and apparently anything else with - * alpha test or pixel discard. - * - * According to the spec, bit 11 (RCCUNIT) must also be set, - * but we didn't debug actual testcases to find it out. - * - * According to the spec, bit 13 (RCZUNIT) must be set on IVB. - * This implements the WaDisableRCZUnitClockGating workaround. - * - * Also apply WaDisableVDSUnitClockGating and - * WaDisableRCPBUnitClockGating. - */ - I915_WRITE(GEN6_UCGCTL2, - GEN7_VDSUNIT_CLOCK_GATE_DISABLE | - GEN7_TDLUNIT_CLOCK_GATE_DISABLE | - GEN6_RCZUNIT_CLOCK_GATE_DISABLE | - GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | - GEN6_RCCUNIT_CLOCK_GATE_DISABLE); - - I915_WRITE(GEN7_UCGCTL4, GEN7_L3BANK2X_CLOCK_GATE_DISABLE); - for_each_pipe(pipe) { I915_WRITE(DSPCNTR(pipe), I915_READ(DSPCNTR(pipe)) | @@ -3619,19 +3474,6 @@ static void valleyview_init_clock_gating(struct drm_device *dev) I915_WRITE(CACHE_MODE_1, _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); - - /* - * On ValleyView, the GUnit needs to signal the GT - * when flip and other events complete. So enable - * all the GUnit->GT interrupts here - */ - I915_WRITE(VLV_DPFLIPSTAT, PIPEB_LINE_COMPARE_INT_EN | - PIPEB_HLINE_INT_EN | PIPEB_VBLANK_INT_EN | - SPRITED_FLIPDONE_INT_EN | SPRITEC_FLIPDONE_INT_EN | - PLANEB_FLIPDONE_INT_EN | PIPEA_LINE_COMPARE_INT_EN | - PIPEA_HLINE_INT_EN | PIPEA_VBLANK_INT_EN | - SPRITEB_FLIPDONE_INT_EN | SPRITEA_FLIPDONE_INT_EN | - PLANEA_FLIPDONE_INT_EN); } static void g4x_init_clock_gating(struct drm_device *dev) @@ -3839,6 +3681,34 @@ void intel_init_pm(struct drm_device *dev) /* For FIFO watermark updates */ if (HAS_PCH_SPLIT(dev)) { + dev_priv->display.force_wake_get = __gen6_gt_force_wake_get; + dev_priv->display.force_wake_put = __gen6_gt_force_wake_put; + + /* IVB configs may use multi-threaded forcewake */ + if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { + u32 ecobus; + + /* A small trick here - if the bios hasn't configured MT forcewake, + * and if the device is in RC6, then force_wake_mt_get will not wake + * the device and the ECOBUS read will return zero. Which will be + * (correctly) interpreted by the test below as MT forcewake being + * disabled. + */ + mutex_lock(&dev->struct_mutex); + __gen6_gt_force_wake_mt_get(dev_priv); + ecobus = I915_READ_NOTRACE(ECOBUS); + __gen6_gt_force_wake_mt_put(dev_priv); + mutex_unlock(&dev->struct_mutex); + + if (ecobus & FORCEWAKE_MT_ENABLE) { + DRM_DEBUG_KMS("Using MT version of forcewake\n"); + dev_priv->display.force_wake_get = + __gen6_gt_force_wake_mt_get; + dev_priv->display.force_wake_put = + __gen6_gt_force_wake_mt_put; + } + } + if (HAS_PCH_IBX(dev)) dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating; else if (HAS_PCH_CPT(dev)) @@ -3886,7 +3756,7 @@ void intel_init_pm(struct drm_device *dev) "Disable CxSR\n"); dev_priv->display.update_wm = NULL; } - dev_priv->display.init_clock_gating = haswell_init_clock_gating; + dev_priv->display.init_clock_gating = ivybridge_init_clock_gating; dev_priv->display.sanitize_pm = gen6_sanitize_pm; } else dev_priv->display.update_wm = NULL; @@ -3894,6 +3764,8 @@ void intel_init_pm(struct drm_device *dev) dev_priv->display.update_wm = valleyview_update_wm; dev_priv->display.init_clock_gating = valleyview_init_clock_gating; + dev_priv->display.force_wake_get = vlv_force_wake_get; + dev_priv->display.force_wake_put = vlv_force_wake_put; } else if (IS_PINEVIEW(dev)) { if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3, @@ -3946,194 +3818,3 @@ void intel_init_pm(struct drm_device *dev) intel_init_power_wells(dev); } -static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv) -{ - u32 gt_thread_status_mask; - - if (IS_HASWELL(dev_priv->dev)) - gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK_HSW; - else - gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK; - - /* w/a for a sporadic read returning 0 by waiting for the GT - * thread to wake up. - */ - if (wait_for_atomic_us((I915_READ_NOTRACE(GEN6_GT_THREAD_STATUS_REG) & gt_thread_status_mask) == 0, 500)) - DRM_ERROR("GT thread status wait timed out\n"); -} - -static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) -{ - u32 forcewake_ack; - - if (IS_HASWELL(dev_priv->dev)) - forcewake_ack = FORCEWAKE_ACK_HSW; - else - forcewake_ack = FORCEWAKE_ACK; - - if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, 500)) - DRM_ERROR("Force wake wait timed out\n"); - - I915_WRITE_NOTRACE(FORCEWAKE, 1); - - if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500)) - DRM_ERROR("Force wake wait timed out\n"); - - __gen6_gt_wait_for_thread_c0(dev_priv); -} - -static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) -{ - u32 forcewake_ack; - - if (IS_HASWELL(dev_priv->dev)) - forcewake_ack = FORCEWAKE_ACK_HSW; - else - forcewake_ack = FORCEWAKE_MT_ACK; - - if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, 500)) - DRM_ERROR("Force wake wait timed out\n"); - - I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1)); - - if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500)) - DRM_ERROR("Force wake wait timed out\n"); - - __gen6_gt_wait_for_thread_c0(dev_priv); -} - -/* - * Generally this is called implicitly by the register read function. However, - * if some sequence requires the GT to not power down then this function should - * be called at the beginning of the sequence followed by a call to - * gen6_gt_force_wake_put() at the end of the sequence. - */ -void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) -{ - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->gt_lock, irqflags); - if (dev_priv->forcewake_count++ == 0) - dev_priv->gt.force_wake_get(dev_priv); - spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); -} - -void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) -{ - u32 gtfifodbg; - gtfifodbg = I915_READ_NOTRACE(GTFIFODBG); - if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK, - "MMIO read or write has been dropped %x\n", gtfifodbg)) - I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK); -} - -static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) -{ - I915_WRITE_NOTRACE(FORCEWAKE, 0); - /* The below doubles as a POSTING_READ */ - gen6_gt_check_fifodbg(dev_priv); -} - -static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) -{ - I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1)); - /* The below doubles as a POSTING_READ */ - gen6_gt_check_fifodbg(dev_priv); -} - -/* - * see gen6_gt_force_wake_get() - */ -void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) -{ - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->gt_lock, irqflags); - if (--dev_priv->forcewake_count == 0) - dev_priv->gt.force_wake_put(dev_priv); - spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); -} - -int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) -{ - int ret = 0; - - if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) { - int loop = 500; - u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); - while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) { - udelay(10); - fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); - } - if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES)) - ++ret; - dev_priv->gt_fifo_count = fifo; - } - dev_priv->gt_fifo_count--; - - return ret; -} - -static void vlv_force_wake_get(struct drm_i915_private *dev_priv) -{ - /* Already awake? */ - if ((I915_READ(0x130094) & 0xa1) == 0xa1) - return; - - I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffffffff); - POSTING_READ(FORCEWAKE_VLV); - - if (wait_for_atomic_us((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1), 500)) - DRM_ERROR("Force wake wait timed out\n"); - - __gen6_gt_wait_for_thread_c0(dev_priv); -} - -static void vlv_force_wake_put(struct drm_i915_private *dev_priv) -{ - I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffff0000); - /* FIXME: confirm VLV behavior with Punit folks */ - POSTING_READ(FORCEWAKE_VLV); -} - -void intel_gt_init(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - spin_lock_init(&dev_priv->gt_lock); - - if (IS_VALLEYVIEW(dev)) { - dev_priv->gt.force_wake_get = vlv_force_wake_get; - dev_priv->gt.force_wake_put = vlv_force_wake_put; - } else if (INTEL_INFO(dev)->gen >= 6) { - dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get; - dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put; - - /* IVB configs may use multi-threaded forcewake */ - if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { - u32 ecobus; - - /* A small trick here - if the bios hasn't configured - * MT forcewake, and if the device is in RC6, then - * force_wake_mt_get will not wake the device and the - * ECOBUS read will return zero. Which will be - * (correctly) interpreted by the test below as MT - * forcewake being disabled. - */ - mutex_lock(&dev->struct_mutex); - __gen6_gt_force_wake_mt_get(dev_priv); - ecobus = I915_READ_NOTRACE(ECOBUS); - __gen6_gt_force_wake_mt_put(dev_priv); - mutex_unlock(&dev->struct_mutex); - - if (ecobus & FORCEWAKE_MT_ENABLE) { - DRM_DEBUG_KMS("Using MT version of forcewake\n"); - dev_priv->gt.force_wake_get = - __gen6_gt_force_wake_mt_get; - dev_priv->gt.force_wake_put = - __gen6_gt_force_wake_mt_put; - } - } - } -} - diff --git a/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c b/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c index d42d821c64d6..e5b84ff89ca5 100644 --- a/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -219,28 +219,19 @@ gen6_render_ring_flush(struct intel_ring_buffer *ring, int ret; /* Force SNB workarounds for PIPE_CONTROL flushes */ - ret = intel_emit_post_sync_nonzero_flush(ring); - if (ret) - return ret; + intel_emit_post_sync_nonzero_flush(ring); /* Just flush everything. Experiments have shown that reducing the * number of bits based on the write domains has little performance * impact. */ flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; - flags |= PIPE_CONTROL_TLB_INVALIDATE; flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; - /* - * Ensure that any following seqno writes only happen when the render - * cache is indeed flushed (but only if the caller actually wants that). - */ - if (flush_domains) - flags |= PIPE_CONTROL_CS_STALL; ret = intel_ring_begin(ring, 6); if (ret) @@ -442,21 +433,11 @@ static int init_render_ring(struct intel_ring_buffer *ring) */ I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); - - /* This is not explicitly set for GEN6, so read the register. - * see intel_ring_mi_set_context() for why we care. - * TODO: consider explicitly setting the bit for GEN5 - */ - ring->itlb_before_ctx_switch = - !!(I915_READ(GFX_MODE) & GFX_TLB_INVALIDATE_ALWAYS); } if (INTEL_INFO(dev)->gen >= 6) I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); - if (IS_IVYBRIDGE(dev)) - I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR); - return ret; } @@ -844,11 +825,7 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring) spin_lock_irqsave(&dev_priv->irq_lock, flags); if (ring->irq_refcount++ == 0) { - if (IS_IVYBRIDGE(dev) && ring->id == RCS) - I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | - GEN6_RENDER_L3_PARITY_ERROR)); - else - I915_WRITE_IMR(ring, ~ring->irq_enable_mask); + I915_WRITE_IMR(ring, ~ring->irq_enable_mask); dev_priv->gt_irq_mask &= ~ring->irq_enable_mask; I915_WRITE(GTIMR, dev_priv->gt_irq_mask); POSTING_READ(GTIMR); @@ -867,10 +844,7 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring) spin_lock_irqsave(&dev_priv->irq_lock, flags); if (--ring->irq_refcount == 0) { - if (IS_IVYBRIDGE(dev) && ring->id == RCS) - I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR); - else - I915_WRITE_IMR(ring, ~0); + I915_WRITE_IMR(ring, ~0); dev_priv->gt_irq_mask |= ring->irq_enable_mask; I915_WRITE(GTIMR, dev_priv->gt_irq_mask); POSTING_READ(GTIMR); @@ -995,7 +969,6 @@ static int intel_init_ring_buffer(struct drm_device *dev, struct intel_ring_buffer *ring) { struct drm_i915_gem_object *obj; - struct drm_i915_private *dev_priv = dev->dev_private; int ret; ring->dev = dev; @@ -1029,9 +1002,8 @@ static int intel_init_ring_buffer(struct drm_device *dev, if (ret) goto err_unpin; - ring->virtual_start = - ioremap_wc(dev_priv->mm.gtt->gma_bus_addr + obj->gtt_offset, - ring->size); + ring->virtual_start = ioremap_wc(dev->agp->base + obj->gtt_offset, + ring->size); if (ring->virtual_start == NULL) { DRM_ERROR("Failed to map ringbuffer.\n"); ret = -EINVAL; @@ -1117,9 +1089,20 @@ static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring) static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno) { + struct drm_i915_private *dev_priv = ring->dev->dev_private; + bool was_interruptible; int ret; - ret = i915_wait_seqno(ring, seqno); + /* XXX As we have not yet audited all the paths to check that + * they are ready for ERESTARTSYS from intel_ring_begin, do not + * allow us to be interruptible by a signal. + */ + was_interruptible = dev_priv->mm.interruptible; + dev_priv->mm.interruptible = false; + + ret = i915_wait_request(ring, seqno); + + dev_priv->mm.interruptible = was_interruptible; if (!ret) i915_gem_retire_requests_ring(ring); @@ -1217,10 +1200,8 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n) } msleep(1); - - ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); - if (ret) - return ret; + if (atomic_read(&dev_priv->mm.wedged)) + return -EAGAIN; } while (!time_after(jiffies, end)); trace_i915_ring_wait_end(ring); return -EBUSY; @@ -1229,13 +1210,12 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n) int intel_ring_begin(struct intel_ring_buffer *ring, int num_dwords) { - drm_i915_private_t *dev_priv = ring->dev->dev_private; + struct drm_i915_private *dev_priv = ring->dev->dev_private; int n = 4*num_dwords; int ret; - ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); - if (ret) - return ret; + if (unlikely(atomic_read(&dev_priv->mm.wedged))) + return -EIO; if (unlikely(ring->tail + n > ring->effective_size)) { ret = intel_wrap_ring_buffer(ring); diff --git a/trunk/drivers/gpu/drm/i915/intel_ringbuffer.h b/trunk/drivers/gpu/drm/i915/intel_ringbuffer.h index 1d3c81fdad92..55d3da26bae7 100644 --- a/trunk/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/trunk/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -113,17 +113,9 @@ struct intel_ring_buffer { * Do we have some not yet emitted requests outstanding? */ u32 outstanding_lazy_request; - bool gpu_caches_dirty; wait_queue_head_t irq_queue; - /** - * Do an explicit TLB flush before MI_SET_CONTEXT - */ - bool itlb_before_ctx_switch; - struct i915_hw_context *default_context; - struct drm_i915_gem_object *last_context_obj; - void *private; }; diff --git a/trunk/drivers/gpu/drm/i915/intel_sdvo.c b/trunk/drivers/gpu/drm/i915/intel_sdvo.c index 26a6a4d0d078..b6a9d45fc3c6 100644 --- a/trunk/drivers/gpu/drm/i915/intel_sdvo.c +++ b/trunk/drivers/gpu/drm/i915/intel_sdvo.c @@ -140,6 +140,9 @@ struct intel_sdvo { /* DDC bus used by this SDVO encoder */ uint8_t ddc_bus; + + /* Input timings for adjusted_mode */ + struct intel_sdvo_dtd input_dtd; }; struct intel_sdvo_connector { @@ -935,7 +938,7 @@ static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) static bool intel_sdvo_set_output_timings_from_mode(struct intel_sdvo *intel_sdvo, - const struct drm_display_mode *mode) + struct drm_display_mode *mode) { struct intel_sdvo_dtd output_dtd; @@ -950,15 +953,11 @@ intel_sdvo_set_output_timings_from_mode(struct intel_sdvo *intel_sdvo, return true; } -/* Asks the sdvo controller for the preferred input mode given the output mode. - * Unfortunately we have to set up the full output mode to do that. */ static bool -intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +intel_sdvo_set_input_timings_for_mode(struct intel_sdvo *intel_sdvo, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { - struct intel_sdvo_dtd input_dtd; - /* Reset the input timing to the screen. Assume always input 0. */ if (!intel_sdvo_set_target_input(intel_sdvo)) return false; @@ -970,16 +969,16 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, return false; if (!intel_sdvo_get_preferred_input_timing(intel_sdvo, - &input_dtd)) + &intel_sdvo->input_dtd)) return false; - intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); + intel_sdvo_get_mode_from_dtd(adjusted_mode, &intel_sdvo->input_dtd); return true; } static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder); @@ -994,17 +993,17 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode)) return false; - (void) intel_sdvo_get_preferred_input_mode(intel_sdvo, - mode, - adjusted_mode); + (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo, + mode, + adjusted_mode); } else if (intel_sdvo->is_lvds) { if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, intel_sdvo->sdvo_lvds_fixed_mode)) return false; - (void) intel_sdvo_get_preferred_input_mode(intel_sdvo, - mode, - adjusted_mode); + (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo, + mode, + adjusted_mode); } /* Make the CRTC code factor in the SDVO pixel multiplier. The @@ -1058,9 +1057,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, intel_sdvo->sdvo_lvds_fixed_mode); else intel_sdvo_get_dtd_from_mode(&output_dtd, mode); - if (!intel_sdvo_set_output_timing(intel_sdvo, &output_dtd)) - DRM_INFO("Setting output timings on %s failed\n", - SDVO_NAME(intel_sdvo)); + (void) intel_sdvo_set_output_timing(intel_sdvo, &output_dtd); /* Set the input timing to the screen. Assume always input 0. */ if (!intel_sdvo_set_target_input(intel_sdvo)) @@ -1082,9 +1079,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, * adjusted_mode. */ intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); - if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd)) - DRM_INFO("Setting input timings on %s failed\n", - SDVO_NAME(intel_sdvo)); + (void) intel_sdvo_set_input_timing(intel_sdvo, &input_dtd); switch (pixel_multiplier) { default: @@ -1381,7 +1376,7 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) /* add 30ms delay when the output type might be TV */ if (intel_sdvo->caps.output_flags & SDVO_TV_MASK) - msleep(30); + mdelay(30); if (!intel_sdvo_read_response(intel_sdvo, &response, 2)) return connector_status_unknown; @@ -2526,7 +2521,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *intel_encoder; struct intel_sdvo *intel_sdvo; - u32 hotplug_mask; int i; intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL); @@ -2558,18 +2552,10 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) } } - hotplug_mask = 0; - if (IS_G4X(dev)) { - hotplug_mask = intel_sdvo->is_sdvob ? - SDVOB_HOTPLUG_INT_STATUS_G4X : SDVOC_HOTPLUG_INT_STATUS_G4X; - } else if (IS_GEN4(dev)) { - hotplug_mask = intel_sdvo->is_sdvob ? - SDVOB_HOTPLUG_INT_STATUS_I965 : SDVOC_HOTPLUG_INT_STATUS_I965; - } else { - hotplug_mask = intel_sdvo->is_sdvob ? - SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915; - } - dev_priv->hotplug_supported_mask |= hotplug_mask; + if (intel_sdvo->is_sdvob) + dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS; + else + dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS; drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs); diff --git a/trunk/drivers/gpu/drm/i915/intel_sprite.c b/trunk/drivers/gpu/drm/i915/intel_sprite.c index 1a1483b924d0..2a20fb0781d7 100644 --- a/trunk/drivers/gpu/drm/i915/intel_sprite.c +++ b/trunk/drivers/gpu/drm/i915/intel_sprite.c @@ -56,7 +56,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, sprctl &= ~SPRITE_PIXFORMAT_MASK; sprctl &= ~SPRITE_RGB_ORDER_RGBX; sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK; - sprctl &= ~SPRITE_TILED; switch (fb->pixel_format) { case DRM_FORMAT_XBGR8888: @@ -85,7 +84,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, break; default: DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n"); - sprctl |= SPRITE_FORMAT_RGBX888; + sprctl |= DVS_FORMAT_RGBX888; pixel_size = 4; break; } @@ -327,12 +326,6 @@ intel_enable_primary(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int reg = DSPCNTR(intel_crtc->plane); - if (!intel_crtc->primary_disabled) - return; - - intel_crtc->primary_disabled = false; - intel_update_fbc(dev); - I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); } @@ -344,13 +337,7 @@ intel_disable_primary(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int reg = DSPCNTR(intel_crtc->plane); - if (intel_crtc->primary_disabled) - return; - I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE); - - intel_crtc->primary_disabled = true; - intel_update_fbc(dev); } static int @@ -498,14 +485,18 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, * Be sure to re-enable the primary before the sprite is no longer * covering it fully. */ - if (!disable_primary) + if (!disable_primary && intel_plane->primary_disabled) { intel_enable_primary(crtc); + intel_plane->primary_disabled = false; + } intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y, crtc_w, crtc_h, x, y, src_w, src_h); - if (disable_primary) + if (disable_primary) { intel_disable_primary(crtc); + intel_plane->primary_disabled = true; + } /* Unpin old obj after new one is active to avoid ugliness */ if (old_obj) { @@ -536,8 +527,11 @@ intel_disable_plane(struct drm_plane *plane) struct intel_plane *intel_plane = to_intel_plane(plane); int ret = 0; - if (plane->crtc) + if (intel_plane->primary_disabled) { intel_enable_primary(plane->crtc); + intel_plane->primary_disabled = false; + } + intel_plane->disable_plane(plane); if (!intel_plane->obj) @@ -691,7 +685,6 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe) break; default: - kfree(intel_plane); return -ENODEV; } @@ -706,3 +699,4 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe) return ret; } + diff --git a/trunk/drivers/gpu/drm/i915/intel_tv.c b/trunk/drivers/gpu/drm/i915/intel_tv.c index befce6c49704..a233a51fd7e6 100644 --- a/trunk/drivers/gpu/drm/i915/intel_tv.c +++ b/trunk/drivers/gpu/drm/i915/intel_tv.c @@ -891,21 +891,24 @@ intel_tv_mode_valid(struct drm_connector *connector, static bool -intel_tv_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, +intel_tv_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = encoder->dev; + struct drm_mode_config *drm_config = &dev->mode_config; struct intel_tv *intel_tv = enc_to_intel_tv(encoder); const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv); - struct intel_encoder *other_encoder; + struct drm_encoder *other_encoder; if (!tv_mode) return false; - for_each_encoder_on_crtc(dev, encoder->crtc, other_encoder) - if (&other_encoder->base != encoder) + /* FIXME: lock encoder list */ + list_for_each_entry(other_encoder, &drm_config->encoder_list, head) { + if (other_encoder != encoder && + other_encoder->crtc == encoder->crtc) return false; + } adjusted_mode->clock = tv_mode->clock; return true; diff --git a/trunk/drivers/gpu/drm/mga/mga_drv.c b/trunk/drivers/gpu/drm/mga/mga_drv.c index b1bb46de3f5a..f9a925d58819 100644 --- a/trunk/drivers/gpu/drm/mga/mga_drv.c +++ b/trunk/drivers/gpu/drm/mga/mga_drv.c @@ -75,6 +75,7 @@ static struct drm_driver driver = { .irq_postinstall = mga_driver_irq_postinstall, .irq_uninstall = mga_driver_irq_uninstall, .irq_handler = mga_driver_irq_handler, + .reclaim_buffers = drm_core_reclaim_buffers, .ioctls = mga_ioctls, .dma_ioctl = mga_dma_buffers, .fops = &mga_driver_fops, diff --git a/trunk/drivers/gpu/drm/mgag200/mgag200_drv.c b/trunk/drivers/gpu/drm/mgag200/mgag200_drv.c index ea1024d79974..93e832d6c328 100644 --- a/trunk/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/trunk/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -47,9 +47,6 @@ static void mgag200_kick_out_firmware_fb(struct pci_dev *pdev) bool primary = false; ap = alloc_apertures(1); - if (!ap) - return; - ap->ranges[0].base = pci_resource_start(pdev, 0); ap->ranges[0].size = pci_resource_len(pdev, 0); diff --git a/trunk/drivers/gpu/drm/mgag200/mgag200_mode.c b/trunk/drivers/gpu/drm/mgag200/mgag200_mode.c index a4d7c500c97b..d303061b251e 100644 --- a/trunk/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/trunk/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -78,8 +78,8 @@ static inline void mga_wait_busy(struct mga_device *mdev) * to just pass that straight through, so this does nothing */ static bool mga_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { return true; } @@ -1322,8 +1322,8 @@ void mga_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, * to handle any encoder-specific limitations */ static bool mga_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { return true; } diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_drv.c b/trunk/drivers/gpu/drm/nouveau/nouveau_drv.c index b4d1b4afcac5..cad254c8e387 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -422,6 +422,7 @@ static struct drm_driver driver = { .get_vblank_counter = drm_vblank_count, .enable_vblank = nouveau_vblank_enable, .disable_vblank = nouveau_vblank_disable, + .reclaim_buffers = drm_core_reclaim_buffers, .ioctls = nouveau_ioctls, .fops = &nouveau_driver_fops, diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_gem.c b/trunk/drivers/gpu/drm/nouveau/nouveau_gem.c index fe3f5a821b84..30f542316944 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -207,7 +207,8 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, struct nouveau_bo *nvbo = NULL; int ret = 0; - dev_priv->ttm.bdev.dev_mapping = dev->dev_mapping; + if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) + dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) { NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags); diff --git a/trunk/drivers/gpu/drm/nouveau/nv04_crtc.c b/trunk/drivers/gpu/drm/nouveau/nv04_crtc.c index 43accc11102f..4c31c63e5528 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/trunk/drivers/gpu/drm/nouveau/nv04_crtc.c @@ -215,7 +215,7 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode) } static bool -nv_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, +nv_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; diff --git a/trunk/drivers/gpu/drm/nouveau/nv04_dac.c b/trunk/drivers/gpu/drm/nouveau/nv04_dac.c index 38f19479417c..8300266ffaea 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/trunk/drivers/gpu/drm/nouveau/nv04_dac.c @@ -332,7 +332,7 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) } static bool nv04_dac_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { if (nv04_dac_in_use(encoder)) diff --git a/trunk/drivers/gpu/drm/nouveau/nv04_dfp.c b/trunk/drivers/gpu/drm/nouveau/nv04_dfp.c index c2675623b7cd..2258746016f8 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/trunk/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -179,7 +179,7 @@ static struct drm_encoder *get_tmds_slave(struct drm_encoder *encoder) } static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); diff --git a/trunk/drivers/gpu/drm/nouveau/nv17_tv.c b/trunk/drivers/gpu/drm/nouveau/nv17_tv.c index 67be5db021f5..696d7e7dc2a0 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/trunk/drivers/gpu/drm/nouveau/nv17_tv.c @@ -338,7 +338,7 @@ static int nv17_tv_mode_valid(struct drm_encoder *encoder, } static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_crtc.c b/trunk/drivers/gpu/drm/nouveau/nv50_crtc.c index 22cebd5dd694..97a477b3d52d 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_crtc.c @@ -527,7 +527,7 @@ nv50_crtc_commit(struct drm_crtc *crtc) } static bool -nv50_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, +nv50_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_dac.c b/trunk/drivers/gpu/drm/nouveau/nv50_dac.c index 2c36a6b92c53..eb216a446b89 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_dac.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_dac.c @@ -175,8 +175,7 @@ nv50_dac_restore(struct drm_encoder *encoder) } static bool -nv50_dac_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, +nv50_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_sor.c b/trunk/drivers/gpu/drm/nouveau/nv50_sor.c index 93240bde891b..a9514eaa74c1 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_sor.c @@ -327,8 +327,7 @@ nv50_sor_restore(struct drm_encoder *encoder) } static bool -nv50_sor_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, +nv50_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); diff --git a/trunk/drivers/gpu/drm/nouveau/nva3_copy.fuc b/trunk/drivers/gpu/drm/nouveau/nva3_copy.fuc index abc36626fef0..219850d53286 100644 --- a/trunk/drivers/gpu/drm/nouveau/nva3_copy.fuc +++ b/trunk/drivers/gpu/drm/nouveau/nva3_copy.fuc @@ -119,9 +119,9 @@ dispatch_dma: // mthd 0x030c-0x0340, various stuff .b16 0xc3 14 .b32 #ctx_src_address_high ~0x000000ff -.b32 #ctx_src_address_low ~0xfffffff0 +.b32 #ctx_src_address_low ~0xffffffff .b32 #ctx_dst_address_high ~0x000000ff -.b32 #ctx_dst_address_low ~0xfffffff0 +.b32 #ctx_dst_address_low ~0xffffffff .b32 #ctx_src_pitch ~0x0007ffff .b32 #ctx_dst_pitch ~0x0007ffff .b32 #ctx_xcnt ~0x0000ffff diff --git a/trunk/drivers/gpu/drm/nouveau/nva3_copy.fuc.h b/trunk/drivers/gpu/drm/nouveau/nva3_copy.fuc.h index 1f33fbdc00be..37d6de3c9d61 100644 --- a/trunk/drivers/gpu/drm/nouveau/nva3_copy.fuc.h +++ b/trunk/drivers/gpu/drm/nouveau/nva3_copy.fuc.h @@ -1,37 +1,72 @@ -uint32_t nva3_pcopy_data[] = { +u32 nva3_pcopy_data[] = { +/* 0x0000: ctx_object */ 0x00000000, +/* 0x0004: ctx_dma */ +/* 0x0004: ctx_dma_query */ 0x00000000, +/* 0x0008: ctx_dma_src */ 0x00000000, +/* 0x000c: ctx_dma_dst */ 0x00000000, +/* 0x0010: ctx_query_address_high */ 0x00000000, +/* 0x0014: ctx_query_address_low */ 0x00000000, +/* 0x0018: ctx_query_counter */ 0x00000000, +/* 0x001c: ctx_src_address_high */ 0x00000000, +/* 0x0020: ctx_src_address_low */ 0x00000000, +/* 0x0024: ctx_src_pitch */ 0x00000000, +/* 0x0028: ctx_src_tile_mode */ 0x00000000, +/* 0x002c: ctx_src_xsize */ 0x00000000, +/* 0x0030: ctx_src_ysize */ 0x00000000, +/* 0x0034: ctx_src_zsize */ 0x00000000, +/* 0x0038: ctx_src_zoff */ 0x00000000, +/* 0x003c: ctx_src_xoff */ 0x00000000, +/* 0x0040: ctx_src_yoff */ 0x00000000, +/* 0x0044: ctx_src_cpp */ 0x00000000, +/* 0x0048: ctx_dst_address_high */ 0x00000000, +/* 0x004c: ctx_dst_address_low */ 0x00000000, +/* 0x0050: ctx_dst_pitch */ 0x00000000, +/* 0x0054: ctx_dst_tile_mode */ 0x00000000, +/* 0x0058: ctx_dst_xsize */ 0x00000000, +/* 0x005c: ctx_dst_ysize */ 0x00000000, +/* 0x0060: ctx_dst_zsize */ 0x00000000, +/* 0x0064: ctx_dst_zoff */ 0x00000000, +/* 0x0068: ctx_dst_xoff */ 0x00000000, +/* 0x006c: ctx_dst_yoff */ 0x00000000, +/* 0x0070: ctx_dst_cpp */ 0x00000000, +/* 0x0074: ctx_format */ 0x00000000, +/* 0x0078: ctx_swz_const0 */ 0x00000000, +/* 0x007c: ctx_swz_const1 */ 0x00000000, +/* 0x0080: ctx_xcnt */ 0x00000000, +/* 0x0084: ctx_ycnt */ 0x00000000, 0x00000000, 0x00000000, @@ -63,6 +98,7 @@ uint32_t nva3_pcopy_data[] = { 0x00000000, 0x00000000, 0x00000000, +/* 0x0100: dispatch_table */ 0x00010000, 0x00000000, 0x00000000, @@ -73,6 +109,7 @@ uint32_t nva3_pcopy_data[] = { 0x00010162, 0x00000000, 0x00030060, +/* 0x0128: dispatch_dma */ 0x00010170, 0x00000000, 0x00010170, @@ -118,11 +155,11 @@ uint32_t nva3_pcopy_data[] = { 0x0000001c, 0xffffff00, 0x00000020, - 0x0000000f, + 0x00000000, 0x00000048, 0xffffff00, 0x0000004c, - 0x0000000f, + 0x00000000, 0x00000024, 0xfff80000, 0x00000050, @@ -146,7 +183,8 @@ uint32_t nva3_pcopy_data[] = { 0x00000800, }; -uint32_t nva3_pcopy_code[] = { +u32 nva3_pcopy_code[] = { +/* 0x0000: main */ 0x04fe04bd, 0x3517f000, 0xf10010fe, @@ -158,23 +196,31 @@ uint32_t nva3_pcopy_code[] = { 0x17f11031, 0x27f01200, 0x0012d003, +/* 0x002f: spin */ 0xf40031f4, 0x0ef40028, +/* 0x0035: ih */ 0x8001cffd, 0xf40812c4, 0x21f4060b, +/* 0x0041: ih_no_chsw */ 0x0412c472, 0xf4060bf4, +/* 0x004a: ih_no_cmd */ 0x11c4c321, 0x4001d00c, +/* 0x0052: swctx */ 0x47f101f8, 0x4bfe7700, 0x0007fe00, 0xf00204b9, 0x01f40643, 0x0604fa09, +/* 0x006b: swctx_load */ 0xfa060ef4, +/* 0x006e: swctx_done */ 0x03f80504, +/* 0x0072: chsw */ 0x27f100f8, 0x23cf1400, 0x1e3fc800, @@ -183,18 +229,22 @@ uint32_t nva3_pcopy_code[] = { 0x1e3af052, 0xf00023d0, 0x24d00147, +/* 0x0093: chsw_no_unload */ 0xcf00f880, 0x3dc84023, 0x220bf41e, 0xf40131f4, 0x57f05221, 0x0367f004, +/* 0x00a8: chsw_load_ctx_dma */ 0xa07856bc, 0xb6018068, 0x87d00884, 0x0162b600, +/* 0x00bb: chsw_finish_load */ 0xf0f018f4, 0x23d00237, +/* 0x00c3: dispatch */ 0xf100f880, 0xcf190037, 0x33cf4032, @@ -202,6 +252,7 @@ uint32_t nva3_pcopy_code[] = { 0x1024b607, 0x010057f1, 0x74bd64bd, +/* 0x00dc: dispatch_loop */ 0x58005658, 0x50b60157, 0x0446b804, @@ -211,6 +262,7 @@ uint32_t nva3_pcopy_code[] = { 0xb60276bb, 0x57bb0374, 0xdf0ef400, +/* 0x0100: dispatch_valid_mthd */ 0xb60246bb, 0x45bb0344, 0x01459800, @@ -220,31 +272,41 @@ uint32_t nva3_pcopy_code[] = { 0xb0014658, 0x1bf40064, 0x00538009, +/* 0x0127: dispatch_cmd */ 0xf4300ef4, 0x55f90132, 0xf40c01f4, +/* 0x0132: dispatch_invalid_bitfield */ 0x25f0250e, +/* 0x0135: dispatch_illegal_mthd */ 0x0125f002, +/* 0x0138: dispatch_error */ 0x100047f1, 0xd00042d0, 0x27f04043, 0x0002d040, +/* 0x0148: hostirq_wait */ 0xf08002cf, 0x24b04024, 0xf71bf400, +/* 0x0154: dispatch_done */ 0x1d0027f1, 0xd00137f0, 0x00f80023, +/* 0x0160: cmd_nop */ +/* 0x0162: cmd_pm_trigger */ 0x27f100f8, 0x34bd2200, 0xd00233f0, 0x00f80023, +/* 0x0170: cmd_dma */ 0x012842b7, 0xf00145b6, 0x43801e39, 0x0040b701, 0x0644b606, 0xf80043d0, +/* 0x0189: cmd_exec_set_format */ 0xf030f400, 0xb00001b0, 0x01b00101, @@ -256,20 +318,26 @@ uint32_t nva3_pcopy_code[] = { 0x70b63847, 0x0232f401, 0x94bd84bd, +/* 0x01b4: ncomp_loop */ 0xb60f4ac4, 0xb4bd0445, +/* 0x01bc: bpc_loop */ 0xf404a430, 0xa5ff0f18, 0x00cbbbc0, 0xf40231f4, +/* 0x01ce: cmp_c0 */ 0x1bf4220e, 0x10c7f00c, 0xf400cbbb, +/* 0x01da: cmp_c1 */ 0xa430160e, 0x0c18f406, 0xbb14c7f0, 0x0ef400cb, +/* 0x01e9: cmp_zero */ 0x80c7f107, +/* 0x01ed: bpc_next */ 0x01c83800, 0xb60180b6, 0xb5b801b0, @@ -280,6 +348,7 @@ uint32_t nva3_pcopy_code[] = { 0x98110680, 0x68fd2008, 0x0502f400, +/* 0x0216: dst_xcnt */ 0x75fd64bd, 0x1c078000, 0xf10078fd, @@ -304,6 +373,7 @@ uint32_t nva3_pcopy_code[] = { 0x980056d0, 0x56d01f06, 0x1030f440, +/* 0x0276: cmd_exec_set_surface_tiled */ 0x579800f8, 0x6879c70a, 0xb66478c7, @@ -311,9 +381,11 @@ uint32_t nva3_pcopy_code[] = { 0x0e76b060, 0xf0091bf4, 0x0ef40477, +/* 0x0291: xtile64 */ 0x027cf00f, 0xfd1170b6, 0x77f00947, +/* 0x029d: xtileok */ 0x0f5a9806, 0xfd115b98, 0xb7f000ab, @@ -371,6 +443,7 @@ uint32_t nva3_pcopy_code[] = { 0x67d00600, 0x0060b700, 0x0068d004, +/* 0x0382: cmd_exec_set_surface_linear */ 0x6cf000f8, 0x0260b702, 0x0864b602, @@ -381,13 +454,16 @@ uint32_t nva3_pcopy_code[] = { 0xb70067d0, 0x98040060, 0x67d00957, +/* 0x03ab: cmd_exec_wait */ 0xf900f800, 0xf110f900, 0xb6080007, +/* 0x03b6: loop */ 0x01cf0604, 0x0114f000, 0xfcfa1bf4, 0xf800fc10, +/* 0x03c5: cmd_exec_query */ 0x0d34c800, 0xf5701bf4, 0xf103ab21, @@ -417,6 +493,7 @@ uint32_t nva3_pcopy_code[] = { 0x47f10153, 0x44b60800, 0x0045d006, +/* 0x0438: query_counter */ 0x03ab21f5, 0x080c47f1, 0x980644b6, @@ -439,11 +516,13 @@ uint32_t nva3_pcopy_code[] = { 0x47f10153, 0x44b60800, 0x0045d006, +/* 0x0492: cmd_exec */ 0x21f500f8, 0x3fc803ab, 0x0e0bf400, 0x018921f5, 0x020047f1, +/* 0x04a7: cmd_exec_no_format */ 0xf11e0ef4, 0xb6081067, 0x77f00664, @@ -451,19 +530,24 @@ uint32_t nva3_pcopy_code[] = { 0x981c0780, 0x67d02007, 0x4067d000, +/* 0x04c2: cmd_exec_init_src_surface */ 0x32f444bd, 0xc854bd02, 0x0bf4043f, 0x8221f50a, 0x0a0ef403, +/* 0x04d4: src_tiled */ 0x027621f5, +/* 0x04db: cmd_exec_init_dst_surface */ 0xf40749f0, 0x57f00231, 0x083fc82c, 0xf50a0bf4, 0xf4038221, +/* 0x04ee: dst_tiled */ 0x21f50a0e, 0x49f00276, +/* 0x04f5: cmd_exec_kick */ 0x0057f108, 0x0654b608, 0xd0210698, @@ -473,6 +557,8 @@ uint32_t nva3_pcopy_code[] = { 0xc80054d0, 0x0bf40c3f, 0xc521f507, +/* 0x0519: cmd_exec_done */ +/* 0x051b: cmd_wrcache_flush */ 0xf100f803, 0xbd220027, 0x0133f034, diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h b/trunk/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h index a8d17458ced1..cd879f31bb38 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h @@ -1,34 +1,65 @@ -uint32_t nvc0_pcopy_data[] = { +u32 nvc0_pcopy_data[] = { +/* 0x0000: ctx_object */ 0x00000000, +/* 0x0004: ctx_query_address_high */ 0x00000000, +/* 0x0008: ctx_query_address_low */ 0x00000000, +/* 0x000c: ctx_query_counter */ 0x00000000, +/* 0x0010: ctx_src_address_high */ 0x00000000, +/* 0x0014: ctx_src_address_low */ 0x00000000, +/* 0x0018: ctx_src_pitch */ 0x00000000, +/* 0x001c: ctx_src_tile_mode */ 0x00000000, +/* 0x0020: ctx_src_xsize */ 0x00000000, +/* 0x0024: ctx_src_ysize */ 0x00000000, +/* 0x0028: ctx_src_zsize */ 0x00000000, +/* 0x002c: ctx_src_zoff */ 0x00000000, +/* 0x0030: ctx_src_xoff */ 0x00000000, +/* 0x0034: ctx_src_yoff */ 0x00000000, +/* 0x0038: ctx_src_cpp */ 0x00000000, +/* 0x003c: ctx_dst_address_high */ 0x00000000, +/* 0x0040: ctx_dst_address_low */ 0x00000000, +/* 0x0044: ctx_dst_pitch */ 0x00000000, +/* 0x0048: ctx_dst_tile_mode */ 0x00000000, +/* 0x004c: ctx_dst_xsize */ 0x00000000, +/* 0x0050: ctx_dst_ysize */ 0x00000000, +/* 0x0054: ctx_dst_zsize */ 0x00000000, +/* 0x0058: ctx_dst_zoff */ 0x00000000, +/* 0x005c: ctx_dst_xoff */ 0x00000000, +/* 0x0060: ctx_dst_yoff */ 0x00000000, +/* 0x0064: ctx_dst_cpp */ 0x00000000, +/* 0x0068: ctx_format */ 0x00000000, +/* 0x006c: ctx_swz_const0 */ 0x00000000, +/* 0x0070: ctx_swz_const1 */ 0x00000000, +/* 0x0074: ctx_xcnt */ 0x00000000, +/* 0x0078: ctx_ycnt */ 0x00000000, 0x00000000, 0x00000000, @@ -63,6 +94,7 @@ uint32_t nvc0_pcopy_data[] = { 0x00000000, 0x00000000, 0x00000000, +/* 0x0100: dispatch_table */ 0x00010000, 0x00000000, 0x00000000, @@ -111,11 +143,11 @@ uint32_t nvc0_pcopy_data[] = { 0x00000010, 0xffffff00, 0x00000014, - 0x0000000f, + 0x00000000, 0x0000003c, 0xffffff00, 0x00000040, - 0x0000000f, + 0x00000000, 0x00000018, 0xfff80000, 0x00000044, @@ -139,7 +171,8 @@ uint32_t nvc0_pcopy_data[] = { 0x00000800, }; -uint32_t nvc0_pcopy_code[] = { +u32 nvc0_pcopy_code[] = { +/* 0x0000: main */ 0x04fe04bd, 0x3517f000, 0xf10010fe, @@ -151,15 +184,20 @@ uint32_t nvc0_pcopy_code[] = { 0x17f11031, 0x27f01200, 0x0012d003, +/* 0x002f: spin */ 0xf40031f4, 0x0ef40028, +/* 0x0035: ih */ 0x8001cffd, 0xf40812c4, 0x21f4060b, +/* 0x0041: ih_no_chsw */ 0x0412c4ca, 0xf5070bf4, +/* 0x004b: ih_no_cmd */ 0xc4010221, 0x01d00c11, +/* 0x0053: swctx */ 0xf101f840, 0xfe770047, 0x47f1004b, @@ -188,8 +226,11 @@ uint32_t nvc0_pcopy_code[] = { 0xf00204b9, 0x01f40643, 0x0604fa09, +/* 0x00c3: swctx_load */ 0xfa060ef4, +/* 0x00c6: swctx_done */ 0x03f80504, +/* 0x00ca: chsw */ 0x27f100f8, 0x23cf1400, 0x1e3fc800, @@ -198,18 +239,22 @@ uint32_t nvc0_pcopy_code[] = { 0x1e3af053, 0xf00023d0, 0x24d00147, +/* 0x00eb: chsw_no_unload */ 0xcf00f880, 0x3dc84023, 0x090bf41e, 0xf40131f4, +/* 0x00fa: chsw_finish_load */ 0x37f05321, 0x8023d002, +/* 0x0102: dispatch */ 0x37f100f8, 0x32cf1900, 0x0033cf40, 0x07ff24e4, 0xf11024b6, 0xbd010057, +/* 0x011b: dispatch_loop */ 0x5874bd64, 0x57580056, 0x0450b601, @@ -219,6 +264,7 @@ uint32_t nvc0_pcopy_code[] = { 0xbb0f08f4, 0x74b60276, 0x0057bb03, +/* 0x013f: dispatch_valid_mthd */ 0xbbdf0ef4, 0x44b60246, 0x0045bb03, @@ -229,24 +275,33 @@ uint32_t nvc0_pcopy_code[] = { 0x64b00146, 0x091bf400, 0xf4005380, +/* 0x0166: dispatch_cmd */ 0x32f4300e, 0xf455f901, 0x0ef40c01, +/* 0x0171: dispatch_invalid_bitfield */ 0x0225f025, +/* 0x0174: dispatch_illegal_mthd */ +/* 0x0177: dispatch_error */ 0xf10125f0, 0xd0100047, 0x43d00042, 0x4027f040, +/* 0x0187: hostirq_wait */ 0xcf0002d0, 0x24f08002, 0x0024b040, +/* 0x0193: dispatch_done */ 0xf1f71bf4, 0xf01d0027, 0x23d00137, +/* 0x019f: cmd_nop */ 0xf800f800, +/* 0x01a1: cmd_pm_trigger */ 0x0027f100, 0xf034bd22, 0x23d00233, +/* 0x01af: cmd_exec_set_format */ 0xf400f800, 0x01b0f030, 0x0101b000, @@ -258,20 +313,26 @@ uint32_t nvc0_pcopy_code[] = { 0x3847c701, 0xf40170b6, 0x84bd0232, +/* 0x01da: ncomp_loop */ 0x4ac494bd, 0x0445b60f, +/* 0x01e2: bpc_loop */ 0xa430b4bd, 0x0f18f404, 0xbbc0a5ff, 0x31f400cb, 0x220ef402, +/* 0x01f4: cmp_c0 */ 0xf00c1bf4, 0xcbbb10c7, 0x160ef400, +/* 0x0200: cmp_c1 */ 0xf406a430, 0xc7f00c18, 0x00cbbb14, +/* 0x020f: cmp_zero */ 0xf1070ef4, +/* 0x0213: bpc_next */ 0x380080c7, 0x80b601c8, 0x01b0b601, @@ -283,6 +344,7 @@ uint32_t nvc0_pcopy_code[] = { 0x1d08980e, 0xf40068fd, 0x64bd0502, +/* 0x023c: dst_xcnt */ 0x800075fd, 0x78fd1907, 0x1057f100, @@ -307,15 +369,18 @@ uint32_t nvc0_pcopy_code[] = { 0x1c069800, 0xf44056d0, 0x00f81030, +/* 0x029c: cmd_exec_set_surface_tiled */ 0xc7075798, 0x78c76879, 0x0380b664, 0xb06077c7, 0x1bf40e76, 0x0477f009, +/* 0x02b7: xtile64 */ 0xf00f0ef4, 0x70b6027c, 0x0947fd11, +/* 0x02c3: xtileok */ 0x980677f0, 0x5b980c5a, 0x00abfd0e, @@ -374,6 +439,7 @@ uint32_t nvc0_pcopy_code[] = { 0xb70067d0, 0xd0040060, 0x00f80068, +/* 0x03a8: cmd_exec_set_surface_linear */ 0xb7026cf0, 0xb6020260, 0x57980864, @@ -384,12 +450,15 @@ uint32_t nvc0_pcopy_code[] = { 0x0060b700, 0x06579804, 0xf80067d0, +/* 0x03d1: cmd_exec_wait */ 0xf900f900, 0x0007f110, 0x0604b608, +/* 0x03dc: loop */ 0xf00001cf, 0x1bf40114, 0xfc10fcfa, +/* 0x03eb: cmd_exec_query */ 0xc800f800, 0x1bf40d34, 0xd121f570, @@ -419,6 +488,7 @@ uint32_t nvc0_pcopy_code[] = { 0x0153f026, 0x080047f1, 0xd00644b6, +/* 0x045e: query_counter */ 0x21f50045, 0x47f103d1, 0x44b6080c, @@ -442,11 +512,13 @@ uint32_t nvc0_pcopy_code[] = { 0x080047f1, 0xd00644b6, 0x00f80045, +/* 0x04b8: cmd_exec */ 0x03d121f5, 0xf4003fc8, 0x21f50e0b, 0x47f101af, 0x0ef40200, +/* 0x04cd: cmd_exec_no_format */ 0x1067f11e, 0x0664b608, 0x800177f0, @@ -454,18 +526,23 @@ uint32_t nvc0_pcopy_code[] = { 0x1d079819, 0xd00067d0, 0x44bd4067, +/* 0x04e8: cmd_exec_init_src_surface */ 0xbd0232f4, 0x043fc854, 0xf50a0bf4, 0xf403a821, +/* 0x04fa: src_tiled */ 0x21f50a0e, 0x49f0029c, +/* 0x0501: cmd_exec_init_dst_surface */ 0x0231f407, 0xc82c57f0, 0x0bf4083f, 0xa821f50a, 0x0a0ef403, +/* 0x0514: dst_tiled */ 0x029c21f5, +/* 0x051b: cmd_exec_kick */ 0xf10849f0, 0xb6080057, 0x06980654, @@ -475,7 +552,9 @@ uint32_t nvc0_pcopy_code[] = { 0x54d00546, 0x0c3fc800, 0xf5070bf4, +/* 0x053f: cmd_exec_done */ 0xf803eb21, +/* 0x0541: cmd_wrcache_flush */ 0x0027f100, 0xf034bd22, 0x23d00133, diff --git a/trunk/drivers/gpu/drm/nouveau/nvd0_display.c b/trunk/drivers/gpu/drm/nouveau/nvd0_display.c index d0d60e1e7f95..c486d3ce3c2c 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/trunk/drivers/gpu/drm/nouveau/nvd0_display.c @@ -607,7 +607,7 @@ nvd0_crtc_commit(struct drm_crtc *crtc) } static bool -nvd0_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, +nvd0_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; @@ -938,8 +938,7 @@ nvd0_dac_dpms(struct drm_encoder *encoder, int mode) } static bool -nvd0_dac_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, +nvd0_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); @@ -1378,8 +1377,7 @@ nvd0_sor_dpms(struct drm_encoder *encoder, int mode) } static bool -nvd0_sor_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, +nvd0_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); diff --git a/trunk/drivers/gpu/drm/r128/r128_drv.c b/trunk/drivers/gpu/drm/r128/r128_drv.c index 2666a5308ab9..88718fad5d6d 100644 --- a/trunk/drivers/gpu/drm/r128/r128_drv.c +++ b/trunk/drivers/gpu/drm/r128/r128_drv.c @@ -71,6 +71,7 @@ static struct drm_driver driver = { .irq_postinstall = r128_driver_irq_postinstall, .irq_uninstall = r128_driver_irq_uninstall, .irq_handler = r128_driver_irq_handler, + .reclaim_buffers = drm_core_reclaim_buffers, .ioctls = r128_ioctls, .dma_ioctl = r128_cce_buffers, .fops = &r128_driver_fops, diff --git a/trunk/drivers/gpu/drm/radeon/atombios_crtc.c b/trunk/drivers/gpu/drm/radeon/atombios_crtc.c index 9e6f76fec527..3904d7964a4b 100644 --- a/trunk/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/trunk/drivers/gpu/drm/radeon/atombios_crtc.c @@ -457,18 +457,22 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev, switch (pll_id) { case ATOM_PPLL1: args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P1PLL; + args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); + args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step); break; case ATOM_PPLL2: args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P2PLL; + args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); + args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step); break; case ATOM_DCPLL: args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_DCPLL; + args.v3.usSpreadSpectrumAmount = cpu_to_le16(0); + args.v3.usSpreadSpectrumStep = cpu_to_le16(0); break; case ATOM_PPLL_INVALID: return; } - args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); - args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step); args.v3.ucEnable = enable; if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE61(rdev)) args.v3.ucEnable = ATOM_DISABLE; @@ -478,18 +482,22 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev, switch (pll_id) { case ATOM_PPLL1: args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P1PLL; + args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); + args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step); break; case ATOM_PPLL2: args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P2PLL; + args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); + args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step); break; case ATOM_DCPLL: args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_DCPLL; + args.v2.usSpreadSpectrumAmount = cpu_to_le16(0); + args.v2.usSpreadSpectrumStep = cpu_to_le16(0); break; case ATOM_PPLL_INVALID: return; } - args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount); - args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step); args.v2.ucEnable = enable; if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE41(rdev)) args.v2.ucEnable = ATOM_DISABLE; @@ -1531,11 +1539,7 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) * crtc virtual pixel clock. */ if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { - if (ASIC_IS_DCE5(rdev)) - return ATOM_DCPLL; - else if (ASIC_IS_DCE6(rdev)) - return ATOM_PPLL0; - else if (rdev->clock.dp_extclk) + if (ASIC_IS_DCE5(rdev) || rdev->clock.dp_extclk) return ATOM_PPLL_INVALID; } } @@ -1624,7 +1628,7 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, } static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) diff --git a/trunk/drivers/gpu/drm/radeon/atombios_dp.c b/trunk/drivers/gpu/drm/radeon/atombios_dp.c index 7712cf5ab33b..5131b3b0f7d2 100644 --- a/trunk/drivers/gpu/drm/radeon/atombios_dp.c +++ b/trunk/drivers/gpu/drm/radeon/atombios_dp.c @@ -22,7 +22,6 @@ * * Authors: Dave Airlie * Alex Deucher - * Jerome Glisse */ #include "drmP.h" #include "radeon_drm.h" @@ -609,7 +608,7 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, } void radeon_dp_set_link_config(struct drm_connector *connector, - const struct drm_display_mode *mode) + struct drm_display_mode *mode) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_connector_atom_dig *dig_connector; @@ -655,6 +654,7 @@ static bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector, ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, link_status, DP_LINK_STATUS_SIZE, 100); if (ret <= 0) { + DRM_ERROR("displayport link status failed\n"); return false; } @@ -833,10 +833,8 @@ static int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info) else mdelay(dp_info->rd_interval * 4); - if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { - DRM_ERROR("displayport link status failed\n"); + if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) break; - } if (dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { clock_recovery = true; @@ -898,10 +896,8 @@ static int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info) else mdelay(dp_info->rd_interval * 4); - if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { - DRM_ERROR("displayport link status failed\n"); + if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) break; - } if (dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { channel_eq = true; diff --git a/trunk/drivers/gpu/drm/radeon/atombios_encoders.c b/trunk/drivers/gpu/drm/radeon/atombios_encoders.c index f9bc27fe269a..486ccdf4aacd 100644 --- a/trunk/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/trunk/drivers/gpu/drm/radeon/atombios_encoders.c @@ -58,7 +58,7 @@ static inline bool radeon_encoder_is_digital(struct drm_encoder *encoder) } static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); @@ -1392,18 +1392,10 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) case DRM_MODE_DPMS_ON: /* some early dce3.2 boards have a bug in their transmitter control table */ if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) || - ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { - if (ASIC_IS_DCE6(rdev)) { - /* It seems we need to call ATOM_ENCODER_CMD_SETUP again - * before reenabling encoder on DPMS ON, otherwise we never - * get picture - */ - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); - } + ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - } else { + else atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); - } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { atombios_set_edp_panel_power(connector, @@ -2242,7 +2234,7 @@ radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode) } static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; diff --git a/trunk/drivers/gpu/drm/radeon/evergreen.c b/trunk/drivers/gpu/drm/radeon/evergreen.c index e585a3b947eb..7fb3d2e0434c 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen.c @@ -99,14 +99,6 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev) } } -/** - * dce4_wait_for_vblank - vblank wait asic callback. - * - * @rdev: radeon_device pointer - * @crtc: crtc to wait for vblank on - * - * Wait for vblank on the requested crtc (evergreen+). - */ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; @@ -126,49 +118,18 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) } } -/** - * radeon_irq_kms_pflip_irq_get - pre-pageflip callback. - * - * @rdev: radeon_device pointer - * @crtc: crtc to prepare for pageflip on - * - * Pre-pageflip callback (evergreen+). - * Enables the pageflip irq (vblank irq). - */ void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc) { /* enable the pflip int */ radeon_irq_kms_pflip_irq_get(rdev, crtc); } -/** - * evergreen_post_page_flip - pos-pageflip callback. - * - * @rdev: radeon_device pointer - * @crtc: crtc to cleanup pageflip on - * - * Post-pageflip callback (evergreen+). - * Disables the pageflip irq (vblank irq). - */ void evergreen_post_page_flip(struct radeon_device *rdev, int crtc) { /* disable the pflip int */ radeon_irq_kms_pflip_irq_put(rdev, crtc); } -/** - * evergreen_page_flip - pageflip callback. - * - * @rdev: radeon_device pointer - * @crtc_id: crtc to cleanup pageflip on - * @crtc_base: new address of the crtc (GPU MC address) - * - * Does the actual pageflip (evergreen+). - * During vblank we take the crtc lock and wait for the update_pending - * bit to go high, when it does, we release the lock, and allow the - * double buffered update to take place. - * Returns the current update pending status. - */ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; @@ -253,15 +214,6 @@ int sumo_get_temp(struct radeon_device *rdev) return actual_temp * 1000; } -/** - * sumo_pm_init_profile - Initialize power profiles callback. - * - * @rdev: radeon_device pointer - * - * Initialize the power states used in profile mode - * (sumo, trinity, SI). - * Used for profile mode only. - */ void sumo_pm_init_profile(struct radeon_device *rdev) { int idx; @@ -313,14 +265,6 @@ void sumo_pm_init_profile(struct radeon_device *rdev) rdev->pm.power_state[idx].num_clock_modes - 1; } -/** - * evergreen_pm_misc - set additional pm hw parameters callback. - * - * @rdev: radeon_device pointer - * - * Set non-clock parameters associated with a power state - * (voltage, etc.) (evergreen+). - */ void evergreen_pm_misc(struct radeon_device *rdev) { int req_ps_idx = rdev->pm.requested_power_state_index; @@ -348,13 +292,6 @@ void evergreen_pm_misc(struct radeon_device *rdev) } } -/** - * evergreen_pm_prepare - pre-power state change callback. - * - * @rdev: radeon_device pointer - * - * Prepare for a power state change (evergreen+). - */ void evergreen_pm_prepare(struct radeon_device *rdev) { struct drm_device *ddev = rdev->ddev; @@ -373,13 +310,6 @@ void evergreen_pm_prepare(struct radeon_device *rdev) } } -/** - * evergreen_pm_finish - post-power state change callback. - * - * @rdev: radeon_device pointer - * - * Clean up after a power state change (evergreen+). - */ void evergreen_pm_finish(struct radeon_device *rdev) { struct drm_device *ddev = rdev->ddev; @@ -398,15 +328,6 @@ void evergreen_pm_finish(struct radeon_device *rdev) } } -/** - * evergreen_hpd_sense - hpd sense callback. - * - * @rdev: radeon_device pointer - * @hpd: hpd (hotplug detect) pin - * - * Checks if a digital monitor is connected (evergreen+). - * Returns true if connected, false if not connected. - */ bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) { bool connected = false; @@ -443,14 +364,6 @@ bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) return connected; } -/** - * evergreen_hpd_set_polarity - hpd set polarity callback. - * - * @rdev: radeon_device pointer - * @hpd: hpd (hotplug detect) pin - * - * Set the polarity of the hpd pin (evergreen+). - */ void evergreen_hpd_set_polarity(struct radeon_device *rdev, enum radeon_hpd_id hpd) { @@ -511,19 +424,10 @@ void evergreen_hpd_set_polarity(struct radeon_device *rdev, } } -/** - * evergreen_hpd_init - hpd setup callback. - * - * @rdev: radeon_device pointer - * - * Setup the hpd pins used by the card (evergreen+). - * Enable the pin, set the polarity, and enable the hpd interrupts. - */ void evergreen_hpd_init(struct radeon_device *rdev) { struct drm_device *dev = rdev->ddev; struct drm_connector *connector; - unsigned enabled = 0; u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa) | DC_HPDx_EN; @@ -532,72 +436,73 @@ void evergreen_hpd_init(struct radeon_device *rdev) switch (radeon_connector->hpd.hpd) { case RADEON_HPD_1: WREG32(DC_HPD1_CONTROL, tmp); + rdev->irq.hpd[0] = true; break; case RADEON_HPD_2: WREG32(DC_HPD2_CONTROL, tmp); + rdev->irq.hpd[1] = true; break; case RADEON_HPD_3: WREG32(DC_HPD3_CONTROL, tmp); + rdev->irq.hpd[2] = true; break; case RADEON_HPD_4: WREG32(DC_HPD4_CONTROL, tmp); + rdev->irq.hpd[3] = true; break; case RADEON_HPD_5: WREG32(DC_HPD5_CONTROL, tmp); + rdev->irq.hpd[4] = true; break; case RADEON_HPD_6: WREG32(DC_HPD6_CONTROL, tmp); + rdev->irq.hpd[5] = true; break; default: break; } radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); - enabled |= 1 << radeon_connector->hpd.hpd; } - radeon_irq_kms_enable_hpd(rdev, enabled); + if (rdev->irq.installed) + evergreen_irq_set(rdev); } -/** - * evergreen_hpd_fini - hpd tear down callback. - * - * @rdev: radeon_device pointer - * - * Tear down the hpd pins used by the card (evergreen+). - * Disable the hpd interrupts. - */ void evergreen_hpd_fini(struct radeon_device *rdev) { struct drm_device *dev = rdev->ddev; struct drm_connector *connector; - unsigned disabled = 0; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); switch (radeon_connector->hpd.hpd) { case RADEON_HPD_1: WREG32(DC_HPD1_CONTROL, 0); + rdev->irq.hpd[0] = false; break; case RADEON_HPD_2: WREG32(DC_HPD2_CONTROL, 0); + rdev->irq.hpd[1] = false; break; case RADEON_HPD_3: WREG32(DC_HPD3_CONTROL, 0); + rdev->irq.hpd[2] = false; break; case RADEON_HPD_4: WREG32(DC_HPD4_CONTROL, 0); + rdev->irq.hpd[3] = false; break; case RADEON_HPD_5: WREG32(DC_HPD5_CONTROL, 0); + rdev->irq.hpd[4] = false; break; case RADEON_HPD_6: WREG32(DC_HPD6_CONTROL, 0); + rdev->irq.hpd[5] = false; break; default: break; } - disabled |= 1 << radeon_connector->hpd.hpd; } - radeon_irq_kms_disable_hpd(rdev, disabled); } /* watermark setup */ @@ -1028,14 +933,6 @@ static void evergreen_program_watermarks(struct radeon_device *rdev, } -/** - * evergreen_bandwidth_update - update display watermarks callback. - * - * @rdev: radeon_device pointer - * - * Update the display watermarks based on the requested mode(s) - * (evergreen+). - */ void evergreen_bandwidth_update(struct radeon_device *rdev) { struct drm_display_mode *mode0 = NULL; @@ -1059,15 +956,6 @@ void evergreen_bandwidth_update(struct radeon_device *rdev) } } -/** - * evergreen_mc_wait_for_idle - wait for MC idle callback. - * - * @rdev: radeon_device pointer - * - * Wait for the MC (memory controller) to be idle. - * (evergreen+). - * Returns 0 if the MC is idle, -1 if not. - */ int evergreen_mc_wait_for_idle(struct radeon_device *rdev) { unsigned i; @@ -1483,28 +1371,12 @@ void evergreen_mc_program(struct radeon_device *rdev) */ void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) { - struct radeon_ring *ring = &rdev->ring[ib->ring]; - u32 next_rptr; + struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; /* set to DX10/11 mode */ radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); radeon_ring_write(ring, 1); - - if (ring->rptr_save_reg) { - next_rptr = ring->wptr + 3 + 4; - radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); - radeon_ring_write(ring, ((ring->rptr_save_reg - - PACKET3_SET_CONFIG_REG_START) >> 2)); - radeon_ring_write(ring, next_rptr); - } else if (rdev->wb.enabled) { - next_rptr = ring->wptr + 5 + 4; - radeon_ring_write(ring, PACKET3(PACKET3_MEM_WRITE, 3)); - radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); - radeon_ring_write(ring, (upper_32_bits(ring->next_rptr_gpu_addr) & 0xff) | (1 << 18)); - radeon_ring_write(ring, next_rptr); - radeon_ring_write(ring, 0); - } - + /* FIXME: implement */ radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); radeon_ring_write(ring, #ifdef __BIG_ENDIAN @@ -2316,14 +2188,6 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev) RREG32(GRBM_STATUS_SE1)); dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", RREG32(SRBM_STATUS)); - dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", - RREG32(CP_STALLED_STAT1)); - dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", - RREG32(CP_STALLED_STAT2)); - dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", - RREG32(CP_BUSY_STAT)); - dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", - RREG32(CP_STAT)); evergreen_mc_stop(rdev, &save); if (evergreen_mc_wait_for_idle(rdev)) { dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); @@ -2361,14 +2225,6 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev) RREG32(GRBM_STATUS_SE1)); dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", RREG32(SRBM_STATUS)); - dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", - RREG32(CP_STALLED_STAT1)); - dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", - RREG32(CP_STALLED_STAT2)); - dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", - RREG32(CP_BUSY_STAT)); - dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", - RREG32(CP_STAT)); evergreen_mc_resume(rdev, &save); return 0; } @@ -2492,20 +2348,20 @@ int evergreen_irq_set(struct radeon_device *rdev) if (rdev->family >= CHIP_CAYMAN) { /* enable CP interrupts on all rings */ - if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { + if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); cp_int_cntl |= TIME_STAMP_INT_ENABLE; } - if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP1_INDEX])) { + if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP1_INDEX]) { DRM_DEBUG("evergreen_irq_set: sw int cp1\n"); cp_int_cntl1 |= TIME_STAMP_INT_ENABLE; } - if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP2_INDEX])) { + if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP2_INDEX]) { DRM_DEBUG("evergreen_irq_set: sw int cp2\n"); cp_int_cntl2 |= TIME_STAMP_INT_ENABLE; } } else { - if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { + if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { DRM_DEBUG("evergreen_irq_set: sw int gfx\n"); cp_int_cntl |= RB_INT_ENABLE; cp_int_cntl |= TIME_STAMP_INT_ENABLE; @@ -2513,32 +2369,32 @@ int evergreen_irq_set(struct radeon_device *rdev) } if (rdev->irq.crtc_vblank_int[0] || - atomic_read(&rdev->irq.pflip[0])) { + rdev->irq.pflip[0]) { DRM_DEBUG("evergreen_irq_set: vblank 0\n"); crtc1 |= VBLANK_INT_MASK; } if (rdev->irq.crtc_vblank_int[1] || - atomic_read(&rdev->irq.pflip[1])) { + rdev->irq.pflip[1]) { DRM_DEBUG("evergreen_irq_set: vblank 1\n"); crtc2 |= VBLANK_INT_MASK; } if (rdev->irq.crtc_vblank_int[2] || - atomic_read(&rdev->irq.pflip[2])) { + rdev->irq.pflip[2]) { DRM_DEBUG("evergreen_irq_set: vblank 2\n"); crtc3 |= VBLANK_INT_MASK; } if (rdev->irq.crtc_vblank_int[3] || - atomic_read(&rdev->irq.pflip[3])) { + rdev->irq.pflip[3]) { DRM_DEBUG("evergreen_irq_set: vblank 3\n"); crtc4 |= VBLANK_INT_MASK; } if (rdev->irq.crtc_vblank_int[4] || - atomic_read(&rdev->irq.pflip[4])) { + rdev->irq.pflip[4]) { DRM_DEBUG("evergreen_irq_set: vblank 4\n"); crtc5 |= VBLANK_INT_MASK; } if (rdev->irq.crtc_vblank_int[5] || - atomic_read(&rdev->irq.pflip[5])) { + rdev->irq.pflip[5]) { DRM_DEBUG("evergreen_irq_set: vblank 5\n"); crtc6 |= VBLANK_INT_MASK; } @@ -2820,6 +2676,7 @@ int evergreen_irq_process(struct radeon_device *rdev) u32 rptr; u32 src_id, src_data; u32 ring_index; + unsigned long flags; bool queue_hotplug = false; bool queue_hdmi = false; @@ -2827,21 +2684,22 @@ int evergreen_irq_process(struct radeon_device *rdev) return IRQ_NONE; wptr = evergreen_get_ih_wptr(rdev); - -restart_ih: - /* is somebody else already processing irqs? */ - if (atomic_xchg(&rdev->ih.lock, 1)) - return IRQ_NONE; - rptr = rdev->ih.rptr; DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); + spin_lock_irqsave(&rdev->ih.lock, flags); + if (rptr == wptr) { + spin_unlock_irqrestore(&rdev->ih.lock, flags); + return IRQ_NONE; + } +restart_ih: /* Order reading of wptr vs. reading of IH ring data */ rmb(); /* display interrupts */ evergreen_irq_ack(rdev); + rdev->ih.wptr = wptr; while (rptr != wptr) { /* wptr/rptr are in bytes! */ ring_index = rptr / 4; @@ -2858,7 +2716,7 @@ int evergreen_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[0])) + if (rdev->irq.pflip[0]) radeon_crtc_handle_flip(rdev, 0); rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); @@ -2884,7 +2742,7 @@ int evergreen_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[1])) + if (rdev->irq.pflip[1]) radeon_crtc_handle_flip(rdev, 1); rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); @@ -2910,7 +2768,7 @@ int evergreen_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[2])) + if (rdev->irq.pflip[2]) radeon_crtc_handle_flip(rdev, 2); rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; DRM_DEBUG("IH: D3 vblank\n"); @@ -2936,7 +2794,7 @@ int evergreen_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[3])) + if (rdev->irq.pflip[3]) radeon_crtc_handle_flip(rdev, 3); rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; DRM_DEBUG("IH: D4 vblank\n"); @@ -2962,7 +2820,7 @@ int evergreen_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[4])) + if (rdev->irq.pflip[4]) radeon_crtc_handle_flip(rdev, 4); rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; DRM_DEBUG("IH: D5 vblank\n"); @@ -2988,7 +2846,7 @@ int evergreen_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[5])) + if (rdev->irq.pflip[5]) radeon_crtc_handle_flip(rdev, 5); rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; DRM_DEBUG("IH: D6 vblank\n"); @@ -3128,6 +2986,7 @@ int evergreen_irq_process(struct radeon_device *rdev) break; case 233: /* GUI IDLE */ DRM_DEBUG("IH: GUI idle\n"); + rdev->pm.gui_idle = true; wake_up(&rdev->irq.idle_queue); break; default: @@ -3139,19 +2998,17 @@ int evergreen_irq_process(struct radeon_device *rdev) rptr += 16; rptr &= rdev->ih.ptr_mask; } + /* make sure wptr hasn't changed while processing */ + wptr = evergreen_get_ih_wptr(rdev); + if (wptr != rdev->ih.wptr) + goto restart_ih; if (queue_hotplug) schedule_work(&rdev->hotplug_work); if (queue_hdmi) schedule_work(&rdev->audio_work); rdev->ih.rptr = rptr; WREG32(IH_RB_RPTR, rdev->ih.rptr); - atomic_set(&rdev->ih.lock, 0); - - /* make sure wptr hasn't changed while processing */ - wptr = evergreen_get_ih_wptr(rdev); - if (wptr != rptr) - goto restart_ih; - + spin_unlock_irqrestore(&rdev->ih.lock, flags); return IRQ_HANDLED; } @@ -3239,11 +3096,13 @@ static int evergreen_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_ib_pool_init(rdev); - if (r) { - dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + r = radeon_ib_pool_start(rdev); + if (r) + return r; + + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } r = r600_audio_init(rdev); if (r) { @@ -3287,6 +3146,9 @@ int evergreen_suspend(struct radeon_device *rdev) struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; r600_audio_fini(rdev); + /* FIXME: we should wait for ring to be empty */ + radeon_ib_pool_suspend(rdev); + r600_blit_suspend(rdev); r700_cp_stop(rdev); ring->ready = false; evergreen_irq_suspend(rdev); @@ -3372,14 +3234,20 @@ int evergreen_init(struct radeon_device *rdev) if (r) return r; + r = radeon_ib_pool_init(rdev); rdev->accel_working = true; + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + rdev->accel_working = false; + } + r = evergreen_startup(rdev); if (r) { dev_err(rdev->dev, "disabling GPU acceleration\n"); r700_cp_fini(rdev); r600_irq_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_irq_kms_fini(rdev); evergreen_pcie_gart_fini(rdev); rdev->accel_working = false; @@ -3406,7 +3274,7 @@ void evergreen_fini(struct radeon_device *rdev) r700_cp_fini(rdev); r600_irq_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_irq_kms_fini(rdev); evergreen_pcie_gart_fini(rdev); r600_vram_scratch_fini(rdev); @@ -3421,8 +3289,7 @@ void evergreen_fini(struct radeon_device *rdev) void evergreen_pcie_gen2_enable(struct radeon_device *rdev) { - u32 link_width_cntl, speed_cntl, mask; - int ret; + u32 link_width_cntl, speed_cntl; if (radeon_pcie_gen2 == 0) return; @@ -3437,15 +3304,6 @@ void evergreen_pcie_gen2_enable(struct radeon_device *rdev) if (ASIC_IS_X2(rdev)) return; - ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); - if (ret != 0) - return; - - if (!(mask & DRM_PCIE_SPEED_50)) - return; - - DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); - speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) || (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) { diff --git a/trunk/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/trunk/drivers/gpu/drm/radeon/evergreen_blit_kms.c index 89cb9feb5653..1e96bd458cfd 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen_blit_kms.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen_blit_kms.c @@ -622,8 +622,7 @@ int evergreen_blit_init(struct radeon_device *rdev) rdev->r600_blit.primitives.draw_auto = draw_auto; rdev->r600_blit.primitives.set_default_state = set_default_state; - rdev->r600_blit.ring_size_common = 8; /* sync semaphore */ - rdev->r600_blit.ring_size_common += 55; /* shaders + def state */ + rdev->r600_blit.ring_size_common = 55; /* shaders + def state */ rdev->r600_blit.ring_size_common += 16; /* fence emit for VB IB */ rdev->r600_blit.ring_size_common += 5; /* done copy */ rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */ @@ -634,6 +633,10 @@ int evergreen_blit_init(struct radeon_device *rdev) rdev->r600_blit.max_dim = 16384; + /* pin copy shader into vram if already initialized */ + if (rdev->r600_blit.shader_obj) + goto done; + rdev->r600_blit.state_offset = 0; if (rdev->family < CHIP_CAYMAN) @@ -664,26 +667,11 @@ int evergreen_blit_init(struct radeon_device *rdev) obj_size += cayman_ps_size * 4; obj_size = ALIGN(obj_size, 256); - /* pin copy shader into vram if not already initialized */ - if (!rdev->r600_blit.shader_obj) { - r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, - RADEON_GEM_DOMAIN_VRAM, - NULL, &rdev->r600_blit.shader_obj); - if (r) { - DRM_ERROR("evergreen failed to allocate shader\n"); - return r; - } - - r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); - if (unlikely(r != 0)) - return r; - r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, - &rdev->r600_blit.shader_gpu_addr); - radeon_bo_unreserve(rdev->r600_blit.shader_obj); - if (r) { - dev_err(rdev->dev, "(%d) pin blit object failed\n", r); - return r; - } + r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, + NULL, &rdev->r600_blit.shader_obj); + if (r) { + DRM_ERROR("evergreen failed to allocate shader\n"); + return r; } DRM_DEBUG("evergreen blit allocated bo %08x vs %08x ps %08x\n", @@ -725,6 +713,17 @@ int evergreen_blit_init(struct radeon_device *rdev) radeon_bo_kunmap(rdev->r600_blit.shader_obj); radeon_bo_unreserve(rdev->r600_blit.shader_obj); +done: + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, + &rdev->r600_blit.shader_gpu_addr); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); + if (r) { + dev_err(rdev->dev, "(%d) pin blit object failed\n", r); + return r; + } radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); return 0; } diff --git a/trunk/drivers/gpu/drm/radeon/evergreend.h b/trunk/drivers/gpu/drm/radeon/evergreend.h index d3bd098e4e19..b50b15c70498 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreend.h +++ b/trunk/drivers/gpu/drm/radeon/evergreend.h @@ -88,10 +88,6 @@ #define CONFIG_MEMSIZE 0x5428 #define CP_COHER_BASE 0x85F8 -#define CP_STALLED_STAT1 0x8674 -#define CP_STALLED_STAT2 0x8678 -#define CP_BUSY_STAT 0x867C -#define CP_STAT 0x8680 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) #define CP_PFP_HALT (1 << 26) diff --git a/trunk/drivers/gpu/drm/radeon/ni.c b/trunk/drivers/gpu/drm/radeon/ni.c index 9945d86d9001..b7bf18e40215 100644 --- a/trunk/drivers/gpu/drm/radeon/ni.c +++ b/trunk/drivers/gpu/drm/radeon/ni.c @@ -850,20 +850,11 @@ void cayman_fence_ring_emit(struct radeon_device *rdev, void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) { - struct radeon_ring *ring = &rdev->ring[ib->ring]; + struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; /* set to DX10/11 mode */ radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); radeon_ring_write(ring, 1); - - if (ring->rptr_save_reg) { - uint32_t next_rptr = ring->wptr + 3 + 4 + 8; - radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); - radeon_ring_write(ring, ((ring->rptr_save_reg - - PACKET3_SET_CONFIG_REG_START) >> 2)); - radeon_ring_write(ring, next_rptr); - } - radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); radeon_ring_write(ring, #ifdef __BIG_ENDIAN @@ -990,41 +981,16 @@ static int cayman_cp_start(struct radeon_device *rdev) static void cayman_cp_fini(struct radeon_device *rdev) { - struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; cayman_cp_enable(rdev, false); - radeon_ring_fini(rdev, ring); - radeon_scratch_free(rdev, ring->rptr_save_reg); + radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); } int cayman_cp_resume(struct radeon_device *rdev) { - static const int ridx[] = { - RADEON_RING_TYPE_GFX_INDEX, - CAYMAN_RING_TYPE_CP1_INDEX, - CAYMAN_RING_TYPE_CP2_INDEX - }; - static const unsigned cp_rb_cntl[] = { - CP_RB0_CNTL, - CP_RB1_CNTL, - CP_RB2_CNTL, - }; - static const unsigned cp_rb_rptr_addr[] = { - CP_RB0_RPTR_ADDR, - CP_RB1_RPTR_ADDR, - CP_RB2_RPTR_ADDR - }; - static const unsigned cp_rb_rptr_addr_hi[] = { - CP_RB0_RPTR_ADDR_HI, - CP_RB1_RPTR_ADDR_HI, - CP_RB2_RPTR_ADDR_HI - }; - static const unsigned cp_rb_base[] = { - CP_RB0_BASE, - CP_RB1_BASE, - CP_RB2_BASE - }; struct radeon_ring *ring; - int i, r; + u32 tmp; + u32 rb_bufsz; + int r; /* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */ WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP | @@ -1046,47 +1012,91 @@ int cayman_cp_resume(struct radeon_device *rdev) WREG32(CP_DEBUG, (1 << 27)); + /* ring 0 - compute and gfx */ + /* Set ring buffer size */ + ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + rb_bufsz = drm_order(ring->ring_size / 8); + tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; +#ifdef __BIG_ENDIAN + tmp |= BUF_SWAP_32BIT; +#endif + WREG32(CP_RB0_CNTL, tmp); + + /* Initialize the ring buffer's read and write pointers */ + WREG32(CP_RB0_CNTL, tmp | RB_RPTR_WR_ENA); + ring->wptr = 0; + WREG32(CP_RB0_WPTR, ring->wptr); + /* set the wb address wether it's enabled or not */ + WREG32(CP_RB0_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC); + WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF); WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); - WREG32(SCRATCH_UMSK, 0xff); - for (i = 0; i < 3; ++i) { - uint32_t rb_cntl; - uint64_t addr; + if (rdev->wb.enabled) + WREG32(SCRATCH_UMSK, 0xff); + else { + tmp |= RB_NO_UPDATE; + WREG32(SCRATCH_UMSK, 0); + } - /* Set ring buffer size */ - ring = &rdev->ring[ridx[i]]; - rb_cntl = drm_order(ring->ring_size / 8); - rb_cntl |= drm_order(RADEON_GPU_PAGE_SIZE/8) << 8; + mdelay(1); + WREG32(CP_RB0_CNTL, tmp); + + WREG32(CP_RB0_BASE, ring->gpu_addr >> 8); + + ring->rptr = RREG32(CP_RB0_RPTR); + + /* ring1 - compute only */ + /* Set ring buffer size */ + ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; + rb_bufsz = drm_order(ring->ring_size / 8); + tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; #ifdef __BIG_ENDIAN - rb_cntl |= BUF_SWAP_32BIT; + tmp |= BUF_SWAP_32BIT; #endif - WREG32(cp_rb_cntl[i], rb_cntl); + WREG32(CP_RB1_CNTL, tmp); - /* set the wb address wether it's enabled or not */ - addr = rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET; - WREG32(cp_rb_rptr_addr[i], addr & 0xFFFFFFFC); - WREG32(cp_rb_rptr_addr_hi[i], upper_32_bits(addr) & 0xFF); - } + /* Initialize the ring buffer's read and write pointers */ + WREG32(CP_RB1_CNTL, tmp | RB_RPTR_WR_ENA); + ring->wptr = 0; + WREG32(CP_RB1_WPTR, ring->wptr); - /* set the rb base addr, this causes an internal reset of ALL rings */ - for (i = 0; i < 3; ++i) { - ring = &rdev->ring[ridx[i]]; - WREG32(cp_rb_base[i], ring->gpu_addr >> 8); - } + /* set the wb address wether it's enabled or not */ + WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC); + WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFF); - for (i = 0; i < 3; ++i) { - /* Initialize the ring buffer's read and write pointers */ - ring = &rdev->ring[ridx[i]]; - WREG32_P(cp_rb_cntl[i], RB_RPTR_WR_ENA, ~RB_RPTR_WR_ENA); + mdelay(1); + WREG32(CP_RB1_CNTL, tmp); - ring->rptr = ring->wptr = 0; - WREG32(ring->rptr_reg, ring->rptr); - WREG32(ring->wptr_reg, ring->wptr); + WREG32(CP_RB1_BASE, ring->gpu_addr >> 8); - mdelay(1); - WREG32_P(cp_rb_cntl[i], 0, ~RB_RPTR_WR_ENA); - } + ring->rptr = RREG32(CP_RB1_RPTR); + + /* ring2 - compute only */ + /* Set ring buffer size */ + ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; + rb_bufsz = drm_order(ring->ring_size / 8); + tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; +#ifdef __BIG_ENDIAN + tmp |= BUF_SWAP_32BIT; +#endif + WREG32(CP_RB2_CNTL, tmp); + + /* Initialize the ring buffer's read and write pointers */ + WREG32(CP_RB2_CNTL, tmp | RB_RPTR_WR_ENA); + ring->wptr = 0; + WREG32(CP_RB2_WPTR, ring->wptr); + + /* set the wb address wether it's enabled or not */ + WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC); + WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFF); + + mdelay(1); + WREG32(CP_RB2_CNTL, tmp); + + WREG32(CP_RB2_BASE, ring->gpu_addr >> 8); + + ring->rptr = RREG32(CP_RB2_RPTR); /* start the rings */ cayman_cp_start(rdev); @@ -1122,14 +1132,6 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev) RREG32(GRBM_STATUS_SE1)); dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", RREG32(SRBM_STATUS)); - dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", - RREG32(CP_STALLED_STAT1)); - dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", - RREG32(CP_STALLED_STAT2)); - dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", - RREG32(CP_BUSY_STAT)); - dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", - RREG32(CP_STAT)); dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_ADDR 0x%08X\n", RREG32(0x14F8)); dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_STATUS 0x%08X\n", @@ -1178,14 +1180,6 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev) RREG32(GRBM_STATUS_SE1)); dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", RREG32(SRBM_STATUS)); - dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", - RREG32(CP_STALLED_STAT1)); - dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", - RREG32(CP_STALLED_STAT2)); - dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", - RREG32(CP_BUSY_STAT)); - dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", - RREG32(CP_STAT)); evergreen_mc_resume(rdev, &save); return 0; } @@ -1297,17 +1291,17 @@ static int cayman_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_ib_pool_init(rdev); - if (r) { - dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + r = radeon_ib_pool_start(rdev); + if (r) return r; - } - r = radeon_vm_manager_init(rdev); - if (r) { - dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); + r = radeon_ib_ring_tests(rdev); + if (r) + return r; + + r = radeon_vm_manager_start(rdev); + if (r) return r; - } r = r600_audio_init(rdev); if (r) @@ -1340,6 +1334,10 @@ int cayman_resume(struct radeon_device *rdev) int cayman_suspend(struct radeon_device *rdev) { r600_audio_fini(rdev); + /* FIXME: we should wait for ring to be empty */ + radeon_ib_pool_suspend(rdev); + radeon_vm_manager_suspend(rdev); + r600_blit_suspend(rdev); cayman_cp_enable(rdev, false); rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; evergreen_irq_suspend(rdev); @@ -1415,7 +1413,17 @@ int cayman_init(struct radeon_device *rdev) if (r) return r; + r = radeon_ib_pool_init(rdev); rdev->accel_working = true; + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + rdev->accel_working = false; + } + r = radeon_vm_manager_init(rdev); + if (r) { + dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); + } + r = cayman_startup(rdev); if (r) { dev_err(rdev->dev, "disabling GPU acceleration\n"); @@ -1424,7 +1432,7 @@ int cayman_init(struct radeon_device *rdev) if (rdev->flags & RADEON_IS_IGP) si_rlc_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_vm_manager_fini(rdev); radeon_irq_kms_fini(rdev); cayman_pcie_gart_fini(rdev); @@ -1455,7 +1463,7 @@ void cayman_fini(struct radeon_device *rdev) si_rlc_fini(rdev); radeon_wb_fini(rdev); radeon_vm_manager_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_irq_kms_fini(rdev); cayman_pcie_gart_fini(rdev); r600_vram_scratch_fini(rdev); diff --git a/trunk/drivers/gpu/drm/radeon/nid.h b/trunk/drivers/gpu/drm/radeon/nid.h index 870db340d377..a0b98066e207 100644 --- a/trunk/drivers/gpu/drm/radeon/nid.h +++ b/trunk/drivers/gpu/drm/radeon/nid.h @@ -236,10 +236,6 @@ #define CP_SEM_WAIT_TIMER 0x85BC #define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8 #define CP_COHER_CNTL2 0x85E8 -#define CP_STALLED_STAT1 0x8674 -#define CP_STALLED_STAT2 0x8678 -#define CP_BUSY_STAT 0x867C -#define CP_STAT 0x8680 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) #define CP_PFP_HALT (1 << 26) diff --git a/trunk/drivers/gpu/drm/radeon/r100.c b/trunk/drivers/gpu/drm/radeon/r100.c index 8acb34fd3fd5..fb44e7e49083 100644 --- a/trunk/drivers/gpu/drm/radeon/r100.c +++ b/trunk/drivers/gpu/drm/radeon/r100.c @@ -65,19 +65,6 @@ MODULE_FIRMWARE(FIRMWARE_R520); #include "r100_track.h" -/* This files gather functions specifics to: - * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 - * and others in some cases. - */ - -/** - * r100_wait_for_vblank - vblank wait asic callback. - * - * @rdev: radeon_device pointer - * @crtc: crtc to wait for vblank on - * - * Wait for vblank on the requested crtc (r1xx-r4xx). - */ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; @@ -112,49 +99,128 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) } } -/** - * r100_pre_page_flip - pre-pageflip callback. - * - * @rdev: radeon_device pointer - * @crtc: crtc to prepare for pageflip on - * - * Pre-pageflip callback (r1xx-r4xx). - * Enables the pageflip irq (vblank irq). +/* This files gather functions specifics to: + * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ + +int r100_reloc_pitch_offset(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + unsigned idx, + unsigned reg) +{ + int r; + u32 tile_flags = 0; + u32 tmp; + struct radeon_cs_reloc *reloc; + u32 value; + + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for ib[%d]=0x%04X\n", + idx, reg); + r100_cs_dump_packet(p, pkt); + return r; + } + + value = radeon_get_ib_value(p, idx); + tmp = value & 0x003fffff; + tmp += (((u32)reloc->lobj.gpu_offset) >> 10); + + if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + tile_flags |= RADEON_DST_TILE_MACRO; + if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { + if (reg == RADEON_SRC_PITCH_OFFSET) { + DRM_ERROR("Cannot src blit from microtiled surface\n"); + r100_cs_dump_packet(p, pkt); + return -EINVAL; + } + tile_flags |= RADEON_DST_TILE_MICRO; + } + + tmp |= tile_flags; + p->ib.ptr[idx] = (value & 0x3fc00000) | tmp; + } else + p->ib.ptr[idx] = (value & 0xffc00000) | tmp; + return 0; +} + +int r100_packet3_load_vbpntr(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + int idx) +{ + unsigned c, i; + struct radeon_cs_reloc *reloc; + struct r100_cs_track *track; + int r = 0; + volatile uint32_t *ib; + u32 idx_value; + + ib = p->ib.ptr; + track = (struct r100_cs_track *)p->track; + c = radeon_get_ib_value(p, idx++) & 0x1F; + if (c > 16) { + DRM_ERROR("Only 16 vertex buffers are allowed %d\n", + pkt->opcode); + r100_cs_dump_packet(p, pkt); + return -EINVAL; + } + track->num_arrays = c; + for (i = 0; i < (c - 1); i+=2, idx+=3) { + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for packet3 %d\n", + pkt->opcode); + r100_cs_dump_packet(p, pkt); + return r; + } + idx_value = radeon_get_ib_value(p, idx); + ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); + + track->arrays[i + 0].esize = idx_value >> 8; + track->arrays[i + 0].robj = reloc->robj; + track->arrays[i + 0].esize &= 0x7F; + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for packet3 %d\n", + pkt->opcode); + r100_cs_dump_packet(p, pkt); + return r; + } + ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset); + track->arrays[i + 1].robj = reloc->robj; + track->arrays[i + 1].esize = idx_value >> 24; + track->arrays[i + 1].esize &= 0x7F; + } + if (c & 1) { + r = r100_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("No reloc for packet3 %d\n", + pkt->opcode); + r100_cs_dump_packet(p, pkt); + return r; + } + idx_value = radeon_get_ib_value(p, idx); + ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); + track->arrays[i + 0].robj = reloc->robj; + track->arrays[i + 0].esize = idx_value >> 8; + track->arrays[i + 0].esize &= 0x7F; + } + return r; +} + void r100_pre_page_flip(struct radeon_device *rdev, int crtc) { /* enable the pflip int */ radeon_irq_kms_pflip_irq_get(rdev, crtc); } -/** - * r100_post_page_flip - pos-pageflip callback. - * - * @rdev: radeon_device pointer - * @crtc: crtc to cleanup pageflip on - * - * Post-pageflip callback (r1xx-r4xx). - * Disables the pageflip irq (vblank irq). - */ void r100_post_page_flip(struct radeon_device *rdev, int crtc) { /* disable the pflip int */ radeon_irq_kms_pflip_irq_put(rdev, crtc); } -/** - * r100_page_flip - pageflip callback. - * - * @rdev: radeon_device pointer - * @crtc_id: crtc to cleanup pageflip on - * @crtc_base: new address of the crtc (GPU MC address) - * - * Does the actual pageflip (r1xx-r4xx). - * During vblank we take the crtc lock and wait for the update_pending - * bit to go high, when it does, we release the lock, and allow the - * double buffered update to take place. - * Returns the current update pending status. - */ u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; @@ -181,15 +247,6 @@ u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET; } -/** - * r100_pm_get_dynpm_state - look up dynpm power state callback. - * - * @rdev: radeon_device pointer - * - * Look up the optimal power state based on the - * current state of the GPU (r1xx-r5xx). - * Used for dynpm only. - */ void r100_pm_get_dynpm_state(struct radeon_device *rdev) { int i; @@ -272,15 +329,6 @@ void r100_pm_get_dynpm_state(struct radeon_device *rdev) pcie_lanes); } -/** - * r100_pm_init_profile - Initialize power profiles callback. - * - * @rdev: radeon_device pointer - * - * Initialize the power states used in profile mode - * (r1xx-r3xx). - * Used for profile mode only. - */ void r100_pm_init_profile(struct radeon_device *rdev) { /* default */ @@ -320,14 +368,6 @@ void r100_pm_init_profile(struct radeon_device *rdev) rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; } -/** - * r100_pm_misc - set additional pm hw parameters callback. - * - * @rdev: radeon_device pointer - * - * Set non-clock parameters associated with a power state - * (voltage, pcie lanes, etc.) (r1xx-r4xx). - */ void r100_pm_misc(struct radeon_device *rdev) { int requested_index = rdev->pm.requested_power_state_index; @@ -419,13 +459,6 @@ void r100_pm_misc(struct radeon_device *rdev) } } -/** - * r100_pm_prepare - pre-power state change callback. - * - * @rdev: radeon_device pointer - * - * Prepare for a power state change (r1xx-r4xx). - */ void r100_pm_prepare(struct radeon_device *rdev) { struct drm_device *ddev = rdev->ddev; @@ -450,13 +483,6 @@ void r100_pm_prepare(struct radeon_device *rdev) } } -/** - * r100_pm_finish - post-power state change callback. - * - * @rdev: radeon_device pointer - * - * Clean up after a power state change (r1xx-r4xx). - */ void r100_pm_finish(struct radeon_device *rdev) { struct drm_device *ddev = rdev->ddev; @@ -481,14 +507,6 @@ void r100_pm_finish(struct radeon_device *rdev) } } -/** - * r100_gui_idle - gui idle callback. - * - * @rdev: radeon_device pointer - * - * Check of the GUI (2D/3D engines) are idle (r1xx-r5xx). - * Returns true if idle, false if not. - */ bool r100_gui_idle(struct radeon_device *rdev) { if (RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE) @@ -498,15 +516,6 @@ bool r100_gui_idle(struct radeon_device *rdev) } /* hpd for digital panel detect/disconnect */ -/** - * r100_hpd_sense - hpd sense callback. - * - * @rdev: radeon_device pointer - * @hpd: hpd (hotplug detect) pin - * - * Checks if a digital monitor is connected (r1xx-r4xx). - * Returns true if connected, false if not connected. - */ bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) { bool connected = false; @@ -526,14 +535,6 @@ bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) return connected; } -/** - * r100_hpd_set_polarity - hpd set polarity callback. - * - * @rdev: radeon_device pointer - * @hpd: hpd (hotplug detect) pin - * - * Set the polarity of the hpd pin (r1xx-r4xx). - */ void r100_hpd_set_polarity(struct radeon_device *rdev, enum radeon_hpd_id hpd) { @@ -562,47 +563,47 @@ void r100_hpd_set_polarity(struct radeon_device *rdev, } } -/** - * r100_hpd_init - hpd setup callback. - * - * @rdev: radeon_device pointer - * - * Setup the hpd pins used by the card (r1xx-r4xx). - * Set the polarity, and enable the hpd interrupts. - */ void r100_hpd_init(struct radeon_device *rdev) { struct drm_device *dev = rdev->ddev; struct drm_connector *connector; - unsigned enable = 0; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); - enable |= 1 << radeon_connector->hpd.hpd; + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + rdev->irq.hpd[0] = true; + break; + case RADEON_HPD_2: + rdev->irq.hpd[1] = true; + break; + default: + break; + } radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); } - radeon_irq_kms_enable_hpd(rdev, enable); + if (rdev->irq.installed) + r100_irq_set(rdev); } -/** - * r100_hpd_fini - hpd tear down callback. - * - * @rdev: radeon_device pointer - * - * Tear down the hpd pins used by the card (r1xx-r4xx). - * Disable the hpd interrupts. - */ void r100_hpd_fini(struct radeon_device *rdev) { struct drm_device *dev = rdev->ddev; struct drm_connector *connector; - unsigned disable = 0; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); - disable |= 1 << radeon_connector->hpd.hpd; + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + rdev->irq.hpd[0] = false; + break; + case RADEON_HPD_2: + rdev->irq.hpd[1] = false; + break; + default: + break; + } } - radeon_irq_kms_disable_hpd(rdev, disable); } /* @@ -634,6 +635,15 @@ int r100_pci_gart_init(struct radeon_device *rdev) return radeon_gart_table_ram_alloc(rdev); } +/* required on r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ +void r100_enable_bm(struct radeon_device *rdev) +{ + uint32_t tmp; + /* Enable bus mastering */ + tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; + WREG32(RADEON_BUS_CNTL, tmp); +} + int r100_pci_gart_enable(struct radeon_device *rdev) { uint32_t tmp; @@ -695,18 +705,18 @@ int r100_irq_set(struct radeon_device *rdev) WREG32(R_000040_GEN_INT_CNTL, 0); return -EINVAL; } - if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { + if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { tmp |= RADEON_SW_INT_ENABLE; } if (rdev->irq.gui_idle) { tmp |= RADEON_GUI_IDLE_MASK; } if (rdev->irq.crtc_vblank_int[0] || - atomic_read(&rdev->irq.pflip[0])) { + rdev->irq.pflip[0]) { tmp |= RADEON_CRTC_VBLANK_MASK; } if (rdev->irq.crtc_vblank_int[1] || - atomic_read(&rdev->irq.pflip[1])) { + rdev->irq.pflip[1]) { tmp |= RADEON_CRTC2_VBLANK_MASK; } if (rdev->irq.hpd[0]) { @@ -772,6 +782,7 @@ int r100_irq_process(struct radeon_device *rdev) /* gui idle interrupt */ if (status & RADEON_GUI_IDLE_STAT) { rdev->irq.gui_idle_acked = true; + rdev->pm.gui_idle = true; wake_up(&rdev->irq.idle_queue); } /* Vertical blank interrupts */ @@ -781,7 +792,7 @@ int r100_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[0])) + if (rdev->irq.pflip[0]) radeon_crtc_handle_flip(rdev, 0); } if (status & RADEON_CRTC2_VBLANK_STAT) { @@ -790,7 +801,7 @@ int r100_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[1])) + if (rdev->irq.pflip[1]) radeon_crtc_handle_flip(rdev, 1); } if (status & RADEON_FP_DETECT_STAT) { @@ -872,7 +883,7 @@ int r100_copy_blit(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct radeon_fence **fence) + struct radeon_fence *fence) { struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; uint32_t cur_pages; @@ -936,7 +947,7 @@ int r100_copy_blit(struct radeon_device *rdev, RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE); if (fence) { - r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX); + r = radeon_fence_emit(rdev, fence); } radeon_ring_unlock_commit(rdev, ring); return r; @@ -1181,14 +1192,6 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) } ring->ready = true; radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); - - if (radeon_ring_supports_scratch_reg(rdev, ring)) { - r = radeon_scratch_get(rdev, &ring->rptr_save_reg); - if (r) { - DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r); - ring->rptr_save_reg = 0; - } - } return 0; } @@ -1199,7 +1202,6 @@ void r100_cp_fini(struct radeon_device *rdev) } /* Disable ring */ r100_cp_disable(rdev); - radeon_scratch_free(rdev, rdev->ring[RADEON_RING_TYPE_GFX_INDEX].rptr_save_reg); radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); DRM_INFO("radeon: cp finalized\n"); } @@ -1221,144 +1223,38 @@ void r100_cp_disable(struct radeon_device *rdev) /* * CS functions */ -int r100_reloc_pitch_offset(struct radeon_cs_parser *p, - struct radeon_cs_packet *pkt, - unsigned idx, - unsigned reg) +int r100_cs_parse_packet0(struct radeon_cs_parser *p, + struct radeon_cs_packet *pkt, + const unsigned *auth, unsigned n, + radeon_packet0_check_t check) { + unsigned reg; + unsigned i, j, m; + unsigned idx; int r; - u32 tile_flags = 0; - u32 tmp; - struct radeon_cs_reloc *reloc; - u32 value; - r = r100_cs_packet_next_reloc(p, &reloc); - if (r) { - DRM_ERROR("No reloc for ib[%d]=0x%04X\n", - idx, reg); - r100_cs_dump_packet(p, pkt); - return r; + idx = pkt->idx + 1; + reg = pkt->reg; + /* Check that register fall into register range + * determined by the number of entry (n) in the + * safe register bitmap. + */ + if (pkt->one_reg_wr) { + if ((reg >> 7) > n) { + return -EINVAL; + } + } else { + if (((reg + (pkt->count << 2)) >> 7) > n) { + return -EINVAL; + } } - - value = radeon_get_ib_value(p, idx); - tmp = value & 0x003fffff; - tmp += (((u32)reloc->lobj.gpu_offset) >> 10); - - if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { - if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) - tile_flags |= RADEON_DST_TILE_MACRO; - if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { - if (reg == RADEON_SRC_PITCH_OFFSET) { - DRM_ERROR("Cannot src blit from microtiled surface\n"); - r100_cs_dump_packet(p, pkt); - return -EINVAL; - } - tile_flags |= RADEON_DST_TILE_MICRO; - } - - tmp |= tile_flags; - p->ib.ptr[idx] = (value & 0x3fc00000) | tmp; - } else - p->ib.ptr[idx] = (value & 0xffc00000) | tmp; - return 0; -} - -int r100_packet3_load_vbpntr(struct radeon_cs_parser *p, - struct radeon_cs_packet *pkt, - int idx) -{ - unsigned c, i; - struct radeon_cs_reloc *reloc; - struct r100_cs_track *track; - int r = 0; - volatile uint32_t *ib; - u32 idx_value; - - ib = p->ib.ptr; - track = (struct r100_cs_track *)p->track; - c = radeon_get_ib_value(p, idx++) & 0x1F; - if (c > 16) { - DRM_ERROR("Only 16 vertex buffers are allowed %d\n", - pkt->opcode); - r100_cs_dump_packet(p, pkt); - return -EINVAL; - } - track->num_arrays = c; - for (i = 0; i < (c - 1); i+=2, idx+=3) { - r = r100_cs_packet_next_reloc(p, &reloc); - if (r) { - DRM_ERROR("No reloc for packet3 %d\n", - pkt->opcode); - r100_cs_dump_packet(p, pkt); - return r; - } - idx_value = radeon_get_ib_value(p, idx); - ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); - - track->arrays[i + 0].esize = idx_value >> 8; - track->arrays[i + 0].robj = reloc->robj; - track->arrays[i + 0].esize &= 0x7F; - r = r100_cs_packet_next_reloc(p, &reloc); - if (r) { - DRM_ERROR("No reloc for packet3 %d\n", - pkt->opcode); - r100_cs_dump_packet(p, pkt); - return r; - } - ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset); - track->arrays[i + 1].robj = reloc->robj; - track->arrays[i + 1].esize = idx_value >> 24; - track->arrays[i + 1].esize &= 0x7F; - } - if (c & 1) { - r = r100_cs_packet_next_reloc(p, &reloc); - if (r) { - DRM_ERROR("No reloc for packet3 %d\n", - pkt->opcode); - r100_cs_dump_packet(p, pkt); - return r; - } - idx_value = radeon_get_ib_value(p, idx); - ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); - track->arrays[i + 0].robj = reloc->robj; - track->arrays[i + 0].esize = idx_value >> 8; - track->arrays[i + 0].esize &= 0x7F; - } - return r; -} - -int r100_cs_parse_packet0(struct radeon_cs_parser *p, - struct radeon_cs_packet *pkt, - const unsigned *auth, unsigned n, - radeon_packet0_check_t check) -{ - unsigned reg; - unsigned i, j, m; - unsigned idx; - int r; - - idx = pkt->idx + 1; - reg = pkt->reg; - /* Check that register fall into register range - * determined by the number of entry (n) in the - * safe register bitmap. - */ - if (pkt->one_reg_wr) { - if ((reg >> 7) > n) { - return -EINVAL; - } - } else { - if (((reg + (pkt->count << 2)) >> 7) > n) { - return -EINVAL; - } - } - for (i = 0; i <= pkt->count; i++, idx++) { - j = (reg >> 7); - m = 1 << ((reg >> 2) & 31); - if (auth[j] & m) { - r = check(p, pkt, idx, reg); - if (r) { - return r; + for (i = 0; i <= pkt->count; i++, idx++) { + j = (reg >> 7); + m = 1 << ((reg >> 2) & 31); + if (auth[j] & m) { + r = check(p, pkt, idx, reg); + if (r) { + return r; } } if (pkt->one_reg_wr) { @@ -2152,470 +2048,97 @@ int r100_cs_parse(struct radeon_cs_parser *p) return 0; } -static void r100_cs_track_texture_print(struct r100_cs_track_texture *t) -{ - DRM_ERROR("pitch %d\n", t->pitch); - DRM_ERROR("use_pitch %d\n", t->use_pitch); - DRM_ERROR("width %d\n", t->width); - DRM_ERROR("width_11 %d\n", t->width_11); - DRM_ERROR("height %d\n", t->height); - DRM_ERROR("height_11 %d\n", t->height_11); - DRM_ERROR("num levels %d\n", t->num_levels); - DRM_ERROR("depth %d\n", t->txdepth); - DRM_ERROR("bpp %d\n", t->cpp); - DRM_ERROR("coordinate type %d\n", t->tex_coord_type); - DRM_ERROR("width round to power of 2 %d\n", t->roundup_w); - DRM_ERROR("height round to power of 2 %d\n", t->roundup_h); - DRM_ERROR("compress format %d\n", t->compress_format); -} -static int r100_track_compress_size(int compress_format, int w, int h) +/* + * Global GPU functions + */ +void r100_errata(struct radeon_device *rdev) { - int block_width, block_height, block_bytes; - int wblocks, hblocks; - int min_wblocks; - int sz; + rdev->pll_errata = 0; - block_width = 4; - block_height = 4; + if (rdev->family == CHIP_RV200 || rdev->family == CHIP_RS200) { + rdev->pll_errata |= CHIP_ERRATA_PLL_DUMMYREADS; + } - switch (compress_format) { - case R100_TRACK_COMP_DXT1: - block_bytes = 8; - min_wblocks = 4; - break; - default: - case R100_TRACK_COMP_DXT35: - block_bytes = 16; - min_wblocks = 2; - break; + if (rdev->family == CHIP_RV100 || + rdev->family == CHIP_RS100 || + rdev->family == CHIP_RS200) { + rdev->pll_errata |= CHIP_ERRATA_PLL_DELAY; } +} - hblocks = (h + block_height - 1) / block_height; - wblocks = (w + block_width - 1) / block_width; - if (wblocks < min_wblocks) - wblocks = min_wblocks; - sz = wblocks * hblocks * block_bytes; - return sz; +/* Wait for vertical sync on primary CRTC */ +void r100_gpu_wait_for_vsync(struct radeon_device *rdev) +{ + uint32_t crtc_gen_cntl, tmp; + int i; + + crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); + if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) || + !(crtc_gen_cntl & RADEON_CRTC_EN)) { + return; + } + /* Clear the CRTC_VBLANK_SAVE bit */ + WREG32(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR); + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = RREG32(RADEON_CRTC_STATUS); + if (tmp & RADEON_CRTC_VBLANK_SAVE) { + return; + } + DRM_UDELAY(1); + } } -static int r100_cs_track_cube(struct radeon_device *rdev, - struct r100_cs_track *track, unsigned idx) +/* Wait for vertical sync on secondary CRTC */ +void r100_gpu_wait_for_vsync2(struct radeon_device *rdev) { - unsigned face, w, h; - struct radeon_bo *cube_robj; - unsigned long size; - unsigned compress_format = track->textures[idx].compress_format; + uint32_t crtc2_gen_cntl, tmp; + int i; - for (face = 0; face < 5; face++) { - cube_robj = track->textures[idx].cube_info[face].robj; - w = track->textures[idx].cube_info[face].width; - h = track->textures[idx].cube_info[face].height; + crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) || + !(crtc2_gen_cntl & RADEON_CRTC2_EN)) + return; - if (compress_format) { - size = r100_track_compress_size(compress_format, w, h); - } else - size = w * h; - size *= track->textures[idx].cpp; + /* Clear the CRTC_VBLANK_SAVE bit */ + WREG32(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR); + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = RREG32(RADEON_CRTC2_STATUS); + if (tmp & RADEON_CRTC2_VBLANK_SAVE) { + return; + } + DRM_UDELAY(1); + } +} - size += track->textures[idx].cube_info[face].offset; +int r100_rbbm_fifo_wait_for_entry(struct radeon_device *rdev, unsigned n) +{ + unsigned i; + uint32_t tmp; - if (size > radeon_bo_size(cube_robj)) { - DRM_ERROR("Cube texture offset greater than object size %lu %lu\n", - size, radeon_bo_size(cube_robj)); - r100_cs_track_texture_print(&track->textures[idx]); - return -1; + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK; + if (tmp >= n) { + return 0; } + DRM_UDELAY(1); } - return 0; + return -1; } -static int r100_cs_track_texture_check(struct radeon_device *rdev, - struct r100_cs_track *track) +int r100_gui_wait_for_idle(struct radeon_device *rdev) { - struct radeon_bo *robj; - unsigned long size; - unsigned u, i, w, h, d; - int ret; + unsigned i; + uint32_t tmp; - for (u = 0; u < track->num_texture; u++) { - if (!track->textures[u].enabled) - continue; - if (track->textures[u].lookup_disable) - continue; - robj = track->textures[u].robj; - if (robj == NULL) { - DRM_ERROR("No texture bound to unit %u\n", u); - return -EINVAL; - } - size = 0; - for (i = 0; i <= track->textures[u].num_levels; i++) { - if (track->textures[u].use_pitch) { - if (rdev->family < CHIP_R300) - w = (track->textures[u].pitch / track->textures[u].cpp) / (1 << i); - else - w = track->textures[u].pitch / (1 << i); - } else { - w = track->textures[u].width; - if (rdev->family >= CHIP_RV515) - w |= track->textures[u].width_11; - w = w / (1 << i); - if (track->textures[u].roundup_w) - w = roundup_pow_of_two(w); - } - h = track->textures[u].height; - if (rdev->family >= CHIP_RV515) - h |= track->textures[u].height_11; - h = h / (1 << i); - if (track->textures[u].roundup_h) - h = roundup_pow_of_two(h); - if (track->textures[u].tex_coord_type == 1) { - d = (1 << track->textures[u].txdepth) / (1 << i); - if (!d) - d = 1; - } else { - d = 1; - } - if (track->textures[u].compress_format) { - - size += r100_track_compress_size(track->textures[u].compress_format, w, h) * d; - /* compressed textures are block based */ - } else - size += w * h * d; - } - size *= track->textures[u].cpp; - - switch (track->textures[u].tex_coord_type) { - case 0: - case 1: - break; - case 2: - if (track->separate_cube) { - ret = r100_cs_track_cube(rdev, track, u); - if (ret) - return ret; - } else - size *= 6; - break; - default: - DRM_ERROR("Invalid texture coordinate type %u for unit " - "%u\n", track->textures[u].tex_coord_type, u); - return -EINVAL; - } - if (size > radeon_bo_size(robj)) { - DRM_ERROR("Texture of unit %u needs %lu bytes but is " - "%lu\n", u, size, radeon_bo_size(robj)); - r100_cs_track_texture_print(&track->textures[u]); - return -EINVAL; - } - } - return 0; -} - -int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) -{ - unsigned i; - unsigned long size; - unsigned prim_walk; - unsigned nverts; - unsigned num_cb = track->cb_dirty ? track->num_cb : 0; - - if (num_cb && !track->zb_cb_clear && !track->color_channel_mask && - !track->blend_read_enable) - num_cb = 0; - - for (i = 0; i < num_cb; i++) { - if (track->cb[i].robj == NULL) { - DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); - return -EINVAL; - } - size = track->cb[i].pitch * track->cb[i].cpp * track->maxy; - size += track->cb[i].offset; - if (size > radeon_bo_size(track->cb[i].robj)) { - DRM_ERROR("[drm] Buffer too small for color buffer %d " - "(need %lu have %lu) !\n", i, size, - radeon_bo_size(track->cb[i].robj)); - DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n", - i, track->cb[i].pitch, track->cb[i].cpp, - track->cb[i].offset, track->maxy); - return -EINVAL; - } - } - track->cb_dirty = false; - - if (track->zb_dirty && track->z_enabled) { - if (track->zb.robj == NULL) { - DRM_ERROR("[drm] No buffer for z buffer !\n"); - return -EINVAL; - } - size = track->zb.pitch * track->zb.cpp * track->maxy; - size += track->zb.offset; - if (size > radeon_bo_size(track->zb.robj)) { - DRM_ERROR("[drm] Buffer too small for z buffer " - "(need %lu have %lu) !\n", size, - radeon_bo_size(track->zb.robj)); - DRM_ERROR("[drm] zbuffer (%u %u %u %u)\n", - track->zb.pitch, track->zb.cpp, - track->zb.offset, track->maxy); - return -EINVAL; - } - } - track->zb_dirty = false; - - if (track->aa_dirty && track->aaresolve) { - if (track->aa.robj == NULL) { - DRM_ERROR("[drm] No buffer for AA resolve buffer %d !\n", i); - return -EINVAL; - } - /* I believe the format comes from colorbuffer0. */ - size = track->aa.pitch * track->cb[0].cpp * track->maxy; - size += track->aa.offset; - if (size > radeon_bo_size(track->aa.robj)) { - DRM_ERROR("[drm] Buffer too small for AA resolve buffer %d " - "(need %lu have %lu) !\n", i, size, - radeon_bo_size(track->aa.robj)); - DRM_ERROR("[drm] AA resolve buffer %d (%u %u %u %u)\n", - i, track->aa.pitch, track->cb[0].cpp, - track->aa.offset, track->maxy); - return -EINVAL; - } - } - track->aa_dirty = false; - - prim_walk = (track->vap_vf_cntl >> 4) & 0x3; - if (track->vap_vf_cntl & (1 << 14)) { - nverts = track->vap_alt_nverts; - } else { - nverts = (track->vap_vf_cntl >> 16) & 0xFFFF; - } - switch (prim_walk) { - case 1: - for (i = 0; i < track->num_arrays; i++) { - size = track->arrays[i].esize * track->max_indx * 4; - if (track->arrays[i].robj == NULL) { - DRM_ERROR("(PW %u) Vertex array %u no buffer " - "bound\n", prim_walk, i); - return -EINVAL; - } - if (size > radeon_bo_size(track->arrays[i].robj)) { - dev_err(rdev->dev, "(PW %u) Vertex array %u " - "need %lu dwords have %lu dwords\n", - prim_walk, i, size >> 2, - radeon_bo_size(track->arrays[i].robj) - >> 2); - DRM_ERROR("Max indices %u\n", track->max_indx); - return -EINVAL; - } - } - break; - case 2: - for (i = 0; i < track->num_arrays; i++) { - size = track->arrays[i].esize * (nverts - 1) * 4; - if (track->arrays[i].robj == NULL) { - DRM_ERROR("(PW %u) Vertex array %u no buffer " - "bound\n", prim_walk, i); - return -EINVAL; - } - if (size > radeon_bo_size(track->arrays[i].robj)) { - dev_err(rdev->dev, "(PW %u) Vertex array %u " - "need %lu dwords have %lu dwords\n", - prim_walk, i, size >> 2, - radeon_bo_size(track->arrays[i].robj) - >> 2); - return -EINVAL; - } - } - break; - case 3: - size = track->vtx_size * nverts; - if (size != track->immd_dwords) { - DRM_ERROR("IMMD draw %u dwors but needs %lu dwords\n", - track->immd_dwords, size); - DRM_ERROR("VAP_VF_CNTL.NUM_VERTICES %u, VTX_SIZE %u\n", - nverts, track->vtx_size); - return -EINVAL; - } - break; - default: - DRM_ERROR("[drm] Invalid primitive walk %d for VAP_VF_CNTL\n", - prim_walk); - return -EINVAL; - } - - if (track->tex_dirty) { - track->tex_dirty = false; - return r100_cs_track_texture_check(rdev, track); - } - return 0; -} - -void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track) -{ - unsigned i, face; - - track->cb_dirty = true; - track->zb_dirty = true; - track->tex_dirty = true; - track->aa_dirty = true; - - if (rdev->family < CHIP_R300) { - track->num_cb = 1; - if (rdev->family <= CHIP_RS200) - track->num_texture = 3; - else - track->num_texture = 6; - track->maxy = 2048; - track->separate_cube = 1; - } else { - track->num_cb = 4; - track->num_texture = 16; - track->maxy = 4096; - track->separate_cube = 0; - track->aaresolve = false; - track->aa.robj = NULL; - } - - for (i = 0; i < track->num_cb; i++) { - track->cb[i].robj = NULL; - track->cb[i].pitch = 8192; - track->cb[i].cpp = 16; - track->cb[i].offset = 0; - } - track->z_enabled = true; - track->zb.robj = NULL; - track->zb.pitch = 8192; - track->zb.cpp = 4; - track->zb.offset = 0; - track->vtx_size = 0x7F; - track->immd_dwords = 0xFFFFFFFFUL; - track->num_arrays = 11; - track->max_indx = 0x00FFFFFFUL; - for (i = 0; i < track->num_arrays; i++) { - track->arrays[i].robj = NULL; - track->arrays[i].esize = 0x7F; - } - for (i = 0; i < track->num_texture; i++) { - track->textures[i].compress_format = R100_TRACK_COMP_NONE; - track->textures[i].pitch = 16536; - track->textures[i].width = 16536; - track->textures[i].height = 16536; - track->textures[i].width_11 = 1 << 11; - track->textures[i].height_11 = 1 << 11; - track->textures[i].num_levels = 12; - if (rdev->family <= CHIP_RS200) { - track->textures[i].tex_coord_type = 0; - track->textures[i].txdepth = 0; - } else { - track->textures[i].txdepth = 16; - track->textures[i].tex_coord_type = 1; - } - track->textures[i].cpp = 64; - track->textures[i].robj = NULL; - /* CS IB emission code makes sure texture unit are disabled */ - track->textures[i].enabled = false; - track->textures[i].lookup_disable = false; - track->textures[i].roundup_w = true; - track->textures[i].roundup_h = true; - if (track->separate_cube) - for (face = 0; face < 5; face++) { - track->textures[i].cube_info[face].robj = NULL; - track->textures[i].cube_info[face].width = 16536; - track->textures[i].cube_info[face].height = 16536; - track->textures[i].cube_info[face].offset = 0; - } - } -} - -/* - * Global GPU functions - */ -void r100_errata(struct radeon_device *rdev) -{ - rdev->pll_errata = 0; - - if (rdev->family == CHIP_RV200 || rdev->family == CHIP_RS200) { - rdev->pll_errata |= CHIP_ERRATA_PLL_DUMMYREADS; - } - - if (rdev->family == CHIP_RV100 || - rdev->family == CHIP_RS100 || - rdev->family == CHIP_RS200) { - rdev->pll_errata |= CHIP_ERRATA_PLL_DELAY; - } -} - -/* Wait for vertical sync on primary CRTC */ -void r100_gpu_wait_for_vsync(struct radeon_device *rdev) -{ - uint32_t crtc_gen_cntl, tmp; - int i; - - crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); - if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) || - !(crtc_gen_cntl & RADEON_CRTC_EN)) { - return; - } - /* Clear the CRTC_VBLANK_SAVE bit */ - WREG32(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR); - for (i = 0; i < rdev->usec_timeout; i++) { - tmp = RREG32(RADEON_CRTC_STATUS); - if (tmp & RADEON_CRTC_VBLANK_SAVE) { - return; - } - DRM_UDELAY(1); - } -} - -/* Wait for vertical sync on secondary CRTC */ -void r100_gpu_wait_for_vsync2(struct radeon_device *rdev) -{ - uint32_t crtc2_gen_cntl, tmp; - int i; - - crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); - if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) || - !(crtc2_gen_cntl & RADEON_CRTC2_EN)) - return; - - /* Clear the CRTC_VBLANK_SAVE bit */ - WREG32(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR); - for (i = 0; i < rdev->usec_timeout; i++) { - tmp = RREG32(RADEON_CRTC2_STATUS); - if (tmp & RADEON_CRTC2_VBLANK_SAVE) { - return; - } - DRM_UDELAY(1); - } -} - -int r100_rbbm_fifo_wait_for_entry(struct radeon_device *rdev, unsigned n) -{ - unsigned i; - uint32_t tmp; - - for (i = 0; i < rdev->usec_timeout; i++) { - tmp = RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK; - if (tmp >= n) { - return 0; - } - DRM_UDELAY(1); - } - return -1; -} - -int r100_gui_wait_for_idle(struct radeon_device *rdev) -{ - unsigned i; - uint32_t tmp; - - if (r100_rbbm_fifo_wait_for_entry(rdev, 64)) { - printk(KERN_WARNING "radeon: wait for empty RBBM fifo failed !" - " Bad things might happen.\n"); - } - for (i = 0; i < rdev->usec_timeout; i++) { - tmp = RREG32(RADEON_RBBM_STATUS); - if (!(tmp & RADEON_RBBM_ACTIVE)) { - return 0; + if (r100_rbbm_fifo_wait_for_entry(rdev, 64)) { + printk(KERN_WARNING "radeon: wait for empty RBBM fifo failed !" + " Bad things might happen.\n"); + } + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = RREG32(RADEON_RBBM_STATUS); + if (!(tmp & RADEON_RBBM_ACTIVE)) { + return 0; } DRM_UDELAY(1); } @@ -2652,15 +2175,6 @@ bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) return radeon_ring_test_lockup(rdev, ring); } -/* required on r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ -void r100_enable_bm(struct radeon_device *rdev) -{ - uint32_t tmp; - /* Enable bus mastering */ - tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; - WREG32(RADEON_BUS_CNTL, tmp); -} - void r100_bm_disable(struct radeon_device *rdev) { u32 tmp; @@ -3547,203 +3061,577 @@ void r100_bandwidth_update(struct radeon_device *rdev) temp_ff.full = tras_ff.full; cur_latency_mclk.full = dfixed_div(temp_ff, mclk_ff); - temp_ff.full = dfixed_const(cur_size); - cur_latency_sclk.full = dfixed_div(temp_ff, sclk_eff_ff); - /* - Find the total latency for the display data. - */ - disp_latency_overhead.full = dfixed_const(8); - disp_latency_overhead.full = dfixed_div(disp_latency_overhead, sclk_ff); - mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full; - mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full; + temp_ff.full = dfixed_const(cur_size); + cur_latency_sclk.full = dfixed_div(temp_ff, sclk_eff_ff); + /* + Find the total latency for the display data. + */ + disp_latency_overhead.full = dfixed_const(8); + disp_latency_overhead.full = dfixed_div(disp_latency_overhead, sclk_ff); + mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full; + mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full; + + if (mc_latency_mclk.full > mc_latency_sclk.full) + disp_latency.full = mc_latency_mclk.full; + else + disp_latency.full = mc_latency_sclk.full; + + /* setup Max GRPH_STOP_REQ default value */ + if (ASIC_IS_RV100(rdev)) + max_stop_req = 0x5c; + else + max_stop_req = 0x7c; + + if (mode1) { + /* CRTC1 + Set GRPH_BUFFER_CNTL register using h/w defined optimal values. + GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] + */ + stop_req = mode1->hdisplay * pixel_bytes1 / 16; + + if (stop_req > max_stop_req) + stop_req = max_stop_req; + + /* + Find the drain rate of the display buffer. + */ + temp_ff.full = dfixed_const((16/pixel_bytes1)); + disp_drain_rate.full = dfixed_div(pix_clk, temp_ff); + + /* + Find the critical point of the display buffer. + */ + crit_point_ff.full = dfixed_mul(disp_drain_rate, disp_latency); + crit_point_ff.full += dfixed_const_half(0); + + critical_point = dfixed_trunc(crit_point_ff); + + if (rdev->disp_priority == 2) { + critical_point = 0; + } + + /* + The critical point should never be above max_stop_req-4. Setting + GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. + */ + if (max_stop_req - critical_point < 4) + critical_point = 0; + + if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) { + /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ + critical_point = 0x10; + } + + temp = RREG32(RADEON_GRPH_BUFFER_CNTL); + temp &= ~(RADEON_GRPH_STOP_REQ_MASK); + temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); + temp &= ~(RADEON_GRPH_START_REQ_MASK); + if ((rdev->family == CHIP_R350) && + (stop_req > 0x15)) { + stop_req -= 0x10; + } + temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); + temp |= RADEON_GRPH_BUFFER_SIZE; + temp &= ~(RADEON_GRPH_CRITICAL_CNTL | + RADEON_GRPH_CRITICAL_AT_SOF | + RADEON_GRPH_STOP_CNTL); + /* + Write the result into the register. + */ + WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | + (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); + +#if 0 + if ((rdev->family == CHIP_RS400) || + (rdev->family == CHIP_RS480)) { + /* attempt to program RS400 disp regs correctly ??? */ + temp = RREG32(RS400_DISP1_REG_CNTL); + temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK | + RS400_DISP1_STOP_REQ_LEVEL_MASK); + WREG32(RS400_DISP1_REQ_CNTL1, (temp | + (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) | + (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); + temp = RREG32(RS400_DMIF_MEM_CNTL1); + temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK | + RS400_DISP1_CRITICAL_POINT_STOP_MASK); + WREG32(RS400_DMIF_MEM_CNTL1, (temp | + (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) | + (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT))); + } +#endif + + DRM_DEBUG_KMS("GRPH_BUFFER_CNTL from to %x\n", + /* (unsigned int)info->SavedReg->grph_buffer_cntl, */ + (unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL)); + } + + if (mode2) { + u32 grph2_cntl; + stop_req = mode2->hdisplay * pixel_bytes2 / 16; + + if (stop_req > max_stop_req) + stop_req = max_stop_req; + + /* + Find the drain rate of the display buffer. + */ + temp_ff.full = dfixed_const((16/pixel_bytes2)); + disp_drain_rate2.full = dfixed_div(pix_clk2, temp_ff); + + grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL); + grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK); + grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); + grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK); + if ((rdev->family == CHIP_R350) && + (stop_req > 0x15)) { + stop_req -= 0x10; + } + grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); + grph2_cntl |= RADEON_GRPH_BUFFER_SIZE; + grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL | + RADEON_GRPH_CRITICAL_AT_SOF | + RADEON_GRPH_STOP_CNTL); + + if ((rdev->family == CHIP_RS100) || + (rdev->family == CHIP_RS200)) + critical_point2 = 0; + else { + temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128; + temp_ff.full = dfixed_const(temp); + temp_ff.full = dfixed_mul(mclk_ff, temp_ff); + if (sclk_ff.full < temp_ff.full) + temp_ff.full = sclk_ff.full; + + read_return_rate.full = temp_ff.full; + + if (mode1) { + temp_ff.full = read_return_rate.full - disp_drain_rate.full; + time_disp1_drop_priority.full = dfixed_div(crit_point_ff, temp_ff); + } else { + time_disp1_drop_priority.full = 0; + } + crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full; + crit_point_ff.full = dfixed_mul(crit_point_ff, disp_drain_rate2); + crit_point_ff.full += dfixed_const_half(0); + + critical_point2 = dfixed_trunc(crit_point_ff); + + if (rdev->disp_priority == 2) { + critical_point2 = 0; + } + + if (max_stop_req - critical_point2 < 4) + critical_point2 = 0; + + } + + if (critical_point2 == 0 && rdev->family == CHIP_R300) { + /* some R300 cards have problem with this set to 0 */ + critical_point2 = 0x10; + } + + WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) | + (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); + + if ((rdev->family == CHIP_RS400) || + (rdev->family == CHIP_RS480)) { +#if 0 + /* attempt to program RS400 disp2 regs correctly ??? */ + temp = RREG32(RS400_DISP2_REQ_CNTL1); + temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK | + RS400_DISP2_STOP_REQ_LEVEL_MASK); + WREG32(RS400_DISP2_REQ_CNTL1, (temp | + (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) | + (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); + temp = RREG32(RS400_DISP2_REQ_CNTL2); + temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK | + RS400_DISP2_CRITICAL_POINT_STOP_MASK); + WREG32(RS400_DISP2_REQ_CNTL2, (temp | + (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) | + (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT))); +#endif + WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC); + WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000); + WREG32(RS400_DMIF_MEM_CNTL1, 0x29CA71DC); + WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC); + } + + DRM_DEBUG_KMS("GRPH2_BUFFER_CNTL from to %x\n", + (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL)); + } +} + +static void r100_cs_track_texture_print(struct r100_cs_track_texture *t) +{ + DRM_ERROR("pitch %d\n", t->pitch); + DRM_ERROR("use_pitch %d\n", t->use_pitch); + DRM_ERROR("width %d\n", t->width); + DRM_ERROR("width_11 %d\n", t->width_11); + DRM_ERROR("height %d\n", t->height); + DRM_ERROR("height_11 %d\n", t->height_11); + DRM_ERROR("num levels %d\n", t->num_levels); + DRM_ERROR("depth %d\n", t->txdepth); + DRM_ERROR("bpp %d\n", t->cpp); + DRM_ERROR("coordinate type %d\n", t->tex_coord_type); + DRM_ERROR("width round to power of 2 %d\n", t->roundup_w); + DRM_ERROR("height round to power of 2 %d\n", t->roundup_h); + DRM_ERROR("compress format %d\n", t->compress_format); +} + +static int r100_track_compress_size(int compress_format, int w, int h) +{ + int block_width, block_height, block_bytes; + int wblocks, hblocks; + int min_wblocks; + int sz; - if (mc_latency_mclk.full > mc_latency_sclk.full) - disp_latency.full = mc_latency_mclk.full; - else - disp_latency.full = mc_latency_sclk.full; + block_width = 4; + block_height = 4; - /* setup Max GRPH_STOP_REQ default value */ - if (ASIC_IS_RV100(rdev)) - max_stop_req = 0x5c; - else - max_stop_req = 0x7c; + switch (compress_format) { + case R100_TRACK_COMP_DXT1: + block_bytes = 8; + min_wblocks = 4; + break; + default: + case R100_TRACK_COMP_DXT35: + block_bytes = 16; + min_wblocks = 2; + break; + } - if (mode1) { - /* CRTC1 - Set GRPH_BUFFER_CNTL register using h/w defined optimal values. - GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] - */ - stop_req = mode1->hdisplay * pixel_bytes1 / 16; + hblocks = (h + block_height - 1) / block_height; + wblocks = (w + block_width - 1) / block_width; + if (wblocks < min_wblocks) + wblocks = min_wblocks; + sz = wblocks * hblocks * block_bytes; + return sz; +} - if (stop_req > max_stop_req) - stop_req = max_stop_req; +static int r100_cs_track_cube(struct radeon_device *rdev, + struct r100_cs_track *track, unsigned idx) +{ + unsigned face, w, h; + struct radeon_bo *cube_robj; + unsigned long size; + unsigned compress_format = track->textures[idx].compress_format; - /* - Find the drain rate of the display buffer. - */ - temp_ff.full = dfixed_const((16/pixel_bytes1)); - disp_drain_rate.full = dfixed_div(pix_clk, temp_ff); + for (face = 0; face < 5; face++) { + cube_robj = track->textures[idx].cube_info[face].robj; + w = track->textures[idx].cube_info[face].width; + h = track->textures[idx].cube_info[face].height; - /* - Find the critical point of the display buffer. - */ - crit_point_ff.full = dfixed_mul(disp_drain_rate, disp_latency); - crit_point_ff.full += dfixed_const_half(0); + if (compress_format) { + size = r100_track_compress_size(compress_format, w, h); + } else + size = w * h; + size *= track->textures[idx].cpp; - critical_point = dfixed_trunc(crit_point_ff); + size += track->textures[idx].cube_info[face].offset; - if (rdev->disp_priority == 2) { - critical_point = 0; + if (size > radeon_bo_size(cube_robj)) { + DRM_ERROR("Cube texture offset greater than object size %lu %lu\n", + size, radeon_bo_size(cube_robj)); + r100_cs_track_texture_print(&track->textures[idx]); + return -1; } + } + return 0; +} - /* - The critical point should never be above max_stop_req-4. Setting - GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. - */ - if (max_stop_req - critical_point < 4) - critical_point = 0; +static int r100_cs_track_texture_check(struct radeon_device *rdev, + struct r100_cs_track *track) +{ + struct radeon_bo *robj; + unsigned long size; + unsigned u, i, w, h, d; + int ret; - if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) { - /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ - critical_point = 0x10; + for (u = 0; u < track->num_texture; u++) { + if (!track->textures[u].enabled) + continue; + if (track->textures[u].lookup_disable) + continue; + robj = track->textures[u].robj; + if (robj == NULL) { + DRM_ERROR("No texture bound to unit %u\n", u); + return -EINVAL; } + size = 0; + for (i = 0; i <= track->textures[u].num_levels; i++) { + if (track->textures[u].use_pitch) { + if (rdev->family < CHIP_R300) + w = (track->textures[u].pitch / track->textures[u].cpp) / (1 << i); + else + w = track->textures[u].pitch / (1 << i); + } else { + w = track->textures[u].width; + if (rdev->family >= CHIP_RV515) + w |= track->textures[u].width_11; + w = w / (1 << i); + if (track->textures[u].roundup_w) + w = roundup_pow_of_two(w); + } + h = track->textures[u].height; + if (rdev->family >= CHIP_RV515) + h |= track->textures[u].height_11; + h = h / (1 << i); + if (track->textures[u].roundup_h) + h = roundup_pow_of_two(h); + if (track->textures[u].tex_coord_type == 1) { + d = (1 << track->textures[u].txdepth) / (1 << i); + if (!d) + d = 1; + } else { + d = 1; + } + if (track->textures[u].compress_format) { - temp = RREG32(RADEON_GRPH_BUFFER_CNTL); - temp &= ~(RADEON_GRPH_STOP_REQ_MASK); - temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); - temp &= ~(RADEON_GRPH_START_REQ_MASK); - if ((rdev->family == CHIP_R350) && - (stop_req > 0x15)) { - stop_req -= 0x10; + size += r100_track_compress_size(track->textures[u].compress_format, w, h) * d; + /* compressed textures are block based */ + } else + size += w * h * d; } - temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); - temp |= RADEON_GRPH_BUFFER_SIZE; - temp &= ~(RADEON_GRPH_CRITICAL_CNTL | - RADEON_GRPH_CRITICAL_AT_SOF | - RADEON_GRPH_STOP_CNTL); - /* - Write the result into the register. - */ - WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | - (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); + size *= track->textures[u].cpp; -#if 0 - if ((rdev->family == CHIP_RS400) || - (rdev->family == CHIP_RS480)) { - /* attempt to program RS400 disp regs correctly ??? */ - temp = RREG32(RS400_DISP1_REG_CNTL); - temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK | - RS400_DISP1_STOP_REQ_LEVEL_MASK); - WREG32(RS400_DISP1_REQ_CNTL1, (temp | - (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) | - (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); - temp = RREG32(RS400_DMIF_MEM_CNTL1); - temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK | - RS400_DISP1_CRITICAL_POINT_STOP_MASK); - WREG32(RS400_DMIF_MEM_CNTL1, (temp | - (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) | - (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT))); + switch (track->textures[u].tex_coord_type) { + case 0: + case 1: + break; + case 2: + if (track->separate_cube) { + ret = r100_cs_track_cube(rdev, track, u); + if (ret) + return ret; + } else + size *= 6; + break; + default: + DRM_ERROR("Invalid texture coordinate type %u for unit " + "%u\n", track->textures[u].tex_coord_type, u); + return -EINVAL; + } + if (size > radeon_bo_size(robj)) { + DRM_ERROR("Texture of unit %u needs %lu bytes but is " + "%lu\n", u, size, radeon_bo_size(robj)); + r100_cs_track_texture_print(&track->textures[u]); + return -EINVAL; } -#endif - - DRM_DEBUG_KMS("GRPH_BUFFER_CNTL from to %x\n", - /* (unsigned int)info->SavedReg->grph_buffer_cntl, */ - (unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL)); } + return 0; +} - if (mode2) { - u32 grph2_cntl; - stop_req = mode2->hdisplay * pixel_bytes2 / 16; - - if (stop_req > max_stop_req) - stop_req = max_stop_req; +int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) +{ + unsigned i; + unsigned long size; + unsigned prim_walk; + unsigned nverts; + unsigned num_cb = track->cb_dirty ? track->num_cb : 0; - /* - Find the drain rate of the display buffer. - */ - temp_ff.full = dfixed_const((16/pixel_bytes2)); - disp_drain_rate2.full = dfixed_div(pix_clk2, temp_ff); + if (num_cb && !track->zb_cb_clear && !track->color_channel_mask && + !track->blend_read_enable) + num_cb = 0; - grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL); - grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK); - grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); - grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK); - if ((rdev->family == CHIP_R350) && - (stop_req > 0x15)) { - stop_req -= 0x10; + for (i = 0; i < num_cb; i++) { + if (track->cb[i].robj == NULL) { + DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); + return -EINVAL; + } + size = track->cb[i].pitch * track->cb[i].cpp * track->maxy; + size += track->cb[i].offset; + if (size > radeon_bo_size(track->cb[i].robj)) { + DRM_ERROR("[drm] Buffer too small for color buffer %d " + "(need %lu have %lu) !\n", i, size, + radeon_bo_size(track->cb[i].robj)); + DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n", + i, track->cb[i].pitch, track->cb[i].cpp, + track->cb[i].offset, track->maxy); + return -EINVAL; } - grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); - grph2_cntl |= RADEON_GRPH_BUFFER_SIZE; - grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL | - RADEON_GRPH_CRITICAL_AT_SOF | - RADEON_GRPH_STOP_CNTL); + } + track->cb_dirty = false; - if ((rdev->family == CHIP_RS100) || - (rdev->family == CHIP_RS200)) - critical_point2 = 0; - else { - temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128; - temp_ff.full = dfixed_const(temp); - temp_ff.full = dfixed_mul(mclk_ff, temp_ff); - if (sclk_ff.full < temp_ff.full) - temp_ff.full = sclk_ff.full; + if (track->zb_dirty && track->z_enabled) { + if (track->zb.robj == NULL) { + DRM_ERROR("[drm] No buffer for z buffer !\n"); + return -EINVAL; + } + size = track->zb.pitch * track->zb.cpp * track->maxy; + size += track->zb.offset; + if (size > radeon_bo_size(track->zb.robj)) { + DRM_ERROR("[drm] Buffer too small for z buffer " + "(need %lu have %lu) !\n", size, + radeon_bo_size(track->zb.robj)); + DRM_ERROR("[drm] zbuffer (%u %u %u %u)\n", + track->zb.pitch, track->zb.cpp, + track->zb.offset, track->maxy); + return -EINVAL; + } + } + track->zb_dirty = false; - read_return_rate.full = temp_ff.full; + if (track->aa_dirty && track->aaresolve) { + if (track->aa.robj == NULL) { + DRM_ERROR("[drm] No buffer for AA resolve buffer %d !\n", i); + return -EINVAL; + } + /* I believe the format comes from colorbuffer0. */ + size = track->aa.pitch * track->cb[0].cpp * track->maxy; + size += track->aa.offset; + if (size > radeon_bo_size(track->aa.robj)) { + DRM_ERROR("[drm] Buffer too small for AA resolve buffer %d " + "(need %lu have %lu) !\n", i, size, + radeon_bo_size(track->aa.robj)); + DRM_ERROR("[drm] AA resolve buffer %d (%u %u %u %u)\n", + i, track->aa.pitch, track->cb[0].cpp, + track->aa.offset, track->maxy); + return -EINVAL; + } + } + track->aa_dirty = false; - if (mode1) { - temp_ff.full = read_return_rate.full - disp_drain_rate.full; - time_disp1_drop_priority.full = dfixed_div(crit_point_ff, temp_ff); - } else { - time_disp1_drop_priority.full = 0; + prim_walk = (track->vap_vf_cntl >> 4) & 0x3; + if (track->vap_vf_cntl & (1 << 14)) { + nverts = track->vap_alt_nverts; + } else { + nverts = (track->vap_vf_cntl >> 16) & 0xFFFF; + } + switch (prim_walk) { + case 1: + for (i = 0; i < track->num_arrays; i++) { + size = track->arrays[i].esize * track->max_indx * 4; + if (track->arrays[i].robj == NULL) { + DRM_ERROR("(PW %u) Vertex array %u no buffer " + "bound\n", prim_walk, i); + return -EINVAL; } - crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full; - crit_point_ff.full = dfixed_mul(crit_point_ff, disp_drain_rate2); - crit_point_ff.full += dfixed_const_half(0); - - critical_point2 = dfixed_trunc(crit_point_ff); - - if (rdev->disp_priority == 2) { - critical_point2 = 0; + if (size > radeon_bo_size(track->arrays[i].robj)) { + dev_err(rdev->dev, "(PW %u) Vertex array %u " + "need %lu dwords have %lu dwords\n", + prim_walk, i, size >> 2, + radeon_bo_size(track->arrays[i].robj) + >> 2); + DRM_ERROR("Max indices %u\n", track->max_indx); + return -EINVAL; + } + } + break; + case 2: + for (i = 0; i < track->num_arrays; i++) { + size = track->arrays[i].esize * (nverts - 1) * 4; + if (track->arrays[i].robj == NULL) { + DRM_ERROR("(PW %u) Vertex array %u no buffer " + "bound\n", prim_walk, i); + return -EINVAL; + } + if (size > radeon_bo_size(track->arrays[i].robj)) { + dev_err(rdev->dev, "(PW %u) Vertex array %u " + "need %lu dwords have %lu dwords\n", + prim_walk, i, size >> 2, + radeon_bo_size(track->arrays[i].robj) + >> 2); + return -EINVAL; } + } + break; + case 3: + size = track->vtx_size * nverts; + if (size != track->immd_dwords) { + DRM_ERROR("IMMD draw %u dwors but needs %lu dwords\n", + track->immd_dwords, size); + DRM_ERROR("VAP_VF_CNTL.NUM_VERTICES %u, VTX_SIZE %u\n", + nverts, track->vtx_size); + return -EINVAL; + } + break; + default: + DRM_ERROR("[drm] Invalid primitive walk %d for VAP_VF_CNTL\n", + prim_walk); + return -EINVAL; + } - if (max_stop_req - critical_point2 < 4) - critical_point2 = 0; + if (track->tex_dirty) { + track->tex_dirty = false; + return r100_cs_track_texture_check(rdev, track); + } + return 0; +} - } +void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track) +{ + unsigned i, face; - if (critical_point2 == 0 && rdev->family == CHIP_R300) { - /* some R300 cards have problem with this set to 0 */ - critical_point2 = 0x10; - } + track->cb_dirty = true; + track->zb_dirty = true; + track->tex_dirty = true; + track->aa_dirty = true; - WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) | - (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); + if (rdev->family < CHIP_R300) { + track->num_cb = 1; + if (rdev->family <= CHIP_RS200) + track->num_texture = 3; + else + track->num_texture = 6; + track->maxy = 2048; + track->separate_cube = 1; + } else { + track->num_cb = 4; + track->num_texture = 16; + track->maxy = 4096; + track->separate_cube = 0; + track->aaresolve = false; + track->aa.robj = NULL; + } - if ((rdev->family == CHIP_RS400) || - (rdev->family == CHIP_RS480)) { -#if 0 - /* attempt to program RS400 disp2 regs correctly ??? */ - temp = RREG32(RS400_DISP2_REQ_CNTL1); - temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK | - RS400_DISP2_STOP_REQ_LEVEL_MASK); - WREG32(RS400_DISP2_REQ_CNTL1, (temp | - (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) | - (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); - temp = RREG32(RS400_DISP2_REQ_CNTL2); - temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK | - RS400_DISP2_CRITICAL_POINT_STOP_MASK); - WREG32(RS400_DISP2_REQ_CNTL2, (temp | - (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) | - (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT))); -#endif - WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC); - WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000); - WREG32(RS400_DMIF_MEM_CNTL1, 0x29CA71DC); - WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC); + for (i = 0; i < track->num_cb; i++) { + track->cb[i].robj = NULL; + track->cb[i].pitch = 8192; + track->cb[i].cpp = 16; + track->cb[i].offset = 0; + } + track->z_enabled = true; + track->zb.robj = NULL; + track->zb.pitch = 8192; + track->zb.cpp = 4; + track->zb.offset = 0; + track->vtx_size = 0x7F; + track->immd_dwords = 0xFFFFFFFFUL; + track->num_arrays = 11; + track->max_indx = 0x00FFFFFFUL; + for (i = 0; i < track->num_arrays; i++) { + track->arrays[i].robj = NULL; + track->arrays[i].esize = 0x7F; + } + for (i = 0; i < track->num_texture; i++) { + track->textures[i].compress_format = R100_TRACK_COMP_NONE; + track->textures[i].pitch = 16536; + track->textures[i].width = 16536; + track->textures[i].height = 16536; + track->textures[i].width_11 = 1 << 11; + track->textures[i].height_11 = 1 << 11; + track->textures[i].num_levels = 12; + if (rdev->family <= CHIP_RS200) { + track->textures[i].tex_coord_type = 0; + track->textures[i].txdepth = 0; + } else { + track->textures[i].txdepth = 16; + track->textures[i].tex_coord_type = 1; } - - DRM_DEBUG_KMS("GRPH2_BUFFER_CNTL from to %x\n", - (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL)); + track->textures[i].cpp = 64; + track->textures[i].robj = NULL; + /* CS IB emission code makes sure texture unit are disabled */ + track->textures[i].enabled = false; + track->textures[i].lookup_disable = false; + track->textures[i].roundup_w = true; + track->textures[i].roundup_h = true; + if (track->separate_cube) + for (face = 0; face < 5; face++) { + track->textures[i].cube_info[face].robj = NULL; + track->textures[i].cube_info[face].width = 16536; + track->textures[i].cube_info[face].height = 16536; + track->textures[i].cube_info[face].offset = 0; + } } } @@ -3791,12 +3679,6 @@ void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) { struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; - if (ring->rptr_save_reg) { - u32 next_rptr = ring->wptr + 2 + 3; - radeon_ring_write(ring, PACKET0(ring->rptr_save_reg, 0)); - radeon_ring_write(ring, next_rptr); - } - radeon_ring_write(ring, PACKET0(RADEON_CP_IB_BASE, 1)); radeon_ring_write(ring, ib->gpu_addr); radeon_ring_write(ring, ib->length_dw); @@ -3829,7 +3711,7 @@ int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) ib.ptr[6] = PACKET2(0); ib.ptr[7] = PACKET2(0); ib.length_dw = 8; - r = radeon_ib_schedule(rdev, &ib, NULL); + r = radeon_ib_schedule(rdev, &ib); if (r) { radeon_scratch_free(rdev, scratch); radeon_ib_free(rdev, &ib); @@ -3858,6 +3740,12 @@ int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) return r; } +void r100_ib_fini(struct radeon_device *rdev) +{ + radeon_ib_pool_suspend(rdev); + radeon_ib_pool_fini(rdev); +} + void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save) { /* Shutdown CP we shouldn't need to do that but better be safe than @@ -4017,11 +3905,13 @@ static int r100_startup(struct radeon_device *rdev) return r; } - r = radeon_ib_pool_init(rdev); - if (r) { - dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + r = radeon_ib_pool_start(rdev); + if (r) + return r; + + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } return 0; } @@ -4058,6 +3948,7 @@ int r100_resume(struct radeon_device *rdev) int r100_suspend(struct radeon_device *rdev) { + radeon_ib_pool_suspend(rdev); r100_cp_disable(rdev); radeon_wb_disable(rdev); r100_irq_disable(rdev); @@ -4070,7 +3961,7 @@ void r100_fini(struct radeon_device *rdev) { r100_cp_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_gem_fini(rdev); if (rdev->flags & RADEON_IS_PCI) r100_pci_gart_fini(rdev); @@ -4177,14 +4068,20 @@ int r100_init(struct radeon_device *rdev) } r100_set_safe_registers(rdev); + r = radeon_ib_pool_init(rdev); rdev->accel_working = true; + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + rdev->accel_working = false; + } + r = r100_startup(rdev); if (r) { /* Somethings want wront with the accel init stop accel */ dev_err(rdev->dev, "Disabling GPU acceleration\n"); r100_cp_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_irq_kms_fini(rdev); if (rdev->flags & RADEON_IS_PCI) r100_pci_gart_fini(rdev); diff --git a/trunk/drivers/gpu/drm/radeon/r200.c b/trunk/drivers/gpu/drm/radeon/r200.c index f0889259eb08..a26144d01207 100644 --- a/trunk/drivers/gpu/drm/radeon/r200.c +++ b/trunk/drivers/gpu/drm/radeon/r200.c @@ -85,7 +85,7 @@ int r200_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct radeon_fence **fence) + struct radeon_fence *fence) { struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; uint32_t size; @@ -120,7 +120,7 @@ int r200_copy_dma(struct radeon_device *rdev, radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); radeon_ring_write(ring, RADEON_WAIT_DMA_GUI_IDLE); if (fence) { - r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX); + r = radeon_fence_emit(rdev, fence); } radeon_ring_unlock_commit(rdev, ring); return r; diff --git a/trunk/drivers/gpu/drm/radeon/r300.c b/trunk/drivers/gpu/drm/radeon/r300.c index 646a1927dda7..97722a33e513 100644 --- a/trunk/drivers/gpu/drm/radeon/r300.c +++ b/trunk/drivers/gpu/drm/radeon/r300.c @@ -1391,11 +1391,13 @@ static int r300_startup(struct radeon_device *rdev) return r; } - r = radeon_ib_pool_init(rdev); - if (r) { - dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + r = radeon_ib_pool_start(rdev); + if (r) + return r; + + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } return 0; } @@ -1434,6 +1436,7 @@ int r300_resume(struct radeon_device *rdev) int r300_suspend(struct radeon_device *rdev) { + radeon_ib_pool_suspend(rdev); r100_cp_disable(rdev); radeon_wb_disable(rdev); r100_irq_disable(rdev); @@ -1448,7 +1451,7 @@ void r300_fini(struct radeon_device *rdev) { r100_cp_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_gem_fini(rdev); if (rdev->flags & RADEON_IS_PCIE) rv370_pcie_gart_fini(rdev); @@ -1535,14 +1538,20 @@ int r300_init(struct radeon_device *rdev) } r300_set_reg_safe(rdev); + r = radeon_ib_pool_init(rdev); rdev->accel_working = true; + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + rdev->accel_working = false; + } + r = r300_startup(rdev); if (r) { /* Somethings want wront with the accel init stop accel */ dev_err(rdev->dev, "Disabling GPU acceleration\n"); r100_cp_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_irq_kms_fini(rdev); if (rdev->flags & RADEON_IS_PCIE) rv370_pcie_gart_fini(rdev); diff --git a/trunk/drivers/gpu/drm/radeon/r420.c b/trunk/drivers/gpu/drm/radeon/r420.c index f2f5bf6d339f..99137be7a300 100644 --- a/trunk/drivers/gpu/drm/radeon/r420.c +++ b/trunk/drivers/gpu/drm/radeon/r420.c @@ -275,11 +275,13 @@ static int r420_startup(struct radeon_device *rdev) } r420_cp_errata_init(rdev); - r = radeon_ib_pool_init(rdev); - if (r) { - dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + r = radeon_ib_pool_start(rdev); + if (r) + return r; + + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } return 0; } @@ -322,6 +324,7 @@ int r420_resume(struct radeon_device *rdev) int r420_suspend(struct radeon_device *rdev) { + radeon_ib_pool_suspend(rdev); r420_cp_errata_fini(rdev); r100_cp_disable(rdev); radeon_wb_disable(rdev); @@ -337,7 +340,7 @@ void r420_fini(struct radeon_device *rdev) { r100_cp_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_gem_fini(rdev); if (rdev->flags & RADEON_IS_PCIE) rv370_pcie_gart_fini(rdev); @@ -435,14 +438,20 @@ int r420_init(struct radeon_device *rdev) } r420_set_reg_safe(rdev); + r = radeon_ib_pool_init(rdev); rdev->accel_working = true; + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + rdev->accel_working = false; + } + r = r420_startup(rdev); if (r) { /* Somethings want wront with the accel init stop accel */ dev_err(rdev->dev, "Disabling GPU acceleration\n"); r100_cp_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_irq_kms_fini(rdev); if (rdev->flags & RADEON_IS_PCIE) rv370_pcie_gart_fini(rdev); diff --git a/trunk/drivers/gpu/drm/radeon/r520.c b/trunk/drivers/gpu/drm/radeon/r520.c index 079d3c52c08a..b5cf8375cd25 100644 --- a/trunk/drivers/gpu/drm/radeon/r520.c +++ b/trunk/drivers/gpu/drm/radeon/r520.c @@ -203,11 +203,13 @@ static int r520_startup(struct radeon_device *rdev) return r; } - r = radeon_ib_pool_init(rdev); - if (r) { - dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + r = radeon_ib_pool_start(rdev); + if (r) + return r; + + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } return 0; } @@ -309,14 +311,20 @@ int r520_init(struct radeon_device *rdev) return r; rv515_set_safe_registers(rdev); + r = radeon_ib_pool_init(rdev); rdev->accel_working = true; + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + rdev->accel_working = false; + } + r = r520_startup(rdev); if (r) { /* Somethings want wront with the accel init stop accel */ dev_err(rdev->dev, "Disabling GPU acceleration\n"); r100_cp_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_irq_kms_fini(rdev); rv370_pcie_gart_fini(rdev); radeon_agp_fini(rdev); diff --git a/trunk/drivers/gpu/drm/radeon/r600.c b/trunk/drivers/gpu/drm/radeon/r600.c index 637280f541a3..bff627293812 100644 --- a/trunk/drivers/gpu/drm/radeon/r600.c +++ b/trunk/drivers/gpu/drm/radeon/r600.c @@ -709,7 +709,6 @@ void r600_hpd_init(struct radeon_device *rdev) { struct drm_device *dev = rdev->ddev; struct drm_connector *connector; - unsigned enable = 0; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -730,22 +729,28 @@ void r600_hpd_init(struct radeon_device *rdev) switch (radeon_connector->hpd.hpd) { case RADEON_HPD_1: WREG32(DC_HPD1_CONTROL, tmp); + rdev->irq.hpd[0] = true; break; case RADEON_HPD_2: WREG32(DC_HPD2_CONTROL, tmp); + rdev->irq.hpd[1] = true; break; case RADEON_HPD_3: WREG32(DC_HPD3_CONTROL, tmp); + rdev->irq.hpd[2] = true; break; case RADEON_HPD_4: WREG32(DC_HPD4_CONTROL, tmp); + rdev->irq.hpd[3] = true; break; /* DCE 3.2 */ case RADEON_HPD_5: WREG32(DC_HPD5_CONTROL, tmp); + rdev->irq.hpd[4] = true; break; case RADEON_HPD_6: WREG32(DC_HPD6_CONTROL, tmp); + rdev->irq.hpd[5] = true; break; default: break; @@ -754,73 +759,85 @@ void r600_hpd_init(struct radeon_device *rdev) switch (radeon_connector->hpd.hpd) { case RADEON_HPD_1: WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN); + rdev->irq.hpd[0] = true; break; case RADEON_HPD_2: WREG32(DC_HOT_PLUG_DETECT2_CONTROL, DC_HOT_PLUG_DETECTx_EN); + rdev->irq.hpd[1] = true; break; case RADEON_HPD_3: WREG32(DC_HOT_PLUG_DETECT3_CONTROL, DC_HOT_PLUG_DETECTx_EN); + rdev->irq.hpd[2] = true; break; default: break; } } - enable |= 1 << radeon_connector->hpd.hpd; radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); } - radeon_irq_kms_enable_hpd(rdev, enable); + if (rdev->irq.installed) + r600_irq_set(rdev); } void r600_hpd_fini(struct radeon_device *rdev) { struct drm_device *dev = rdev->ddev; struct drm_connector *connector; - unsigned disable = 0; - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - struct radeon_connector *radeon_connector = to_radeon_connector(connector); - if (ASIC_IS_DCE3(rdev)) { + if (ASIC_IS_DCE3(rdev)) { + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); switch (radeon_connector->hpd.hpd) { case RADEON_HPD_1: WREG32(DC_HPD1_CONTROL, 0); + rdev->irq.hpd[0] = false; break; case RADEON_HPD_2: WREG32(DC_HPD2_CONTROL, 0); + rdev->irq.hpd[1] = false; break; case RADEON_HPD_3: WREG32(DC_HPD3_CONTROL, 0); + rdev->irq.hpd[2] = false; break; case RADEON_HPD_4: WREG32(DC_HPD4_CONTROL, 0); + rdev->irq.hpd[3] = false; break; /* DCE 3.2 */ case RADEON_HPD_5: WREG32(DC_HPD5_CONTROL, 0); + rdev->irq.hpd[4] = false; break; case RADEON_HPD_6: WREG32(DC_HPD6_CONTROL, 0); + rdev->irq.hpd[5] = false; break; default: break; } - } else { + } + } else { + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); switch (radeon_connector->hpd.hpd) { case RADEON_HPD_1: WREG32(DC_HOT_PLUG_DETECT1_CONTROL, 0); + rdev->irq.hpd[0] = false; break; case RADEON_HPD_2: WREG32(DC_HOT_PLUG_DETECT2_CONTROL, 0); + rdev->irq.hpd[1] = false; break; case RADEON_HPD_3: WREG32(DC_HOT_PLUG_DETECT3_CONTROL, 0); + rdev->irq.hpd[2] = false; break; default: break; } } - disable |= 1 << radeon_connector->hpd.hpd; } - radeon_irq_kms_disable_hpd(rdev, disable); } /* @@ -1289,14 +1306,6 @@ int r600_gpu_soft_reset(struct radeon_device *rdev) RREG32(R_008014_GRBM_STATUS2)); dev_info(rdev->dev, " R_000E50_SRBM_STATUS=0x%08X\n", RREG32(R_000E50_SRBM_STATUS)); - dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", - RREG32(CP_STALLED_STAT1)); - dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", - RREG32(CP_STALLED_STAT2)); - dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", - RREG32(CP_BUSY_STAT)); - dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", - RREG32(CP_STAT)); rv515_mc_stop(rdev, &save); if (r600_mc_wait_for_idle(rdev)) { dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); @@ -1340,14 +1349,6 @@ int r600_gpu_soft_reset(struct radeon_device *rdev) RREG32(R_008014_GRBM_STATUS2)); dev_info(rdev->dev, " R_000E50_SRBM_STATUS=0x%08X\n", RREG32(R_000E50_SRBM_STATUS)); - dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", - RREG32(CP_STALLED_STAT1)); - dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", - RREG32(CP_STALLED_STAT2)); - dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", - RREG32(CP_BUSY_STAT)); - dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", - RREG32(CP_STAT)); rv515_mc_resume(rdev, &save); return 0; } @@ -2171,29 +2172,18 @@ int r600_cp_resume(struct radeon_device *rdev) void r600_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size) { u32 rb_bufsz; - int r; /* Align ring size */ rb_bufsz = drm_order(ring_size / 8); ring_size = (1 << (rb_bufsz + 1)) * 4; ring->ring_size = ring_size; ring->align_mask = 16 - 1; - - if (radeon_ring_supports_scratch_reg(rdev, ring)) { - r = radeon_scratch_get(rdev, &ring->rptr_save_reg); - if (r) { - DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r); - ring->rptr_save_reg = 0; - } - } } void r600_cp_fini(struct radeon_device *rdev) { - struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; r600_cp_stop(rdev); - radeon_ring_fini(rdev, ring); - radeon_scratch_free(rdev, ring->rptr_save_reg); + radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); } @@ -2216,7 +2206,7 @@ int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) { uint32_t scratch; uint32_t tmp = 0; - unsigned i; + unsigned i, ridx = radeon_ring_index(rdev, ring); int r; r = radeon_scratch_get(rdev, &scratch); @@ -2227,7 +2217,7 @@ int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) WREG32(scratch, 0xCAFEDEAD); r = radeon_ring_lock(rdev, ring, 3); if (r) { - DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n", ring->idx, r); + DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n", ridx, r); radeon_scratch_free(rdev, scratch); return r; } @@ -2242,10 +2232,10 @@ int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) DRM_UDELAY(1); } if (i < rdev->usec_timeout) { - DRM_INFO("ring test on %d succeeded in %d usecs\n", ring->idx, i); + DRM_INFO("ring test on %d succeeded in %d usecs\n", ridx, i); } else { DRM_ERROR("radeon: ring %d test failed (scratch(0x%04X)=0x%08X)\n", - ring->idx, scratch, tmp); + ridx, scratch, tmp); r = -EINVAL; } radeon_scratch_free(rdev, scratch); @@ -2319,21 +2309,34 @@ int r600_copy_blit(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct radeon_fence **fence) + struct radeon_fence *fence) { - struct radeon_semaphore *sem = NULL; struct radeon_sa_bo *vb = NULL; int r; - r = r600_blit_prepare_copy(rdev, num_gpu_pages, fence, &vb, &sem); + r = r600_blit_prepare_copy(rdev, num_gpu_pages, &vb); if (r) { return r; } r600_kms_blit_copy(rdev, src_offset, dst_offset, num_gpu_pages, vb); - r600_blit_done_copy(rdev, fence, vb, sem); + r600_blit_done_copy(rdev, fence, vb); return 0; } +void r600_blit_suspend(struct radeon_device *rdev) +{ + int r; + + /* unpin shaders bo */ + if (rdev->r600_blit.shader_obj) { + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (!r) { + radeon_bo_unpin(rdev->r600_blit.shader_obj); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); + } + } +} + int r600_set_surface_reg(struct radeon_device *rdev, int reg, uint32_t tiling_flags, uint32_t pitch, uint32_t offset, uint32_t obj_size) @@ -2416,11 +2419,13 @@ int r600_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_ib_pool_init(rdev); - if (r) { - dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + r = radeon_ib_pool_start(rdev); + if (r) + return r; + + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } r = r600_audio_init(rdev); if (r) { @@ -2470,6 +2475,9 @@ int r600_resume(struct radeon_device *rdev) int r600_suspend(struct radeon_device *rdev) { r600_audio_fini(rdev); + radeon_ib_pool_suspend(rdev); + r600_blit_suspend(rdev); + /* FIXME: we should wait for ring to be empty */ r600_cp_stop(rdev); rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; r600_irq_suspend(rdev); @@ -2551,14 +2559,20 @@ int r600_init(struct radeon_device *rdev) if (r) return r; + r = radeon_ib_pool_init(rdev); rdev->accel_working = true; + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + rdev->accel_working = false; + } + r = r600_startup(rdev); if (r) { dev_err(rdev->dev, "disabling GPU acceleration\n"); r600_cp_fini(rdev); r600_irq_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_irq_kms_fini(rdev); r600_pcie_gart_fini(rdev); rdev->accel_working = false; @@ -2574,7 +2588,7 @@ void r600_fini(struct radeon_device *rdev) r600_cp_fini(rdev); r600_irq_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_irq_kms_fini(rdev); r600_pcie_gart_fini(rdev); r600_vram_scratch_fini(rdev); @@ -2593,24 +2607,9 @@ void r600_fini(struct radeon_device *rdev) */ void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) { - struct radeon_ring *ring = &rdev->ring[ib->ring]; - u32 next_rptr; - - if (ring->rptr_save_reg) { - next_rptr = ring->wptr + 3 + 4; - radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); - radeon_ring_write(ring, ((ring->rptr_save_reg - - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); - radeon_ring_write(ring, next_rptr); - } else if (rdev->wb.enabled) { - next_rptr = ring->wptr + 5 + 4; - radeon_ring_write(ring, PACKET3(PACKET3_MEM_WRITE, 3)); - radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); - radeon_ring_write(ring, (upper_32_bits(ring->next_rptr_gpu_addr) & 0xff) | (1 << 18)); - radeon_ring_write(ring, next_rptr); - radeon_ring_write(ring, 0); - } + struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; + /* FIXME: implement */ radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); radeon_ring_write(ring, #ifdef __BIG_ENDIAN @@ -2628,6 +2627,7 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) uint32_t tmp = 0; unsigned i; int r; + int ring_index = radeon_ring_index(rdev, ring); r = radeon_scratch_get(rdev, &scratch); if (r) { @@ -2635,7 +2635,7 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) return r; } WREG32(scratch, 0xCAFEDEAD); - r = radeon_ib_get(rdev, ring->idx, &ib, 256); + r = radeon_ib_get(rdev, ring_index, &ib, 256); if (r) { DRM_ERROR("radeon: failed to get ib (%d).\n", r); return r; @@ -2644,7 +2644,7 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) ib.ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); ib.ptr[2] = 0xDEADBEEF; ib.length_dw = 3; - r = radeon_ib_schedule(rdev, &ib, NULL); + r = radeon_ib_schedule(rdev, &ib); if (r) { radeon_scratch_free(rdev, scratch); radeon_ib_free(rdev, &ib); @@ -2857,6 +2857,7 @@ void r600_disable_interrupts(struct radeon_device *rdev) WREG32(IH_RB_RPTR, 0); WREG32(IH_RB_WPTR, 0); rdev->ih.enabled = false; + rdev->ih.wptr = 0; rdev->ih.rptr = 0; } @@ -3041,18 +3042,18 @@ int r600_irq_set(struct radeon_device *rdev) hdmi1 = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; } - if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { + if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { DRM_DEBUG("r600_irq_set: sw int\n"); cp_int_cntl |= RB_INT_ENABLE; cp_int_cntl |= TIME_STAMP_INT_ENABLE; } if (rdev->irq.crtc_vblank_int[0] || - atomic_read(&rdev->irq.pflip[0])) { + rdev->irq.pflip[0]) { DRM_DEBUG("r600_irq_set: vblank 0\n"); mode_int |= D1MODE_VBLANK_INT_MASK; } if (rdev->irq.crtc_vblank_int[1] || - atomic_read(&rdev->irq.pflip[1])) { + rdev->irq.pflip[1]) { DRM_DEBUG("r600_irq_set: vblank 1\n"); mode_int |= D2MODE_VBLANK_INT_MASK; } @@ -3308,6 +3309,7 @@ int r600_irq_process(struct radeon_device *rdev) u32 rptr; u32 src_id, src_data; u32 ring_index; + unsigned long flags; bool queue_hotplug = false; bool queue_hdmi = false; @@ -3319,21 +3321,24 @@ int r600_irq_process(struct radeon_device *rdev) RREG32(IH_RB_WPTR); wptr = r600_get_ih_wptr(rdev); - -restart_ih: - /* is somebody else already processing irqs? */ - if (atomic_xchg(&rdev->ih.lock, 1)) - return IRQ_NONE; - rptr = rdev->ih.rptr; DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); + spin_lock_irqsave(&rdev->ih.lock, flags); + + if (rptr == wptr) { + spin_unlock_irqrestore(&rdev->ih.lock, flags); + return IRQ_NONE; + } + +restart_ih: /* Order reading of wptr vs. reading of IH ring data */ rmb(); /* display interrupts */ r600_irq_ack(rdev); + rdev->ih.wptr = wptr; while (rptr != wptr) { /* wptr/rptr are in bytes! */ ring_index = rptr / 4; @@ -3350,7 +3355,7 @@ int r600_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[0])) + if (rdev->irq.pflip[0]) radeon_crtc_handle_flip(rdev, 0); rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); @@ -3376,7 +3381,7 @@ int r600_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[1])) + if (rdev->irq.pflip[1]) radeon_crtc_handle_flip(rdev, 1); rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); @@ -3475,6 +3480,7 @@ int r600_irq_process(struct radeon_device *rdev) break; case 233: /* GUI IDLE */ DRM_DEBUG("IH: GUI idle\n"); + rdev->pm.gui_idle = true; wake_up(&rdev->irq.idle_queue); break; default: @@ -3486,19 +3492,17 @@ int r600_irq_process(struct radeon_device *rdev) rptr += 16; rptr &= rdev->ih.ptr_mask; } + /* make sure wptr hasn't changed while processing */ + wptr = r600_get_ih_wptr(rdev); + if (wptr != rdev->ih.wptr) + goto restart_ih; if (queue_hotplug) schedule_work(&rdev->hotplug_work); if (queue_hdmi) schedule_work(&rdev->audio_work); rdev->ih.rptr = rptr; WREG32(IH_RB_RPTR, rdev->ih.rptr); - atomic_set(&rdev->ih.lock, 0); - - /* make sure wptr hasn't changed while processing */ - wptr = r600_get_ih_wptr(rdev); - if (wptr != rptr) - goto restart_ih; - + spin_unlock_irqrestore(&rdev->ih.lock, flags); return IRQ_HANDLED; } @@ -3681,8 +3685,6 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev) { u32 link_width_cntl, lanes, speed_cntl, training_cntl, tmp; u16 link_cntl2; - u32 mask; - int ret; if (radeon_pcie_gen2 == 0) return; @@ -3701,15 +3703,6 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev) if (rdev->family <= CHIP_R600) return; - ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); - if (ret != 0) - return; - - if (!(mask & DRM_PCIE_SPEED_50)) - return; - - DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); - /* 55 nm r6xx asics */ if ((rdev->family == CHIP_RV670) || (rdev->family == CHIP_RV620) || diff --git a/trunk/drivers/gpu/drm/radeon/r600_blit_kms.c b/trunk/drivers/gpu/drm/radeon/r600_blit_kms.c index 2bef8549ddfe..03b6e0d3d503 100644 --- a/trunk/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/trunk/drivers/gpu/drm/radeon/r600_blit_kms.c @@ -512,8 +512,7 @@ int r600_blit_init(struct radeon_device *rdev) rdev->r600_blit.primitives.draw_auto = draw_auto; rdev->r600_blit.primitives.set_default_state = set_default_state; - rdev->r600_blit.ring_size_common = 8; /* sync semaphore */ - rdev->r600_blit.ring_size_common += 40; /* shaders + def state */ + rdev->r600_blit.ring_size_common = 40; /* shaders + def state */ rdev->r600_blit.ring_size_common += 5; /* done copy */ rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */ @@ -524,6 +523,10 @@ int r600_blit_init(struct radeon_device *rdev) rdev->r600_blit.max_dim = 8192; + /* pin copy shader into vram if already initialized */ + if (rdev->r600_blit.shader_obj) + goto done; + rdev->r600_blit.state_offset = 0; if (rdev->family >= CHIP_RV770) @@ -548,26 +551,11 @@ int r600_blit_init(struct radeon_device *rdev) obj_size += r6xx_ps_size * 4; obj_size = ALIGN(obj_size, 256); - /* pin copy shader into vram if not already initialized */ - if (rdev->r600_blit.shader_obj == NULL) { - r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, - RADEON_GEM_DOMAIN_VRAM, - NULL, &rdev->r600_blit.shader_obj); - if (r) { - DRM_ERROR("r600 failed to allocate shader\n"); - return r; - } - - r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); - if (unlikely(r != 0)) - return r; - r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, - &rdev->r600_blit.shader_gpu_addr); - radeon_bo_unreserve(rdev->r600_blit.shader_obj); - if (r) { - dev_err(rdev->dev, "(%d) pin blit object failed\n", r); - return r; - } + r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, + NULL, &rdev->r600_blit.shader_obj); + if (r) { + DRM_ERROR("r600 failed to allocate shader\n"); + return r; } DRM_DEBUG("r6xx blit allocated bo %08x vs %08x ps %08x\n", @@ -598,6 +586,17 @@ int r600_blit_init(struct radeon_device *rdev) radeon_bo_kunmap(rdev->r600_blit.shader_obj); radeon_bo_unreserve(rdev->r600_blit.shader_obj); +done: + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM, + &rdev->r600_blit.shader_gpu_addr); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); + if (r) { + dev_err(rdev->dev, "(%d) pin blit object failed\n", r); + return r; + } radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); return 0; } @@ -667,8 +666,7 @@ static unsigned r600_blit_create_rect(unsigned num_gpu_pages, int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages, - struct radeon_fence **fence, struct radeon_sa_bo **vb, - struct radeon_semaphore **sem) + struct radeon_sa_bo **vb) { struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; int r; @@ -691,50 +689,34 @@ int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages, return r; } - r = radeon_semaphore_create(rdev, sem); - if (r) { - radeon_sa_bo_free(rdev, vb, NULL); - return r; - } - /* calculate number of loops correctly */ ring_size = num_loops * dwords_per_loop; ring_size += rdev->r600_blit.ring_size_common; r = radeon_ring_lock(rdev, ring, ring_size); if (r) { radeon_sa_bo_free(rdev, vb, NULL); - radeon_semaphore_free(rdev, sem, NULL); return r; } - if (radeon_fence_need_sync(*fence, RADEON_RING_TYPE_GFX_INDEX)) { - radeon_semaphore_sync_rings(rdev, *sem, (*fence)->ring, - RADEON_RING_TYPE_GFX_INDEX); - radeon_fence_note_sync(*fence, RADEON_RING_TYPE_GFX_INDEX); - } else { - radeon_semaphore_free(rdev, sem, NULL); - } - rdev->r600_blit.primitives.set_default_state(rdev); rdev->r600_blit.primitives.set_shaders(rdev); return 0; } -void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence **fence, - struct radeon_sa_bo *vb, struct radeon_semaphore *sem) +void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence, + struct radeon_sa_bo *vb) { struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; int r; - r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX); + r = radeon_fence_emit(rdev, fence); if (r) { radeon_ring_unlock_undo(rdev, ring); return; } radeon_ring_unlock_commit(rdev, ring); - radeon_sa_bo_free(rdev, &vb, *fence); - radeon_semaphore_free(rdev, &sem, *fence); + radeon_sa_bo_free(rdev, &vb, fence); } void r600_kms_blit_copy(struct radeon_device *rdev, diff --git a/trunk/drivers/gpu/drm/radeon/r600_hdmi.c b/trunk/drivers/gpu/drm/radeon/r600_hdmi.c index e3558c3ef24a..82a0a4c919c0 100644 --- a/trunk/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/trunk/drivers/gpu/drm/radeon/r600_hdmi.c @@ -519,7 +519,8 @@ void r600_hdmi_enable(struct drm_encoder *encoder) if (rdev->irq.installed) { /* if irq is available use it */ - radeon_irq_kms_enable_afmt(rdev, dig->afmt->id); + rdev->irq.afmt[dig->afmt->id] = true; + radeon_irq_set(rdev); } dig->afmt->enabled = true; @@ -555,7 +556,8 @@ void r600_hdmi_disable(struct drm_encoder *encoder) offset, radeon_encoder->encoder_id); /* disable irq */ - radeon_irq_kms_disable_afmt(rdev, dig->afmt->id); + rdev->irq.afmt[dig->afmt->id] = false; + radeon_irq_set(rdev); /* Older chipsets not handled by AtomBIOS */ if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) { diff --git a/trunk/drivers/gpu/drm/radeon/r600d.h b/trunk/drivers/gpu/drm/radeon/r600d.h index 4b116ae75fc2..025fd5b6c08c 100644 --- a/trunk/drivers/gpu/drm/radeon/r600d.h +++ b/trunk/drivers/gpu/drm/radeon/r600d.h @@ -153,9 +153,6 @@ #define CONFIG_MEMSIZE 0x5428 #define CONFIG_CNTL 0x5424 -#define CP_STALLED_STAT1 0x8674 -#define CP_STALLED_STAT2 0x8678 -#define CP_BUSY_STAT 0x867C #define CP_STAT 0x8680 #define CP_COHER_BASE 0x85F8 #define CP_DEBUG 0xC1FC diff --git a/trunk/drivers/gpu/drm/radeon/radeon.h b/trunk/drivers/gpu/drm/radeon/radeon.h index 5431af292408..fefcca55c1eb 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon.h +++ b/trunk/drivers/gpu/drm/radeon/radeon.h @@ -113,6 +113,7 @@ extern int radeon_lockup_timeout; /* fence seq are set to this number when signaled */ #define RADEON_FENCE_SIGNALED_SEQ 0LL +#define RADEON_FENCE_NOTEMITED_SEQ (~0LL) /* internal ring indices */ /* r1xx+ has gfx CP ring */ @@ -159,6 +160,48 @@ static inline int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len) #endif bool radeon_get_bios(struct radeon_device *rdev); + +/* + * Mutex which allows recursive locking from the same process. + */ +struct radeon_mutex { + struct mutex mutex; + struct task_struct *owner; + int level; +}; + +static inline void radeon_mutex_init(struct radeon_mutex *mutex) +{ + mutex_init(&mutex->mutex); + mutex->owner = NULL; + mutex->level = 0; +} + +static inline void radeon_mutex_lock(struct radeon_mutex *mutex) +{ + if (mutex_trylock(&mutex->mutex)) { + /* The mutex was unlocked before, so it's ours now */ + mutex->owner = current; + } else if (mutex->owner != current) { + /* Another process locked the mutex, take it */ + mutex_lock(&mutex->mutex); + mutex->owner = current; + } + /* Otherwise the mutex was already locked by this process */ + + mutex->level++; +} + +static inline void radeon_mutex_unlock(struct radeon_mutex *mutex) +{ + if (--mutex->level > 0) + return; + + mutex->owner = NULL; + mutex_unlock(&mutex->mutex); +} + + /* * Dummy page */ @@ -215,8 +258,8 @@ struct radeon_fence_driver { uint32_t scratch_reg; uint64_t gpu_addr; volatile uint32_t *cpu_addr; - /* sync_seq is protected by ring emission lock */ - uint64_t sync_seq[RADEON_NUM_RINGS]; + /* seq is protected by ring emission lock */ + uint64_t seq; atomic64_t last_seq; unsigned long last_activity; bool initialized; @@ -234,39 +277,19 @@ struct radeon_fence { int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); int radeon_fence_driver_init(struct radeon_device *rdev); void radeon_fence_driver_fini(struct radeon_device *rdev); -int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence **fence, int ring); +int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence **fence, int ring); +int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence); void radeon_fence_process(struct radeon_device *rdev, int ring); bool radeon_fence_signaled(struct radeon_fence *fence); int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring); -void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring); +int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring); int radeon_fence_wait_any(struct radeon_device *rdev, struct radeon_fence **fences, bool intr); struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence); void radeon_fence_unref(struct radeon_fence **fence); unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring); -bool radeon_fence_need_sync(struct radeon_fence *fence, int ring); -void radeon_fence_note_sync(struct radeon_fence *fence, int ring); -static inline struct radeon_fence *radeon_fence_later(struct radeon_fence *a, - struct radeon_fence *b) -{ - if (!a) { - return b; - } - - if (!b) { - return a; - } - - BUG_ON(a->ring != b->ring); - - if (a->seq > b->seq) { - return a; - } else { - return b; - } -} /* * Tiling registers @@ -362,7 +385,7 @@ struct radeon_bo_list { * alignment). */ struct radeon_sa_manager { - wait_queue_head_t wq; + spinlock_t lock; struct radeon_bo *bo; struct list_head *hole; struct list_head flist[RADEON_NUM_RINGS]; @@ -428,9 +451,10 @@ void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, struct radeon_semaphore *semaphore); int radeon_semaphore_sync_rings(struct radeon_device *rdev, struct radeon_semaphore *semaphore, - int signaler, int waiter); + bool sync_to[RADEON_NUM_RINGS], + int dst_ring); void radeon_semaphore_free(struct radeon_device *rdev, - struct radeon_semaphore **semaphore, + struct radeon_semaphore *semaphore, struct radeon_fence *fence); /* @@ -573,18 +597,21 @@ union radeon_irq_stat_regs { #define RADEON_MAX_AFMT_BLOCKS 6 struct radeon_irq { - bool installed; - spinlock_t lock; - atomic_t ring_int[RADEON_NUM_RINGS]; - bool crtc_vblank_int[RADEON_MAX_CRTCS]; - atomic_t pflip[RADEON_MAX_CRTCS]; - wait_queue_head_t vblank_queue; - bool hpd[RADEON_MAX_HPD_PINS]; - bool gui_idle; - bool gui_idle_acked; - wait_queue_head_t idle_queue; - bool afmt[RADEON_MAX_AFMT_BLOCKS]; - union radeon_irq_stat_regs stat_regs; + bool installed; + bool sw_int[RADEON_NUM_RINGS]; + bool crtc_vblank_int[RADEON_MAX_CRTCS]; + bool pflip[RADEON_MAX_CRTCS]; + wait_queue_head_t vblank_queue; + bool hpd[RADEON_MAX_HPD_PINS]; + bool gui_idle; + bool gui_idle_acked; + wait_queue_head_t idle_queue; + bool afmt[RADEON_MAX_AFMT_BLOCKS]; + spinlock_t sw_lock; + int sw_refcount[RADEON_NUM_RINGS]; + union radeon_irq_stat_regs stat_regs; + spinlock_t pflip_lock[RADEON_MAX_CRTCS]; + int pflip_refcount[RADEON_MAX_CRTCS]; }; int radeon_irq_kms_init(struct radeon_device *rdev); @@ -593,11 +620,6 @@ void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring); void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring); void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc); void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc); -void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block); -void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block); -void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask); -void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask); -int radeon_irq_kms_wait_gui_idle(struct radeon_device *rdev); /* * CP & rings. @@ -608,11 +630,9 @@ struct radeon_ib { uint32_t length_dw; uint64_t gpu_addr; uint32_t *ptr; - int ring; struct radeon_fence *fence; unsigned vm_id; bool is_const_ib; - struct radeon_fence *sync_to[RADEON_NUM_RINGS]; struct radeon_semaphore *semaphore; }; @@ -622,9 +642,6 @@ struct radeon_ring { unsigned rptr; unsigned rptr_offs; unsigned rptr_reg; - unsigned rptr_save_reg; - u64 next_rptr_gpu_addr; - volatile u32 *next_rptr_cpu_addr; unsigned wptr; unsigned wptr_old; unsigned wptr_reg; @@ -640,7 +657,6 @@ struct radeon_ring { u32 ptr_reg_shift; u32 ptr_reg_mask; u32 nop; - u32 idx; }; /* @@ -674,7 +690,6 @@ struct radeon_vm_funcs { }; struct radeon_vm_manager { - struct mutex lock; struct list_head lru_vm; uint32_t use_bitmap; struct radeon_sa_manager sa_manager; @@ -703,10 +718,13 @@ struct r600_ih { struct radeon_bo *ring_obj; volatile uint32_t *ring; unsigned rptr; + unsigned rptr_offs; + unsigned wptr; + unsigned wptr_old; unsigned ring_size; uint64_t gpu_addr; uint32_t ptr_mask; - atomic_t lock; + spinlock_t lock; bool enabled; }; @@ -739,6 +757,8 @@ struct r600_blit { u32 state_len; }; +void r600_blit_suspend(struct radeon_device *rdev); + /* * SI RLC stuff */ @@ -754,14 +774,14 @@ struct si_rlc { int radeon_ib_get(struct radeon_device *rdev, int ring, struct radeon_ib *ib, unsigned size); void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib); -int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, - struct radeon_ib *const_ib); +int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib); int radeon_ib_pool_init(struct radeon_device *rdev); void radeon_ib_pool_fini(struct radeon_device *rdev); +int radeon_ib_pool_start(struct radeon_device *rdev); +int radeon_ib_pool_suspend(struct radeon_device *rdev); int radeon_ib_ring_tests(struct radeon_device *rdev); /* Ring access between begin & end cannot sleep */ -bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev, - struct radeon_ring *ring); +int radeon_ring_index(struct radeon_device *rdev, struct radeon_ring *cp); void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *cp); int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw); int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw); @@ -773,10 +793,6 @@ int radeon_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring); void radeon_ring_lockup_update(struct radeon_ring *ring); bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *ring); -unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring, - uint32_t **data); -int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring, - unsigned size, uint32_t *data); int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ring_size, unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop); @@ -875,7 +891,6 @@ struct radeon_wb { }; #define RADEON_WB_SCRATCH_OFFSET 0 -#define RADEON_WB_RING0_NEXT_RPTR 256 #define RADEON_WB_CP_RPTR_OFFSET 1024 #define RADEON_WB_CP1_RPTR_OFFSET 1280 #define RADEON_WB_CP2_RPTR_OFFSET 1536 @@ -1024,12 +1039,11 @@ struct radeon_power_state { struct radeon_pm { struct mutex mutex; - /* write locked while reprogramming mclk */ - struct rw_semaphore mclk_lock; u32 active_crtcs; int active_crtc_count; int req_vblank; bool vblank_sync; + bool gui_idle; fixed20_12 max_bandwidth; fixed20_12 igp_sideport_mclk; fixed20_12 igp_system_mclk; @@ -1178,20 +1192,20 @@ struct radeon_asic { uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct radeon_fence **fence); + struct radeon_fence *fence); u32 blit_ring_index; int (*dma)(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct radeon_fence **fence); + struct radeon_fence *fence); u32 dma_ring_index; /* method used for bo copy */ int (*copy)(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct radeon_fence **fence); + struct radeon_fence *fence); /* ring used for bo copies */ u32 copy_ring_index; } copy; @@ -1453,7 +1467,6 @@ struct radeon_device { struct device *dev; struct drm_device *ddev; struct pci_dev *pdev; - struct rw_semaphore exclusive_lock; /* ASIC */ union radeon_asic_config config; enum radeon_family family; @@ -1499,6 +1512,7 @@ struct radeon_device { struct radeon_gem gem; struct radeon_pm pm; uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH]; + struct radeon_mutex cs_mutex; struct radeon_wb wb; struct radeon_dummy_page dummy_page; bool shutdown; @@ -1520,6 +1534,7 @@ struct radeon_device { struct work_struct audio_work; int num_crtc; /* number of crtcs */ struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */ + struct mutex vram_mutex; bool audio_enabled; struct r600_audio audio_status; /* audio stuff */ struct notifier_block acpi_nb; @@ -1770,6 +1785,8 @@ extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size */ int radeon_vm_manager_init(struct radeon_device *rdev); void radeon_vm_manager_fini(struct radeon_device *rdev); +int radeon_vm_manager_start(struct radeon_device *rdev); +int radeon_vm_manager_suspend(struct radeon_device *rdev); int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm); void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm); int radeon_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_asic.c b/trunk/drivers/gpu/drm/radeon/radeon_asic.c index 973417c4b014..f533df5f7d50 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_asic.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_asic.c @@ -40,16 +40,6 @@ /* * Registers accessors functions. */ -/** - * radeon_invalid_rreg - dummy reg read function - * - * @rdev: radeon device pointer - * @reg: offset of register - * - * Dummy register read function. Used for register blocks - * that certain asics don't have (all asics). - * Returns the value in the register. - */ static uint32_t radeon_invalid_rreg(struct radeon_device *rdev, uint32_t reg) { DRM_ERROR("Invalid callback to read register 0x%04X\n", reg); @@ -57,16 +47,6 @@ static uint32_t radeon_invalid_rreg(struct radeon_device *rdev, uint32_t reg) return 0; } -/** - * radeon_invalid_wreg - dummy reg write function - * - * @rdev: radeon device pointer - * @reg: offset of register - * @v: value to write to the register - * - * Dummy register read function. Used for register blocks - * that certain asics don't have (all asics). - */ static void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) { DRM_ERROR("Invalid callback to write register 0x%04X with 0x%08X\n", @@ -74,14 +54,6 @@ static void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32 BUG_ON(1); } -/** - * radeon_register_accessor_init - sets up the register accessor callbacks - * - * @rdev: radeon device pointer - * - * Sets up the register accessor callbacks for various register - * apertures. Not all asics have all apertures (all asics). - */ static void radeon_register_accessor_init(struct radeon_device *rdev) { rdev->mc_rreg = &radeon_invalid_rreg; @@ -130,14 +102,6 @@ static void radeon_register_accessor_init(struct radeon_device *rdev) /* helper to disable agp */ -/** - * radeon_agp_disable - AGP disable helper function - * - * @rdev: radeon device pointer - * - * Removes AGP flags and changes the gart callbacks on AGP - * cards when using the internal gart rather than AGP (all asics). - */ void radeon_agp_disable(struct radeon_device *rdev) { rdev->flags &= ~RADEON_IS_AGP; @@ -1644,16 +1608,6 @@ static struct radeon_asic si_asic = { }, }; -/** - * radeon_asic_init - register asic specific callbacks - * - * @rdev: radeon device pointer - * - * Registers the appropriate asic specific callbacks for each - * chip family. Also sets other asics specific info like the number - * of crtcs and the register aperture accessors (all asics). - * Returns 0 for success. - */ int radeon_asic_init(struct radeon_device *rdev) { radeon_register_accessor_init(rdev); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_asic.h b/trunk/drivers/gpu/drm/radeon/radeon_asic.h index f4af24310438..e76a941ef14e 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_asic.h +++ b/trunk/drivers/gpu/drm/radeon/radeon_asic.h @@ -79,7 +79,7 @@ int r100_copy_blit(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct radeon_fence **fence); + struct radeon_fence *fence); int r100_set_surface_reg(struct radeon_device *rdev, int reg, uint32_t tiling_flags, uint32_t pitch, uint32_t offset, uint32_t obj_size); @@ -103,6 +103,7 @@ int r100_pci_gart_enable(struct radeon_device *rdev); void r100_pci_gart_disable(struct radeon_device *rdev); int r100_debugfs_mc_info_init(struct radeon_device *rdev); int r100_gui_wait_for_idle(struct radeon_device *rdev); +void r100_ib_fini(struct radeon_device *rdev); int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); void r100_irq_disable(struct radeon_device *rdev); void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save); @@ -143,7 +144,7 @@ extern int r200_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct radeon_fence **fence); + struct radeon_fence *fence); void r200_set_safe_registers(struct radeon_device *rdev); /* @@ -317,7 +318,7 @@ void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); int r600_copy_blit(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, - unsigned num_gpu_pages, struct radeon_fence **fence); + unsigned num_gpu_pages, struct radeon_fence *fence); void r600_hpd_init(struct radeon_device *rdev); void r600_hpd_fini(struct radeon_device *rdev); bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); @@ -362,10 +363,9 @@ int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); void r600_hdmi_update_audio_settings(struct drm_encoder *encoder); /* r600 blit */ int r600_blit_prepare_copy(struct radeon_device *rdev, unsigned num_gpu_pages, - struct radeon_fence **fence, struct radeon_sa_bo **vb, - struct radeon_semaphore **sem); -void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence **fence, - struct radeon_sa_bo *vb, struct radeon_semaphore *sem); + struct radeon_sa_bo **vb); +void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence, + struct radeon_sa_bo *vb); void r600_kms_blit_copy(struct radeon_device *rdev, u64 src_gpu_addr, u64 dst_gpu_addr, unsigned num_gpu_pages, diff --git a/trunk/drivers/gpu/drm/radeon/radeon_benchmark.c b/trunk/drivers/gpu/drm/radeon/radeon_benchmark.c index bedda9caadd9..364f5b1a04b9 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_benchmark.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_benchmark.c @@ -45,14 +45,20 @@ static int radeon_benchmark_do_move(struct radeon_device *rdev, unsigned size, for (i = 0; i < n; i++) { switch (flag) { case RADEON_BENCHMARK_COPY_DMA: + r = radeon_fence_create(rdev, &fence, radeon_copy_dma_ring_index(rdev)); + if (r) + return r; r = radeon_copy_dma(rdev, saddr, daddr, size / RADEON_GPU_PAGE_SIZE, - &fence); + fence); break; case RADEON_BENCHMARK_COPY_BLIT: + r = radeon_fence_create(rdev, &fence, radeon_copy_blit_ring_index(rdev)); + if (r) + return r; r = radeon_copy_blit(rdev, saddr, daddr, size / RADEON_GPU_PAGE_SIZE, - &fence); + fence); break; default: DRM_ERROR("Unknown copy method\n"); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_connectors.c b/trunk/drivers/gpu/drm/radeon/radeon_connectors.c index 895e628b60f8..2914c5761cfc 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_connectors.c @@ -64,33 +64,14 @@ void radeon_connector_hotplug(struct drm_connector *connector) /* just deal with DP (not eDP) here. */ if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { - struct radeon_connector_atom_dig *dig_connector = - radeon_connector->con_priv; - - /* if existing sink type was not DP no need to retrain */ - if (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_DISPLAYPORT) - return; - - /* first get sink type as it may be reset after (un)plug */ - dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector); - /* don't do anything if sink is not display port, i.e., - * passive dp->(dvi|hdmi) adaptor - */ - if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { - int saved_dpms = connector->dpms; - /* Only turn off the display if it's physically disconnected */ - if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { - drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); - } else if (radeon_dp_needs_link_train(radeon_connector)) { - /* set it to OFF so that drm_helper_connector_dpms() - * won't return immediately since the current state - * is ON at this point. - */ - connector->dpms = DRM_MODE_DPMS_OFF; - drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); - } - connector->dpms = saved_dpms; - } + int saved_dpms = connector->dpms; + + /* Only turn off the display it it's physically disconnected */ + if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + else if (radeon_dp_needs_link_train(radeon_connector)) + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); + connector->dpms = saved_dpms; } } diff --git a/trunk/drivers/gpu/drm/radeon/radeon_cs.c b/trunk/drivers/gpu/drm/radeon/radeon_cs.c index 8a4c49ef0cc4..142f89462aa4 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_cs.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_cs.c @@ -115,20 +115,36 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority return 0; } -static void radeon_cs_sync_rings(struct radeon_cs_parser *p) +static int radeon_cs_sync_rings(struct radeon_cs_parser *p) { - int i; + bool sync_to_ring[RADEON_NUM_RINGS] = { }; + bool need_sync = false; + int i, r; for (i = 0; i < p->nrelocs; i++) { - struct radeon_fence *a, *b; + struct radeon_fence *fence; if (!p->relocs[i].robj || !p->relocs[i].robj->tbo.sync_obj) continue; - a = p->relocs[i].robj->tbo.sync_obj; - b = p->ib.sync_to[a->ring]; - p->ib.sync_to[a->ring] = radeon_fence_later(a, b); + fence = p->relocs[i].robj->tbo.sync_obj; + if (fence->ring != p->ring && !radeon_fence_signaled(fence)) { + sync_to_ring[fence->ring] = true; + need_sync = true; + } + } + + if (!need_sync) { + return 0; + } + + r = radeon_semaphore_create(p->rdev, &p->ib.semaphore); + if (r) { + return r; } + + return radeon_semaphore_sync_rings(p->rdev, p->ib.semaphore, + sync_to_ring, p->ring); } /* XXX: note that this is called from the legacy UMS CS ioctl as well */ @@ -352,13 +368,16 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev, DRM_ERROR("Invalid command stream !\n"); return r; } - radeon_cs_sync_rings(parser); + r = radeon_cs_sync_rings(parser); + if (r) { + DRM_ERROR("Failed to synchronize rings !\n"); + } parser->ib.vm_id = 0; - r = radeon_ib_schedule(rdev, &parser->ib, NULL); + r = radeon_ib_schedule(rdev, &parser->ib); if (r) { DRM_ERROR("Failed to schedule IB !\n"); } - return r; + return 0; } static int radeon_bo_vm_update_pte(struct radeon_cs_parser *parser, @@ -440,7 +459,6 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, return r; } - mutex_lock(&rdev->vm_manager.lock); mutex_lock(&vm->mutex); r = radeon_vm_bind(rdev, vm); if (r) { @@ -450,26 +468,30 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, if (r) { goto out; } - radeon_cs_sync_rings(parser); - - parser->ib.vm_id = vm->id; - /* ib pool is bind at 0 in virtual address space, - * so gpu_addr is the offset inside the pool bo - */ - parser->ib.gpu_addr = parser->ib.sa_bo->soffset; + r = radeon_cs_sync_rings(parser); + if (r) { + DRM_ERROR("Failed to synchronize rings !\n"); + } if ((rdev->family >= CHIP_TAHITI) && (parser->chunk_const_ib_idx != -1)) { parser->const_ib.vm_id = vm->id; - /* ib pool is bind at 0 in virtual address space, - * so gpu_addr is the offset inside the pool bo + /* ib pool is bind at 0 in virtual address space to gpu_addr is the + * offset inside the pool bo */ parser->const_ib.gpu_addr = parser->const_ib.sa_bo->soffset; - r = radeon_ib_schedule(rdev, &parser->ib, &parser->const_ib); - } else { - r = radeon_ib_schedule(rdev, &parser->ib, NULL); + r = radeon_ib_schedule(rdev, &parser->const_ib); + if (r) + goto out; } + parser->ib.vm_id = vm->id; + /* ib pool is bind at 0 in virtual address space to gpu_addr is the + * offset inside the pool bo + */ + parser->ib.gpu_addr = parser->ib.sa_bo->soffset; + parser->ib.is_const_ib = false; + r = radeon_ib_schedule(rdev, &parser->ib); out: if (!r) { if (vm->fence) { @@ -477,8 +499,7 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, } vm->fence = radeon_fence_ref(parser->ib.fence); } - mutex_unlock(&vm->mutex); - mutex_unlock(&rdev->vm_manager.lock); + mutex_unlock(&fpriv->vm.mutex); return r; } @@ -498,9 +519,9 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) struct radeon_cs_parser parser; int r; - down_read(&rdev->exclusive_lock); + radeon_mutex_lock(&rdev->cs_mutex); if (!rdev->accel_working) { - up_read(&rdev->exclusive_lock); + radeon_mutex_unlock(&rdev->cs_mutex); return -EBUSY; } /* initialize parser */ @@ -513,8 +534,8 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) if (r) { DRM_ERROR("Failed to initialize parser !\n"); radeon_cs_parser_fini(&parser, r); - up_read(&rdev->exclusive_lock); r = radeon_cs_handle_lockup(rdev, r); + radeon_mutex_unlock(&rdev->cs_mutex); return r; } r = radeon_cs_parser_relocs(&parser); @@ -522,8 +543,8 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) if (r != -ERESTARTSYS) DRM_ERROR("Failed to parse relocation %d!\n", r); radeon_cs_parser_fini(&parser, r); - up_read(&rdev->exclusive_lock); r = radeon_cs_handle_lockup(rdev, r); + radeon_mutex_unlock(&rdev->cs_mutex); return r; } r = radeon_cs_ib_chunk(rdev, &parser); @@ -536,8 +557,8 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) } out: radeon_cs_parser_fini(&parser, r); - up_read(&rdev->exclusive_lock); r = radeon_cs_handle_lockup(rdev, r); + radeon_mutex_unlock(&rdev->cs_mutex); return r; } diff --git a/trunk/drivers/gpu/drm/radeon/radeon_cursor.c b/trunk/drivers/gpu/drm/radeon/radeon_cursor.c index 711e95ad39bf..42acc6449dd6 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_cursor.c @@ -262,14 +262,8 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, if (!(cursor_end & 0x7f)) w--; } - if (w <= 0) { + if (w <= 0) w = 1; - cursor_end = x - xorigin + w; - if (!(cursor_end & 0x7f)) { - x--; - WARN_ON_ONCE(x < 0); - } - } } } diff --git a/trunk/drivers/gpu/drm/radeon/radeon_device.c b/trunk/drivers/gpu/drm/radeon/radeon_device.c index 742af8244e89..066c98b888a5 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_device.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_device.c @@ -96,12 +96,8 @@ static const char radeon_family_name[][16] = { "LAST", }; -/** - * radeon_surface_init - Clear GPU surface registers. - * - * @rdev: radeon_device pointer - * - * Clear GPU surface registers (r1xx-r5xx). +/* + * Clear GPU surface registers. */ void radeon_surface_init(struct radeon_device *rdev) { @@ -123,13 +119,6 @@ void radeon_surface_init(struct radeon_device *rdev) /* * GPU scratch registers helpers function. */ -/** - * radeon_scratch_init - Init scratch register driver information. - * - * @rdev: radeon_device pointer - * - * Init CP scratch register driver information (r1xx-r5xx) - */ void radeon_scratch_init(struct radeon_device *rdev) { int i; @@ -147,15 +136,6 @@ void radeon_scratch_init(struct radeon_device *rdev) } } -/** - * radeon_scratch_get - Allocate a scratch register - * - * @rdev: radeon_device pointer - * @reg: scratch register mmio offset - * - * Allocate a CP scratch register for use by the driver (all asics). - * Returns 0 on success or -EINVAL on failure. - */ int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg) { int i; @@ -170,14 +150,6 @@ int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg) return -EINVAL; } -/** - * radeon_scratch_free - Free a scratch register - * - * @rdev: radeon_device pointer - * @reg: scratch register mmio offset - * - * Free a CP scratch register allocated for use by the driver (all asics) - */ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) { int i; @@ -190,20 +162,6 @@ void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) } } -/* - * radeon_wb_*() - * Writeback is the the method by which the the GPU updates special pages - * in memory with the status of certain GPU events (fences, ring pointers, - * etc.). - */ - -/** - * radeon_wb_disable - Disable Writeback - * - * @rdev: radeon_device pointer - * - * Disables Writeback (all asics). Used for suspend. - */ void radeon_wb_disable(struct radeon_device *rdev) { int r; @@ -219,14 +177,6 @@ void radeon_wb_disable(struct radeon_device *rdev) rdev->wb.enabled = false; } -/** - * radeon_wb_fini - Disable Writeback and free memory - * - * @rdev: radeon_device pointer - * - * Disables Writeback and frees the Writeback memory (all asics). - * Used at driver shutdown. - */ void radeon_wb_fini(struct radeon_device *rdev) { radeon_wb_disable(rdev); @@ -237,15 +187,6 @@ void radeon_wb_fini(struct radeon_device *rdev) } } -/** - * radeon_wb_init- Init Writeback driver info and allocate memory - * - * @rdev: radeon_device pointer - * - * Disables Writeback and frees the Writeback memory (all asics). - * Used at driver startup. - * Returns 0 on success or an -error on failure. - */ int radeon_wb_init(struct radeon_device *rdev) { int r; @@ -414,15 +355,6 @@ void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) /* * GPU helpers function. */ -/** - * radeon_card_posted - check if the hw has already been initialized - * - * @rdev: radeon_device pointer - * - * Check if the asic has been initialized (all asics). - * Used at driver startup. - * Returns true if initialized or false if not. - */ bool radeon_card_posted(struct radeon_device *rdev) { uint32_t reg; @@ -472,14 +404,6 @@ bool radeon_card_posted(struct radeon_device *rdev) } -/** - * radeon_update_bandwidth_info - update display bandwidth params - * - * @rdev: radeon_device pointer - * - * Used when sclk/mclk are switched or display modes are set. - * params are used to calculate display watermarks (all asics) - */ void radeon_update_bandwidth_info(struct radeon_device *rdev) { fixed20_12 a; @@ -500,15 +424,6 @@ void radeon_update_bandwidth_info(struct radeon_device *rdev) } } -/** - * radeon_boot_test_post_card - check and possibly initialize the hw - * - * @rdev: radeon_device pointer - * - * Check if the asic is initialized and if not, attempt to initialize - * it (all asics). - * Returns true if initialized or false if not. - */ bool radeon_boot_test_post_card(struct radeon_device *rdev) { if (radeon_card_posted(rdev)) @@ -527,16 +442,6 @@ bool radeon_boot_test_post_card(struct radeon_device *rdev) } } -/** - * radeon_dummy_page_init - init dummy page used by the driver - * - * @rdev: radeon_device pointer - * - * Allocate the dummy page used by the driver (all asics). - * This dummy page is used by the driver as a filler for gart entries - * when pages are taken out of the GART - * Returns 0 on sucess, -ENOMEM on failure. - */ int radeon_dummy_page_init(struct radeon_device *rdev) { if (rdev->dummy_page.page) @@ -555,13 +460,6 @@ int radeon_dummy_page_init(struct radeon_device *rdev) return 0; } -/** - * radeon_dummy_page_fini - free dummy page used by the driver - * - * @rdev: radeon_device pointer - * - * Frees the dummy page used by the driver (all asics). - */ void radeon_dummy_page_fini(struct radeon_device *rdev) { if (rdev->dummy_page.page == NULL) @@ -574,23 +472,6 @@ void radeon_dummy_page_fini(struct radeon_device *rdev) /* ATOM accessor methods */ -/* - * ATOM is an interpreted byte code stored in tables in the vbios. The - * driver registers callbacks to access registers and the interpreter - * in the driver parses the tables and executes then to program specific - * actions (set display modes, asic init, etc.). See radeon_atombios.c, - * atombios.h, and atom.c - */ - -/** - * cail_pll_read - read PLL register - * - * @info: atom card_info pointer - * @reg: PLL register offset - * - * Provides a PLL register accessor for the atom interpreter (r4xx+). - * Returns the value of the PLL register. - */ static uint32_t cail_pll_read(struct card_info *info, uint32_t reg) { struct radeon_device *rdev = info->dev->dev_private; @@ -600,15 +481,6 @@ static uint32_t cail_pll_read(struct card_info *info, uint32_t reg) return r; } -/** - * cail_pll_write - write PLL register - * - * @info: atom card_info pointer - * @reg: PLL register offset - * @val: value to write to the pll register - * - * Provides a PLL register accessor for the atom interpreter (r4xx+). - */ static void cail_pll_write(struct card_info *info, uint32_t reg, uint32_t val) { struct radeon_device *rdev = info->dev->dev_private; @@ -616,15 +488,6 @@ static void cail_pll_write(struct card_info *info, uint32_t reg, uint32_t val) rdev->pll_wreg(rdev, reg, val); } -/** - * cail_mc_read - read MC (Memory Controller) register - * - * @info: atom card_info pointer - * @reg: MC register offset - * - * Provides an MC register accessor for the atom interpreter (r4xx+). - * Returns the value of the MC register. - */ static uint32_t cail_mc_read(struct card_info *info, uint32_t reg) { struct radeon_device *rdev = info->dev->dev_private; @@ -634,15 +497,6 @@ static uint32_t cail_mc_read(struct card_info *info, uint32_t reg) return r; } -/** - * cail_mc_write - write MC (Memory Controller) register - * - * @info: atom card_info pointer - * @reg: MC register offset - * @val: value to write to the pll register - * - * Provides a MC register accessor for the atom interpreter (r4xx+). - */ static void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val) { struct radeon_device *rdev = info->dev->dev_private; @@ -650,15 +504,6 @@ static void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val) rdev->mc_wreg(rdev, reg, val); } -/** - * cail_reg_write - write MMIO register - * - * @info: atom card_info pointer - * @reg: MMIO register offset - * @val: value to write to the pll register - * - * Provides a MMIO register accessor for the atom interpreter (r4xx+). - */ static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val) { struct radeon_device *rdev = info->dev->dev_private; @@ -666,15 +511,6 @@ static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val) WREG32(reg*4, val); } -/** - * cail_reg_read - read MMIO register - * - * @info: atom card_info pointer - * @reg: MMIO register offset - * - * Provides an MMIO register accessor for the atom interpreter (r4xx+). - * Returns the value of the MMIO register. - */ static uint32_t cail_reg_read(struct card_info *info, uint32_t reg) { struct radeon_device *rdev = info->dev->dev_private; @@ -684,15 +520,6 @@ static uint32_t cail_reg_read(struct card_info *info, uint32_t reg) return r; } -/** - * cail_ioreg_write - write IO register - * - * @info: atom card_info pointer - * @reg: IO register offset - * @val: value to write to the pll register - * - * Provides a IO register accessor for the atom interpreter (r4xx+). - */ static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val) { struct radeon_device *rdev = info->dev->dev_private; @@ -700,15 +527,6 @@ static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val) WREG32_IO(reg*4, val); } -/** - * cail_ioreg_read - read IO register - * - * @info: atom card_info pointer - * @reg: IO register offset - * - * Provides an IO register accessor for the atom interpreter (r4xx+). - * Returns the value of the IO register. - */ static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg) { struct radeon_device *rdev = info->dev->dev_private; @@ -718,16 +536,6 @@ static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg) return r; } -/** - * radeon_atombios_init - init the driver info and callbacks for atombios - * - * @rdev: radeon_device pointer - * - * Initializes the driver info and register access callbacks for the - * ATOM interpreter (r4xx+). - * Returns 0 on sucess, -ENOMEM on failure. - * Called at driver startup. - */ int radeon_atombios_init(struct radeon_device *rdev) { struct card_info *atom_card_info = @@ -761,15 +569,6 @@ int radeon_atombios_init(struct radeon_device *rdev) return 0; } -/** - * radeon_atombios_fini - free the driver info and callbacks for atombios - * - * @rdev: radeon_device pointer - * - * Frees the driver info and register access callbacks for the ATOM - * interpreter (r4xx+). - * Called at driver shutdown. - */ void radeon_atombios_fini(struct radeon_device *rdev) { if (rdev->mode_info.atom_context) { @@ -779,50 +578,17 @@ void radeon_atombios_fini(struct radeon_device *rdev) kfree(rdev->mode_info.atom_card_info); } -/* COMBIOS */ -/* - * COMBIOS is the bios format prior to ATOM. It provides - * command tables similar to ATOM, but doesn't have a unified - * parser. See radeon_combios.c - */ - -/** - * radeon_combios_init - init the driver info for combios - * - * @rdev: radeon_device pointer - * - * Initializes the driver info for combios (r1xx-r3xx). - * Returns 0 on sucess. - * Called at driver startup. - */ int radeon_combios_init(struct radeon_device *rdev) { radeon_combios_initialize_bios_scratch_regs(rdev->ddev); return 0; } -/** - * radeon_combios_fini - free the driver info for combios - * - * @rdev: radeon_device pointer - * - * Frees the driver info for combios (r1xx-r3xx). - * Called at driver shutdown. - */ void radeon_combios_fini(struct radeon_device *rdev) { } -/* if we get transitioned to only one device, take VGA back */ -/** - * radeon_vga_set_decode - enable/disable vga decode - * - * @cookie: radeon_device pointer - * @state: enable/disable vga decode - * - * Enable/disable vga decode (all asics). - * Returns VGA resource flags. - */ +/* if we get transitioned to only one device, tak VGA back */ static unsigned int radeon_vga_set_decode(void *cookie, bool state) { struct radeon_device *rdev = cookie; @@ -834,14 +600,6 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state) return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; } -/** - * radeon_check_arguments - validate module params - * - * @rdev: radeon_device pointer - * - * Validates certain module parameters and updates - * the associated values used by the driver (all asics). - */ void radeon_check_arguments(struct radeon_device *rdev) { /* vramlimit must be a power of two */ @@ -908,15 +666,6 @@ void radeon_check_arguments(struct radeon_device *rdev) } } -/** - * radeon_switcheroo_set_state - set switcheroo state - * - * @pdev: pci dev pointer - * @state: vga switcheroo state - * - * Callback for the switcheroo driver. Suspends or resumes the - * the asics before or after it is powered up using ACPI methods. - */ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) { struct drm_device *dev = pci_get_drvdata(pdev); @@ -937,15 +686,6 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero } } -/** - * radeon_switcheroo_can_switch - see if switcheroo state can change - * - * @pdev: pci dev pointer - * - * Callback for the switcheroo driver. Check of the switcheroo - * state can be changed. - * Returns true if the state can be changed, false if not. - */ static bool radeon_switcheroo_can_switch(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); @@ -963,18 +703,6 @@ static const struct vga_switcheroo_client_ops radeon_switcheroo_ops = { .can_switch = radeon_switcheroo_can_switch, }; -/** - * radeon_device_init - initialize the driver - * - * @rdev: radeon_device pointer - * @pdev: drm dev pointer - * @pdev: pci dev pointer - * @flags: driver flags - * - * Initializes the driver info and hw (all asics). - * Returns 0 for success or an error on failure. - * Called at driver startup. - */ int radeon_device_init(struct radeon_device *rdev, struct drm_device *ddev, struct pci_dev *pdev, @@ -993,10 +721,6 @@ int radeon_device_init(struct radeon_device *rdev, rdev->usec_timeout = RADEON_MAX_USEC_TIMEOUT; rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; rdev->accel_working = false; - /* set up ring ids */ - for (i = 0; i < RADEON_NUM_RINGS; i++) { - rdev->ring[i].idx = i; - } DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n", radeon_family_name[rdev->family], pdev->vendor, pdev->device, @@ -1004,20 +728,20 @@ int radeon_device_init(struct radeon_device *rdev, /* mutex initialization are all done here so we * can recall function without having locking issues */ + radeon_mutex_init(&rdev->cs_mutex); mutex_init(&rdev->ring_lock); mutex_init(&rdev->dc_hw_i2c_mutex); - atomic_set(&rdev->ih.lock, 0); + if (rdev->family >= CHIP_R600) + spin_lock_init(&rdev->ih.lock); mutex_init(&rdev->gem.mutex); mutex_init(&rdev->pm.mutex); - init_rwsem(&rdev->pm.mclk_lock); - init_rwsem(&rdev->exclusive_lock); + mutex_init(&rdev->vram_mutex); init_waitqueue_head(&rdev->irq.vblank_queue); init_waitqueue_head(&rdev->irq.idle_queue); r = radeon_gem_init(rdev); if (r) return r; /* initialize vm here */ - mutex_init(&rdev->vm_manager.lock); rdev->vm_manager.use_bitmap = 1; rdev->vm_manager.max_pfn = 1 << 20; INIT_LIST_HEAD(&rdev->vm_manager.lru_vm); @@ -1098,10 +822,6 @@ int radeon_device_init(struct radeon_device *rdev, if (r) return r; - r = radeon_ib_ring_tests(rdev); - if (r) - DRM_ERROR("ib ring test failed (%d).\n", r); - if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) { /* Acceleration not working on AGP card try again * with fallback to PCI or PCIE GART @@ -1127,14 +847,6 @@ int radeon_device_init(struct radeon_device *rdev, static void radeon_debugfs_remove_files(struct radeon_device *rdev); -/** - * radeon_device_fini - tear down the driver - * - * @rdev: radeon_device pointer - * - * Tear down the driver info (all asics). - * Called at driver shutdown. - */ void radeon_device_fini(struct radeon_device *rdev) { DRM_INFO("radeon: finishing device.\n"); @@ -1156,16 +868,6 @@ void radeon_device_fini(struct radeon_device *rdev) /* * Suspend & resume. */ -/** - * radeon_suspend_kms - initiate device suspend - * - * @pdev: drm dev pointer - * @state: suspend state - * - * Puts the hw in the suspend state (all asics). - * Returns 0 for success or an error on failure. - * Called at driver suspend. - */ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) { struct radeon_device *rdev; @@ -1240,20 +942,10 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) return 0; } -/** - * radeon_resume_kms - initiate device resume - * - * @pdev: drm dev pointer - * - * Bring the hw back to operating state (all asics). - * Returns 0 for success or an error on failure. - * Called at driver resume. - */ int radeon_resume_kms(struct drm_device *dev) { struct drm_connector *connector; struct radeon_device *rdev = dev->dev_private; - int r; if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; @@ -1268,11 +960,6 @@ int radeon_resume_kms(struct drm_device *dev) /* resume AGP if in use */ radeon_agp_resume(rdev); radeon_resume(rdev); - - r = radeon_ib_ring_tests(rdev); - if (r) - DRM_ERROR("ib ring test failed (%d).\n", r); - radeon_pm_resume(rdev); radeon_restore_bios_scratch_regs(rdev); @@ -1297,77 +984,30 @@ int radeon_resume_kms(struct drm_device *dev) return 0; } -/** - * radeon_gpu_reset - reset the asic - * - * @rdev: radeon device pointer - * - * Attempt the reset the GPU if it has hung (all asics). - * Returns 0 for success or an error on failure. - */ int radeon_gpu_reset(struct radeon_device *rdev) { - unsigned ring_sizes[RADEON_NUM_RINGS]; - uint32_t *ring_data[RADEON_NUM_RINGS]; - - bool saved = false; - - int i, r; + int r; int resched; - down_write(&rdev->exclusive_lock); radeon_save_bios_scratch_regs(rdev); /* block TTM */ resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); radeon_suspend(rdev); - for (i = 0; i < RADEON_NUM_RINGS; ++i) { - ring_sizes[i] = radeon_ring_backup(rdev, &rdev->ring[i], - &ring_data[i]); - if (ring_sizes[i]) { - saved = true; - dev_info(rdev->dev, "Saved %d dwords of commands " - "on ring %d.\n", ring_sizes[i], i); - } - } - -retry: r = radeon_asic_reset(rdev); if (!r) { - dev_info(rdev->dev, "GPU reset succeeded, trying to resume\n"); + dev_info(rdev->dev, "GPU reset succeed\n"); radeon_resume(rdev); + radeon_restore_bios_scratch_regs(rdev); + drm_helper_resume_force_mode(rdev->ddev); + ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); } - radeon_restore_bios_scratch_regs(rdev); - drm_helper_resume_force_mode(rdev->ddev); - - if (!r) { - for (i = 0; i < RADEON_NUM_RINGS; ++i) { - radeon_ring_restore(rdev, &rdev->ring[i], - ring_sizes[i], ring_data[i]); - } - - r = radeon_ib_ring_tests(rdev); - if (r) { - dev_err(rdev->dev, "ib ring test failed (%d).\n", r); - if (saved) { - radeon_suspend(rdev); - goto retry; - } - } - } else { - for (i = 0; i < RADEON_NUM_RINGS; ++i) { - kfree(ring_data[i]); - } - } - - ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); if (r) { /* bad news, how to tell it to userspace ? */ dev_info(rdev->dev, "GPU reset failed\n"); } - up_write(&rdev->exclusive_lock); return r; } diff --git a/trunk/drivers/gpu/drm/radeon/radeon_display.c b/trunk/drivers/gpu/drm/radeon/radeon_display.c index 7ddef8f30d0e..64a008d14493 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_display.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_display.c @@ -1401,7 +1401,7 @@ void radeon_modeset_fini(struct radeon_device *rdev) radeon_i2c_fini(rdev); } -static bool is_hdtv_mode(const struct drm_display_mode *mode) +static bool is_hdtv_mode(struct drm_display_mode *mode) { /* try and guess if this is a tv or a monitor */ if ((mode->vdisplay == 480 && mode->hdisplay == 720) || /* 480p */ @@ -1414,7 +1414,7 @@ static bool is_hdtv_mode(const struct drm_display_mode *mode) } bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = crtc->dev; diff --git a/trunk/drivers/gpu/drm/radeon/radeon_drv.c b/trunk/drivers/gpu/drm/radeon/radeon_drv.c index dcea6f01ae4e..2c4d53fd20c5 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_drv.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_drv.c @@ -133,7 +133,7 @@ int radeon_tv = 1; int radeon_audio = 0; int radeon_disp_priority = 0; int radeon_hw_i2c = 0; -int radeon_pcie_gen2 = -1; +int radeon_pcie_gen2 = 0; int radeon_msi = -1; int radeon_lockup_timeout = 10000; @@ -179,7 +179,7 @@ module_param_named(disp_priority, radeon_disp_priority, int, 0444); MODULE_PARM_DESC(hw_i2c, "hw i2c engine enable (0 = disable)"); module_param_named(hw_i2c, radeon_hw_i2c, int, 0444); -MODULE_PARM_DESC(pcie_gen2, "PCIE Gen2 mode (-1 = auto, 0 = disable, 1 = enable)"); +MODULE_PARM_DESC(pcie_gen2, "PCIE Gen2 mode (1 = enable)"); module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444); MODULE_PARM_DESC(msi, "MSI support (1 = enable, 0 = disable, -1 = auto)"); @@ -262,6 +262,7 @@ static struct drm_driver driver_old = { .irq_postinstall = radeon_driver_irq_postinstall, .irq_uninstall = radeon_driver_irq_uninstall, .irq_handler = radeon_driver_irq_handler, + .reclaim_buffers = drm_core_reclaim_buffers, .ioctls = radeon_ioctls, .dma_ioctl = radeon_cp_buffers, .fops = &radeon_driver_old_fops, @@ -364,6 +365,7 @@ static struct drm_driver kms_driver = { .irq_postinstall = radeon_driver_irq_postinstall_kms, .irq_uninstall = radeon_driver_irq_uninstall_kms, .irq_handler = radeon_driver_irq_handler_kms, + .reclaim_buffers = drm_core_reclaim_buffers, .ioctls = radeon_ioctls_kms, .gem_init_object = radeon_gem_object_init, .gem_free_object = radeon_gem_object_free, diff --git a/trunk/drivers/gpu/drm/radeon/radeon_fence.c b/trunk/drivers/gpu/drm/radeon/radeon_fence.c index 7b737b9339ad..11f5f402d22c 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_fence.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_fence.c @@ -40,95 +40,39 @@ #include "radeon.h" #include "radeon_trace.h" -/* - * Fences - * Fences mark an event in the GPUs pipeline and are used - * for GPU/CPU synchronization. When the fence is written, - * it is expected that all buffers associated with that fence - * are no longer in use by the associated ring on the GPU and - * that the the relevant GPU caches have been flushed. Whether - * we use a scratch register or memory location depends on the asic - * and whether writeback is enabled. - */ - -/** - * radeon_fence_write - write a fence value - * - * @rdev: radeon_device pointer - * @seq: sequence number to write - * @ring: ring index the fence is associated with - * - * Writes a fence value to memory or a scratch register (all asics). - */ static void radeon_fence_write(struct radeon_device *rdev, u32 seq, int ring) { - struct radeon_fence_driver *drv = &rdev->fence_drv[ring]; - if (likely(rdev->wb.enabled || !drv->scratch_reg)) { - *drv->cpu_addr = cpu_to_le32(seq); + if (rdev->wb.enabled) { + *rdev->fence_drv[ring].cpu_addr = cpu_to_le32(seq); } else { - WREG32(drv->scratch_reg, seq); + WREG32(rdev->fence_drv[ring].scratch_reg, seq); } } -/** - * radeon_fence_read - read a fence value - * - * @rdev: radeon_device pointer - * @ring: ring index the fence is associated with - * - * Reads a fence value from memory or a scratch register (all asics). - * Returns the value of the fence read from memory or register. - */ static u32 radeon_fence_read(struct radeon_device *rdev, int ring) { - struct radeon_fence_driver *drv = &rdev->fence_drv[ring]; u32 seq = 0; - if (likely(rdev->wb.enabled || !drv->scratch_reg)) { - seq = le32_to_cpu(*drv->cpu_addr); + if (rdev->wb.enabled) { + seq = le32_to_cpu(*rdev->fence_drv[ring].cpu_addr); } else { - seq = RREG32(drv->scratch_reg); + seq = RREG32(rdev->fence_drv[ring].scratch_reg); } return seq; } -/** - * radeon_fence_emit - emit a fence on the requested ring - * - * @rdev: radeon_device pointer - * @fence: radeon fence object - * @ring: ring index the fence is associated with - * - * Emits a fence command on the requested ring (all asics). - * Returns 0 on success, -ENOMEM on failure. - */ -int radeon_fence_emit(struct radeon_device *rdev, - struct radeon_fence **fence, - int ring) +int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) { /* we are protected by the ring emission mutex */ - *fence = kmalloc(sizeof(struct radeon_fence), GFP_KERNEL); - if ((*fence) == NULL) { - return -ENOMEM; + if (fence->seq && fence->seq < RADEON_FENCE_NOTEMITED_SEQ) { + return 0; } - kref_init(&((*fence)->kref)); - (*fence)->rdev = rdev; - (*fence)->seq = ++rdev->fence_drv[ring].sync_seq[ring]; - (*fence)->ring = ring; - radeon_fence_ring_emit(rdev, ring, *fence); - trace_radeon_fence_emit(rdev->ddev, (*fence)->seq); + fence->seq = ++rdev->fence_drv[fence->ring].seq; + radeon_fence_ring_emit(rdev, fence->ring, fence); + trace_radeon_fence_emit(rdev->ddev, fence->seq); return 0; } -/** - * radeon_fence_process - process a fence - * - * @rdev: radeon_device pointer - * @ring: ring index the fence is associated with - * - * Checks the current fence value and wakes the fence queue - * if the sequence number has increased (all asics). - */ void radeon_fence_process(struct radeon_device *rdev, int ring) { uint64_t seq, last_seq; @@ -189,35 +133,30 @@ void radeon_fence_process(struct radeon_device *rdev, int ring) } } -/** - * radeon_fence_destroy - destroy a fence - * - * @kref: fence kref - * - * Frees the fence object (all asics). - */ static void radeon_fence_destroy(struct kref *kref) { struct radeon_fence *fence; fence = container_of(kref, struct radeon_fence, kref); + fence->seq = RADEON_FENCE_NOTEMITED_SEQ; kfree(fence); } -/** - * radeon_fence_seq_signaled - check if a fence sequeuce number has signaled - * - * @rdev: radeon device pointer - * @seq: sequence number - * @ring: ring index the fence is associated with - * - * Check if the last singled fence sequnce number is >= the requested - * sequence number (all asics). - * Returns true if the fence has signaled (current fence value - * is >= requested value) or false if it has not (current fence - * value is < the requested value. Helper function for - * radeon_fence_signaled(). - */ +int radeon_fence_create(struct radeon_device *rdev, + struct radeon_fence **fence, + int ring) +{ + *fence = kmalloc(sizeof(struct radeon_fence), GFP_KERNEL); + if ((*fence) == NULL) { + return -ENOMEM; + } + kref_init(&((*fence)->kref)); + (*fence)->rdev = rdev; + (*fence)->seq = RADEON_FENCE_NOTEMITED_SEQ; + (*fence)->ring = ring; + return 0; +} + static bool radeon_fence_seq_signaled(struct radeon_device *rdev, u64 seq, unsigned ring) { @@ -232,19 +171,15 @@ static bool radeon_fence_seq_signaled(struct radeon_device *rdev, return false; } -/** - * radeon_fence_signaled - check if a fence has signaled - * - * @fence: radeon fence object - * - * Check if the requested fence has signaled (all asics). - * Returns true if the fence has signaled or false if it has not. - */ bool radeon_fence_signaled(struct radeon_fence *fence) { if (!fence) { return true; } + if (fence->seq == RADEON_FENCE_NOTEMITED_SEQ) { + WARN(1, "Querying an unemitted fence : %p !\n", fence); + return true; + } if (fence->seq == RADEON_FENCE_SIGNALED_SEQ) { return true; } @@ -255,24 +190,6 @@ bool radeon_fence_signaled(struct radeon_fence *fence) return false; } -/** - * radeon_fence_wait_seq - wait for a specific sequence number - * - * @rdev: radeon device pointer - * @target_seq: sequence number we want to wait for - * @ring: ring index the fence is associated with - * @intr: use interruptable sleep - * @lock_ring: whether the ring should be locked or not - * - * Wait for the requested sequence number to be written (all asics). - * @intr selects whether to use interruptable (true) or non-interruptable - * (false) sleep when waiting for the sequence number. Helper function - * for radeon_fence_wait(), et al. - * Returns 0 if the sequence number has passed, error for all other cases. - * -EDEADLK is returned when a GPU lockup has been detected and the ring is - * marked as not ready so no further jobs get scheduled until a successful - * reset. - */ static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq, unsigned ring, bool intr, bool lock_ring) { @@ -368,17 +285,6 @@ static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq, return 0; } -/** - * radeon_fence_wait - wait for a fence to signal - * - * @fence: radeon fence object - * @intr: use interruptable sleep - * - * Wait for the requested fence to signal (all asics). - * @intr selects whether to use interruptable (true) or non-interruptable - * (false) sleep when waiting for the fence. - * Returns 0 if the fence has passed, error for all other cases. - */ int radeon_fence_wait(struct radeon_fence *fence, bool intr) { int r; @@ -409,20 +315,6 @@ bool radeon_fence_any_seq_signaled(struct radeon_device *rdev, u64 *seq) return false; } -/** - * radeon_fence_wait_any_seq - wait for a sequence number on any ring - * - * @rdev: radeon device pointer - * @target_seq: sequence number(s) we want to wait for - * @intr: use interruptable sleep - * - * Wait for the requested sequence number(s) to be written by any ring - * (all asics). Sequnce number array is indexed by ring id. - * @intr selects whether to use interruptable (true) or non-interruptable - * (false) sleep when waiting for the sequence number. Helper function - * for radeon_fence_wait_any(), et al. - * Returns 0 if the sequence number has passed, error for all other cases. - */ static int radeon_fence_wait_any_seq(struct radeon_device *rdev, u64 *target_seq, bool intr) { @@ -451,7 +343,7 @@ static int radeon_fence_wait_any_seq(struct radeon_device *rdev, /* nothing to wait for ? */ if (ring == RADEON_NUM_RINGS) { - return -ENOENT; + return 0; } while (!radeon_fence_any_seq_signaled(rdev, target_seq)) { @@ -532,19 +424,6 @@ static int radeon_fence_wait_any_seq(struct radeon_device *rdev, return 0; } -/** - * radeon_fence_wait_any - wait for a fence to signal on any ring - * - * @rdev: radeon device pointer - * @fences: radeon fence object(s) - * @intr: use interruptable sleep - * - * Wait for any requested fence to signal (all asics). Fence - * array is indexed by ring id. @intr selects whether to use - * interruptable (true) or non-interruptable (false) sleep when - * waiting for the fences. Used by the suballocator. - * Returns 0 if any fence has passed, error for all other cases. - */ int radeon_fence_wait_any(struct radeon_device *rdev, struct radeon_fence **fences, bool intr) @@ -565,7 +444,9 @@ int radeon_fence_wait_any(struct radeon_device *rdev, return 0; } - seq[i] = fences[i]->seq; + if (fences[i]->seq < RADEON_FENCE_NOTEMITED_SEQ) { + seq[i] = fences[i]->seq; + } } r = radeon_fence_wait_any_seq(rdev, seq, intr); @@ -575,22 +456,16 @@ int radeon_fence_wait_any(struct radeon_device *rdev, return 0; } -/** - * radeon_fence_wait_next_locked - wait for the next fence to signal - * - * @rdev: radeon device pointer - * @ring: ring index the fence is associated with - * - * Wait for the next fence on the requested ring to signal (all asics). - * Returns 0 if the next fence has passed, error for all other cases. - * Caller must hold ring lock. - */ int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring) { uint64_t seq; + /* We are not protected by ring lock when reading current seq but + * it's ok as worst case is we return to early while we could have + * wait. + */ seq = atomic64_read(&rdev->fence_drv[ring].last_seq) + 1ULL; - if (seq >= rdev->fence_drv[ring].sync_seq[ring]) { + if (seq >= rdev->fence_drv[ring].seq) { /* nothing to wait for, last_seq is already the last emited fence */ return -ENOENT; @@ -598,59 +473,23 @@ int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring) return radeon_fence_wait_seq(rdev, seq, ring, false, false); } -/** - * radeon_fence_wait_empty_locked - wait for all fences to signal - * - * @rdev: radeon device pointer - * @ring: ring index the fence is associated with - * - * Wait for all fences on the requested ring to signal (all asics). - * Returns 0 if the fences have passed, error for all other cases. - * Caller must hold ring lock. - */ -void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) +int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) { - uint64_t seq = rdev->fence_drv[ring].sync_seq[ring]; - - while(1) { - int r; - r = radeon_fence_wait_seq(rdev, seq, ring, false, false); - if (r == -EDEADLK) { - mutex_unlock(&rdev->ring_lock); - r = radeon_gpu_reset(rdev); - mutex_lock(&rdev->ring_lock); - if (!r) - continue; - } - if (r) { - dev_err(rdev->dev, "error waiting for ring to become" - " idle (%d)\n", r); - } - return; - } + /* We are not protected by ring lock when reading current seq + * but it's ok as wait empty is call from place where no more + * activity can be scheduled so there won't be concurrent access + * to seq value. + */ + return radeon_fence_wait_seq(rdev, rdev->fence_drv[ring].seq, + ring, false, false); } -/** - * radeon_fence_ref - take a ref on a fence - * - * @fence: radeon fence object - * - * Take a reference on a fence (all asics). - * Returns the fence. - */ struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence) { kref_get(&fence->kref); return fence; } -/** - * radeon_fence_unref - remove a ref on a fence - * - * @fence: radeon fence object - * - * Remove a reference on a fence (all asics). - */ void radeon_fence_unref(struct radeon_fence **fence) { struct radeon_fence *tmp = *fence; @@ -661,16 +500,6 @@ void radeon_fence_unref(struct radeon_fence **fence) } } -/** - * radeon_fence_count_emitted - get the count of emitted fences - * - * @rdev: radeon device pointer - * @ring: ring index the fence is associated with - * - * Get the number of fences emitted on the requested ring (all asics). - * Returns the number of emitted fences on the ring. Used by the - * dynpm code to ring track activity. - */ unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring) { uint64_t emitted; @@ -679,8 +508,7 @@ unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring) * but it's ok to report slightly wrong fence count here. */ radeon_fence_process(rdev, ring); - emitted = rdev->fence_drv[ring].sync_seq[ring] - - atomic64_read(&rdev->fence_drv[ring].last_seq); + emitted = rdev->fence_drv[ring].seq - atomic64_read(&rdev->fence_drv[ring].last_seq); /* to avoid 32bits warp around */ if (emitted > 0x10000000) { emitted = 0x10000000; @@ -688,83 +516,6 @@ unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring) return (unsigned)emitted; } -/** - * radeon_fence_need_sync - do we need a semaphore - * - * @fence: radeon fence object - * @dst_ring: which ring to check against - * - * Check if the fence needs to be synced against another ring - * (all asics). If so, we need to emit a semaphore. - * Returns true if we need to sync with another ring, false if - * not. - */ -bool radeon_fence_need_sync(struct radeon_fence *fence, int dst_ring) -{ - struct radeon_fence_driver *fdrv; - - if (!fence) { - return false; - } - - if (fence->ring == dst_ring) { - return false; - } - - /* we are protected by the ring mutex */ - fdrv = &fence->rdev->fence_drv[dst_ring]; - if (fence->seq <= fdrv->sync_seq[fence->ring]) { - return false; - } - - return true; -} - -/** - * radeon_fence_note_sync - record the sync point - * - * @fence: radeon fence object - * @dst_ring: which ring to check against - * - * Note the sequence number at which point the fence will - * be synced with the requested ring (all asics). - */ -void radeon_fence_note_sync(struct radeon_fence *fence, int dst_ring) -{ - struct radeon_fence_driver *dst, *src; - unsigned i; - - if (!fence) { - return; - } - - if (fence->ring == dst_ring) { - return; - } - - /* we are protected by the ring mutex */ - src = &fence->rdev->fence_drv[fence->ring]; - dst = &fence->rdev->fence_drv[dst_ring]; - for (i = 0; i < RADEON_NUM_RINGS; ++i) { - if (i == dst_ring) { - continue; - } - dst->sync_seq[i] = max(dst->sync_seq[i], src->sync_seq[i]); - } -} - -/** - * radeon_fence_driver_start_ring - make the fence driver - * ready for use on the requested ring. - * - * @rdev: radeon device pointer - * @ring: ring index to start the fence driver on - * - * Make the fence driver ready for processing (all asics). - * Not all asics have all rings, so each asic will only - * start the fence driver on the rings it has. - * Returns 0 for success, errors for failure. - */ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) { uint64_t index; @@ -786,49 +537,24 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) } rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4]; rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr + index; - radeon_fence_write(rdev, atomic64_read(&rdev->fence_drv[ring].last_seq), ring); + radeon_fence_write(rdev, rdev->fence_drv[ring].seq, ring); rdev->fence_drv[ring].initialized = true; dev_info(rdev->dev, "fence driver on ring %d use gpu addr 0x%016llx and cpu addr 0x%p\n", ring, rdev->fence_drv[ring].gpu_addr, rdev->fence_drv[ring].cpu_addr); return 0; } -/** - * radeon_fence_driver_init_ring - init the fence driver - * for the requested ring. - * - * @rdev: radeon device pointer - * @ring: ring index to start the fence driver on - * - * Init the fence driver for the requested ring (all asics). - * Helper function for radeon_fence_driver_init(). - */ static void radeon_fence_driver_init_ring(struct radeon_device *rdev, int ring) { - int i; - rdev->fence_drv[ring].scratch_reg = -1; rdev->fence_drv[ring].cpu_addr = NULL; rdev->fence_drv[ring].gpu_addr = 0; - for (i = 0; i < RADEON_NUM_RINGS; ++i) - rdev->fence_drv[ring].sync_seq[i] = 0; + rdev->fence_drv[ring].seq = 0; atomic64_set(&rdev->fence_drv[ring].last_seq, 0); rdev->fence_drv[ring].last_activity = jiffies; rdev->fence_drv[ring].initialized = false; } -/** - * radeon_fence_driver_init - init the fence driver - * for all possible rings. - * - * @rdev: radeon device pointer - * - * Init the fence driver for all possible rings (all asics). - * Not all asics have all rings, so each asic will only - * start the fence driver on the rings it has using - * radeon_fence_driver_start_ring(). - * Returns 0 for success. - */ int radeon_fence_driver_init(struct radeon_device *rdev) { int ring; @@ -843,14 +569,6 @@ int radeon_fence_driver_init(struct radeon_device *rdev) return 0; } -/** - * radeon_fence_driver_fini - tear down the fence driver - * for all possible rings. - * - * @rdev: radeon device pointer - * - * Tear down the fence driver for all possible rings (all asics). - */ void radeon_fence_driver_fini(struct radeon_device *rdev) { int ring; @@ -877,7 +595,7 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data) struct drm_info_node *node = (struct drm_info_node *)m->private; struct drm_device *dev = node->minor->dev; struct radeon_device *rdev = dev->dev_private; - int i, j; + int i; for (i = 0; i < RADEON_NUM_RINGS; ++i) { if (!rdev->fence_drv[i].initialized) @@ -886,14 +604,8 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data) seq_printf(m, "--- ring %d ---\n", i); seq_printf(m, "Last signaled fence 0x%016llx\n", (unsigned long long)atomic64_read(&rdev->fence_drv[i].last_seq)); - seq_printf(m, "Last emitted 0x%016llx\n", - rdev->fence_drv[i].sync_seq[i]); - - for (j = 0; j < RADEON_NUM_RINGS; ++j) { - if (i != j && rdev->fence_drv[j].initialized) - seq_printf(m, "Last sync to ring %d 0x%016llx\n", - j, rdev->fence_drv[i].sync_seq[j]); - } + seq_printf(m, "Last emitted 0x%016llx\n", + rdev->fence_drv[i].seq); } return 0; } diff --git a/trunk/drivers/gpu/drm/radeon/radeon_gart.c b/trunk/drivers/gpu/drm/radeon/radeon_gart.c index b3720054614d..84b648a7ddd8 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_gart.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_gart.c @@ -30,39 +30,9 @@ #include "radeon.h" #include "radeon_reg.h" -/* - * GART - * The GART (Graphics Aperture Remapping Table) is an aperture - * in the GPU's address space. System pages can be mapped into - * the aperture and look like contiguous pages from the GPU's - * perspective. A page table maps the pages in the aperture - * to the actual backing pages in system memory. - * - * Radeon GPUs support both an internal GART, as described above, - * and AGP. AGP works similarly, but the GART table is configured - * and maintained by the northbridge rather than the driver. - * Radeon hw has a separate AGP aperture that is programmed to - * point to the AGP aperture provided by the northbridge and the - * requests are passed through to the northbridge aperture. - * Both AGP and internal GART can be used at the same time, however - * that is not currently supported by the driver. - * - * This file handles the common internal GART management. - */ - /* * Common GART table functions. */ -/** - * radeon_gart_table_ram_alloc - allocate system ram for gart page table - * - * @rdev: radeon_device pointer - * - * Allocate system memory for GART page table - * (r1xx-r3xx, non-pcie r4xx, rs400). These asics require the - * gart table to be in system memory. - * Returns 0 for success, -ENOMEM for failure. - */ int radeon_gart_table_ram_alloc(struct radeon_device *rdev) { void *ptr; @@ -84,15 +54,6 @@ int radeon_gart_table_ram_alloc(struct radeon_device *rdev) return 0; } -/** - * radeon_gart_table_ram_free - free system ram for gart page table - * - * @rdev: radeon_device pointer - * - * Free system memory for GART page table - * (r1xx-r3xx, non-pcie r4xx, rs400). These asics require the - * gart table to be in system memory. - */ void radeon_gart_table_ram_free(struct radeon_device *rdev) { if (rdev->gart.ptr == NULL) { @@ -112,16 +73,6 @@ void radeon_gart_table_ram_free(struct radeon_device *rdev) rdev->gart.table_addr = 0; } -/** - * radeon_gart_table_vram_alloc - allocate vram for gart page table - * - * @rdev: radeon_device pointer - * - * Allocate video memory for GART page table - * (pcie r4xx, r5xx+). These asics require the - * gart table to be in video memory. - * Returns 0 for success, error for failure. - */ int radeon_gart_table_vram_alloc(struct radeon_device *rdev) { int r; @@ -137,16 +88,6 @@ int radeon_gart_table_vram_alloc(struct radeon_device *rdev) return 0; } -/** - * radeon_gart_table_vram_pin - pin gart page table in vram - * - * @rdev: radeon_device pointer - * - * Pin the GART page table in vram so it will not be moved - * by the memory manager (pcie r4xx, r5xx+). These asics require the - * gart table to be in video memory. - * Returns 0 for success, error for failure. - */ int radeon_gart_table_vram_pin(struct radeon_device *rdev) { uint64_t gpu_addr; @@ -169,14 +110,6 @@ int radeon_gart_table_vram_pin(struct radeon_device *rdev) return r; } -/** - * radeon_gart_table_vram_unpin - unpin gart page table in vram - * - * @rdev: radeon_device pointer - * - * Unpin the GART page table in vram (pcie r4xx, r5xx+). - * These asics require the gart table to be in video memory. - */ void radeon_gart_table_vram_unpin(struct radeon_device *rdev) { int r; @@ -193,15 +126,6 @@ void radeon_gart_table_vram_unpin(struct radeon_device *rdev) } } -/** - * radeon_gart_table_vram_free - free gart page table vram - * - * @rdev: radeon_device pointer - * - * Free the video memory used for the GART page table - * (pcie r4xx, r5xx+). These asics require the gart table to - * be in video memory. - */ void radeon_gart_table_vram_free(struct radeon_device *rdev) { if (rdev->gart.robj == NULL) { @@ -211,19 +135,12 @@ void radeon_gart_table_vram_free(struct radeon_device *rdev) radeon_bo_unref(&rdev->gart.robj); } + + + /* * Common gart functions. */ -/** - * radeon_gart_unbind - unbind pages from the gart page table - * - * @rdev: radeon_device pointer - * @offset: offset into the GPU's gart aperture - * @pages: number of pages to unbind - * - * Unbinds the requested pages from the gart page table and - * replaces them with the dummy page (all asics). - */ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, int pages) { @@ -255,19 +172,6 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, radeon_gart_tlb_flush(rdev); } -/** - * radeon_gart_bind - bind pages into the gart page table - * - * @rdev: radeon_device pointer - * @offset: offset into the GPU's gart aperture - * @pages: number of pages to bind - * @pagelist: pages to bind - * @dma_addr: DMA addresses of pages - * - * Binds the requested pages to the gart page table - * (all asics). - * Returns 0 for success, -EINVAL for failure. - */ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, int pages, struct page **pagelist, dma_addr_t *dma_addr) { @@ -299,14 +203,6 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, return 0; } -/** - * radeon_gart_restore - bind all pages in the gart page table - * - * @rdev: radeon_device pointer - * - * Binds all pages in the gart page table (all asics). - * Used to rebuild the gart table on device startup or resume. - */ void radeon_gart_restore(struct radeon_device *rdev) { int i, j, t; @@ -326,14 +222,6 @@ void radeon_gart_restore(struct radeon_device *rdev) radeon_gart_tlb_flush(rdev); } -/** - * radeon_gart_init - init the driver info for managing the gart - * - * @rdev: radeon_device pointer - * - * Allocate the dummy page and init the gart driver info (all asics). - * Returns 0 for success, error for failure. - */ int radeon_gart_init(struct radeon_device *rdev) { int r, i; @@ -374,13 +262,6 @@ int radeon_gart_init(struct radeon_device *rdev) return 0; } -/** - * radeon_gart_fini - tear down the driver info for managing the gart - * - * @rdev: radeon_device pointer - * - * Tear down the gart driver info and free the dummy page (all asics). - */ void radeon_gart_fini(struct radeon_device *rdev) { if (rdev->gart.pages && rdev->gart.pages_addr && rdev->gart.ready) { @@ -396,105 +277,36 @@ void radeon_gart_fini(struct radeon_device *rdev) radeon_dummy_page_fini(rdev); } -/* - * GPUVM - * GPUVM is similar to the legacy gart on older asics, however - * rather than there being a single global gart table - * for the entire GPU, there are multiple VM page tables active - * at any given time. The VM page tables can contain a mix - * vram pages and system memory pages and system memory pages - * can be mapped as snooped (cached system pages) or unsnooped - * (uncached system pages). - * Each VM has an ID associated with it and there is a page table - * associated with each VMID. When execting a command buffer, - * the kernel tells the the ring what VMID to use for that command - * buffer. VMIDs are allocated dynamically as commands are submitted. - * The userspace drivers maintain their own address space and the kernel - * sets up their pages tables accordingly when they submit their - * command buffers and a VMID is assigned. - * Cayman/Trinity support up to 8 active VMs at any given time; - * SI supports 16. - */ - /* * vm helpers * * TODO bind a default page at vm initialization for default address */ - -/** - * radeon_vm_manager_init - init the vm manager - * - * @rdev: radeon_device pointer - * - * Init the vm manager (cayman+). - * Returns 0 for success, error for failure. - */ int radeon_vm_manager_init(struct radeon_device *rdev) { - struct radeon_vm *vm; - struct radeon_bo_va *bo_va; int r; - if (!rdev->vm_manager.enabled) { - /* mark first vm as always in use, it's the system one */ - /* allocate enough for 2 full VM pts */ - r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager, - rdev->vm_manager.max_pfn * 8 * 2, - RADEON_GEM_DOMAIN_VRAM); - if (r) { - dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n", - (rdev->vm_manager.max_pfn * 8) >> 10); - return r; - } - - r = rdev->vm_manager.funcs->init(rdev); - if (r) - return r; - - rdev->vm_manager.enabled = true; + rdev->vm_manager.enabled = false; - r = radeon_sa_bo_manager_start(rdev, &rdev->vm_manager.sa_manager); - if (r) - return r; + /* mark first vm as always in use, it's the system one */ + /* allocate enough for 2 full VM pts */ + r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager, + rdev->vm_manager.max_pfn * 8 * 2, + RADEON_GEM_DOMAIN_VRAM); + if (r) { + dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n", + (rdev->vm_manager.max_pfn * 8) >> 10); + return r; } - /* restore page table */ - list_for_each_entry(vm, &rdev->vm_manager.lru_vm, list) { - if (vm->id == -1) - continue; - - list_for_each_entry(bo_va, &vm->va, vm_list) { - struct ttm_mem_reg *mem = NULL; - if (bo_va->valid) - mem = &bo_va->bo->tbo.mem; - - bo_va->valid = false; - r = radeon_vm_bo_update_pte(rdev, vm, bo_va->bo, mem); - if (r) { - DRM_ERROR("Failed to update pte for vm %d!\n", vm->id); - } - } + r = rdev->vm_manager.funcs->init(rdev); + if (r == 0) + rdev->vm_manager.enabled = true; - r = rdev->vm_manager.funcs->bind(rdev, vm, vm->id); - if (r) { - DRM_ERROR("Failed to bind vm %d!\n", vm->id); - } - } - return 0; + return r; } -/* global mutex must be lock */ -/** - * radeon_vm_unbind_locked - unbind a specific vm - * - * @rdev: radeon_device pointer - * @vm: vm to unbind - * - * Unbind the requested vm (cayman+). - * Wait for use of the VM to finish, then unbind the page table, - * and free the page table memory. - */ +/* cs mutex must be lock */ static void radeon_vm_unbind_locked(struct radeon_device *rdev, struct radeon_vm *vm) { @@ -505,21 +317,10 @@ static void radeon_vm_unbind_locked(struct radeon_device *rdev, } /* wait for vm use to end */ - while (vm->fence) { - int r; - r = radeon_fence_wait(vm->fence, false); - if (r) - DRM_ERROR("error while waiting for fence: %d\n", r); - if (r == -EDEADLK) { - mutex_unlock(&rdev->vm_manager.lock); - r = radeon_gpu_reset(rdev); - mutex_lock(&rdev->vm_manager.lock); - if (!r) - continue; - } - break; + if (vm->fence) { + radeon_fence_wait(vm->fence, false); + radeon_fence_unref(&vm->fence); } - radeon_fence_unref(&vm->fence); /* hw unbind */ rdev->vm_manager.funcs->unbind(rdev, vm); @@ -534,42 +335,39 @@ static void radeon_vm_unbind_locked(struct radeon_device *rdev, } } -/** - * radeon_vm_manager_fini - tear down the vm manager - * - * @rdev: radeon_device pointer - * - * Tear down the VM manager (cayman+). - */ void radeon_vm_manager_fini(struct radeon_device *rdev) { - struct radeon_vm *vm, *tmp; - - if (!rdev->vm_manager.enabled) + if (rdev->vm_manager.sa_manager.bo == NULL) return; + radeon_vm_manager_suspend(rdev); + rdev->vm_manager.funcs->fini(rdev); + radeon_sa_bo_manager_fini(rdev, &rdev->vm_manager.sa_manager); + rdev->vm_manager.enabled = false; +} + +int radeon_vm_manager_start(struct radeon_device *rdev) +{ + if (rdev->vm_manager.sa_manager.bo == NULL) { + return -EINVAL; + } + return radeon_sa_bo_manager_start(rdev, &rdev->vm_manager.sa_manager); +} + +int radeon_vm_manager_suspend(struct radeon_device *rdev) +{ + struct radeon_vm *vm, *tmp; - mutex_lock(&rdev->vm_manager.lock); + radeon_mutex_lock(&rdev->cs_mutex); /* unbind all active vm */ list_for_each_entry_safe(vm, tmp, &rdev->vm_manager.lru_vm, list) { radeon_vm_unbind_locked(rdev, vm); } rdev->vm_manager.funcs->fini(rdev); - mutex_unlock(&rdev->vm_manager.lock); - - radeon_sa_bo_manager_suspend(rdev, &rdev->vm_manager.sa_manager); - radeon_sa_bo_manager_fini(rdev, &rdev->vm_manager.sa_manager); - rdev->vm_manager.enabled = false; + radeon_mutex_unlock(&rdev->cs_mutex); + return radeon_sa_bo_manager_suspend(rdev, &rdev->vm_manager.sa_manager); } -/* global mutex must be locked */ -/** - * radeon_vm_unbind - locked version of unbind - * - * @rdev: radeon_device pointer - * @vm: vm to unbind - * - * Locked version that wraps radeon_vm_unbind_locked (cayman+). - */ +/* cs mutex must be lock */ void radeon_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm) { mutex_lock(&vm->mutex); @@ -577,19 +375,7 @@ void radeon_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm) mutex_unlock(&vm->mutex); } -/* global and local mutex must be locked */ -/** - * radeon_vm_bind - bind a page table to a VMID - * - * @rdev: radeon_device pointer - * @vm: vm to bind - * - * Bind the requested vm (cayman+). - * Suballocate memory for the page table, allocate a VMID - * and bind the page table to it, and finally start to populate - * the page table. - * Returns 0 for success, error for failure. - */ +/* cs mutex must be lock & vm mutex must be lock */ int radeon_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm) { struct radeon_vm *vm_evict; @@ -652,20 +438,6 @@ int radeon_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm) } /* object have to be reserved */ -/** - * radeon_vm_bo_add - add a bo to a specific vm - * - * @rdev: radeon_device pointer - * @vm: requested vm - * @bo: radeon buffer object - * @offset: requested offset of the buffer in the VM address space - * @flags: attributes of pages (read/write/valid/etc.) - * - * Add @bo into the requested vm (cayman+). - * Add @bo to the list of bos associated with the vm and validate - * the offset requested within the vm address space. - * Returns 0 for success, error for failure. - */ int radeon_vm_bo_add(struct radeon_device *rdev, struct radeon_vm *vm, struct radeon_bo *bo, @@ -707,7 +479,7 @@ int radeon_vm_bo_add(struct radeon_device *rdev, if (last_pfn > vm->last_pfn) { /* release mutex and lock in right order */ mutex_unlock(&vm->mutex); - mutex_lock(&rdev->vm_manager.lock); + radeon_mutex_lock(&rdev->cs_mutex); mutex_lock(&vm->mutex); /* and check again */ if (last_pfn > vm->last_pfn) { @@ -716,7 +488,7 @@ int radeon_vm_bo_add(struct radeon_device *rdev, radeon_vm_unbind_locked(rdev, vm); vm->last_pfn = (last_pfn + align) & ~align; } - mutex_unlock(&rdev->vm_manager.lock); + radeon_mutex_unlock(&rdev->cs_mutex); } head = &vm->va; last_offset = 0; @@ -743,17 +515,6 @@ int radeon_vm_bo_add(struct radeon_device *rdev, return 0; } -/** - * radeon_vm_get_addr - get the physical address of the page - * - * @rdev: radeon_device pointer - * @mem: ttm mem - * @pfn: pfn - * - * Look up the physical address of the page that the pte resolves - * to (cayman+). - * Returns the physical address of the page. - */ static u64 radeon_vm_get_addr(struct radeon_device *rdev, struct ttm_mem_reg *mem, unsigned pfn) @@ -782,18 +543,7 @@ static u64 radeon_vm_get_addr(struct radeon_device *rdev, return addr; } -/* object have to be reserved & global and local mutex must be locked */ -/** - * radeon_vm_bo_update_pte - map a bo into the vm page table - * - * @rdev: radeon_device pointer - * @vm: requested vm - * @bo: radeon buffer object - * @mem: ttm mem - * - * Fill in the page table entries for @bo (cayman+). - * Returns 0 for success, -EINVAL for failure. - */ +/* object have to be reserved & cs mutex took & vm mutex took */ int radeon_vm_bo_update_pte(struct radeon_device *rdev, struct radeon_vm *vm, struct radeon_bo *bo, @@ -842,18 +592,6 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev, } /* object have to be reserved */ -/** - * radeon_vm_bo_rmv - remove a bo to a specific vm - * - * @rdev: radeon_device pointer - * @vm: requested vm - * @bo: radeon buffer object - * - * Remove @bo from the requested vm (cayman+). - * Remove @bo from the list of bos associated with the vm and - * remove the ptes for @bo in the page table. - * Returns 0 for success. - */ int radeon_vm_bo_rmv(struct radeon_device *rdev, struct radeon_vm *vm, struct radeon_bo *bo) @@ -864,10 +602,10 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev, if (bo_va == NULL) return 0; - mutex_lock(&rdev->vm_manager.lock); + radeon_mutex_lock(&rdev->cs_mutex); mutex_lock(&vm->mutex); radeon_vm_bo_update_pte(rdev, vm, bo, NULL); - mutex_unlock(&rdev->vm_manager.lock); + radeon_mutex_unlock(&rdev->cs_mutex); list_del(&bo_va->vm_list); mutex_unlock(&vm->mutex); list_del(&bo_va->bo_list); @@ -876,15 +614,6 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev, return 0; } -/** - * radeon_vm_bo_invalidate - mark the bo as invalid - * - * @rdev: radeon_device pointer - * @vm: requested vm - * @bo: radeon buffer object - * - * Mark @bo as invalid (cayman+). - */ void radeon_vm_bo_invalidate(struct radeon_device *rdev, struct radeon_bo *bo) { @@ -896,17 +625,6 @@ void radeon_vm_bo_invalidate(struct radeon_device *rdev, } } -/** - * radeon_vm_init - initialize a vm instance - * - * @rdev: radeon_device pointer - * @vm: requested vm - * - * Init @vm (cayman+). - * Map the IB pool and any other shared objects into the VM - * by default as it's used by all VMs. - * Returns 0 for success, error for failure. - */ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) { int r; @@ -933,24 +651,15 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) return r; } -/** - * radeon_vm_init - tear down a vm instance - * - * @rdev: radeon_device pointer - * @vm: requested vm - * - * Tear down @vm (cayman+). - * Unbind the VM and remove all bos from the vm bo list - */ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) { struct radeon_bo_va *bo_va, *tmp; int r; - mutex_lock(&rdev->vm_manager.lock); + radeon_mutex_lock(&rdev->cs_mutex); mutex_lock(&vm->mutex); radeon_vm_unbind_locked(rdev, vm); - mutex_unlock(&rdev->vm_manager.lock); + radeon_mutex_unlock(&rdev->cs_mutex); /* remove all bo */ r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_gem.c b/trunk/drivers/gpu/drm/radeon/radeon_gem.c index 84d045245739..21ec9f5653ce 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_gem.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_gem.c @@ -159,9 +159,11 @@ void radeon_gem_object_close(struct drm_gem_object *obj, static int radeon_gem_handle_lockup(struct radeon_device *rdev, int r) { if (r == -EDEADLK) { + radeon_mutex_lock(&rdev->cs_mutex); r = radeon_gpu_reset(rdev); if (!r) r = -EAGAIN; + radeon_mutex_unlock(&rdev->cs_mutex); } return r; } @@ -215,14 +217,12 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data, uint32_t handle; int r; - down_read(&rdev->exclusive_lock); /* create a gem object to contain this object in */ args->size = roundup(args->size, PAGE_SIZE); r = radeon_gem_object_create(rdev, args->size, args->alignment, args->initial_domain, false, false, &gobj); if (r) { - up_read(&rdev->exclusive_lock); r = radeon_gem_handle_lockup(rdev, r); return r; } @@ -230,12 +230,10 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data, /* drop reference from allocate - handle holds it now */ drm_gem_object_unreference_unlocked(gobj); if (r) { - up_read(&rdev->exclusive_lock); r = radeon_gem_handle_lockup(rdev, r); return r; } args->handle = handle; - up_read(&rdev->exclusive_lock); return 0; } @@ -244,7 +242,6 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, { /* transition the BO to a domain - * just validate the BO into a certain domain */ - struct radeon_device *rdev = dev->dev_private; struct drm_radeon_gem_set_domain *args = data; struct drm_gem_object *gobj; struct radeon_bo *robj; @@ -252,12 +249,10 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, /* for now if someone requests domain CPU - * just make sure the buffer is finished with */ - down_read(&rdev->exclusive_lock); /* just do a BO wait for now */ gobj = drm_gem_object_lookup(dev, filp, args->handle); if (gobj == NULL) { - up_read(&rdev->exclusive_lock); return -ENOENT; } robj = gem_to_radeon_bo(gobj); @@ -265,7 +260,6 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain); drm_gem_object_unreference_unlocked(gobj); - up_read(&rdev->exclusive_lock); r = radeon_gem_handle_lockup(robj->rdev, r); return r; } diff --git a/trunk/drivers/gpu/drm/radeon/radeon_irq_kms.c b/trunk/drivers/gpu/drm/radeon/radeon_irq_kms.c index afaa1727abd2..5df58d1aba06 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -32,17 +32,6 @@ #include "radeon.h" #include "atom.h" -#define RADEON_WAIT_IDLE_TIMEOUT 200 - -/** - * radeon_driver_irq_handler_kms - irq handler for KMS - * - * @DRM_IRQ_ARGS: args - * - * This is the irq handler for the radeon KMS driver (all asics). - * radeon_irq_process is a macro that points to the per-asic - * irq handler callback. - */ irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; @@ -54,17 +43,6 @@ irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) /* * Handle hotplug events outside the interrupt handler proper. */ -/** - * radeon_hotplug_work_func - display hotplug work handler - * - * @work: work struct - * - * This is the hot plug event work handler (all asics). - * The work gets scheduled from the irq handler if there - * was a hot plug interrupt. It walks the connector table - * and calls the hotplug handler for each one, then sends - * a drm hotplug event to alert userspace. - */ static void radeon_hotplug_work_func(struct work_struct *work) { struct radeon_device *rdev = container_of(work, struct radeon_device, @@ -81,94 +59,61 @@ static void radeon_hotplug_work_func(struct work_struct *work) drm_helper_hpd_irq_event(dev); } -/** - * radeon_driver_irq_preinstall_kms - drm irq preinstall callback - * - * @dev: drm dev pointer - * - * Gets the hw ready to enable irqs (all asics). - * This function disables all interrupt sources on the GPU. - */ void radeon_driver_irq_preinstall_kms(struct drm_device *dev) { struct radeon_device *rdev = dev->dev_private; - unsigned long irqflags; unsigned i; - spin_lock_irqsave(&rdev->irq.lock, irqflags); /* Disable *all* interrupts */ for (i = 0; i < RADEON_NUM_RINGS; i++) - atomic_set(&rdev->irq.ring_int[i], 0); + rdev->irq.sw_int[i] = false; rdev->irq.gui_idle = false; for (i = 0; i < RADEON_MAX_HPD_PINS; i++) rdev->irq.hpd[i] = false; for (i = 0; i < RADEON_MAX_CRTCS; i++) { rdev->irq.crtc_vblank_int[i] = false; - atomic_set(&rdev->irq.pflip[i], 0); + rdev->irq.pflip[i] = false; rdev->irq.afmt[i] = false; } radeon_irq_set(rdev); - spin_unlock_irqrestore(&rdev->irq.lock, irqflags); /* Clear bits */ radeon_irq_process(rdev); } -/** - * radeon_driver_irq_postinstall_kms - drm irq preinstall callback - * - * @dev: drm dev pointer - * - * Handles stuff to be done after enabling irqs (all asics). - * Returns 0 on success. - */ int radeon_driver_irq_postinstall_kms(struct drm_device *dev) { + struct radeon_device *rdev = dev->dev_private; + unsigned i; + dev->max_vblank_count = 0x001fffff; + for (i = 0; i < RADEON_NUM_RINGS; i++) + rdev->irq.sw_int[i] = true; + radeon_irq_set(rdev); return 0; } -/** - * radeon_driver_irq_uninstall_kms - drm irq uninstall callback - * - * @dev: drm dev pointer - * - * This function disables all interrupt sources on the GPU (all asics). - */ void radeon_driver_irq_uninstall_kms(struct drm_device *dev) { struct radeon_device *rdev = dev->dev_private; - unsigned long irqflags; unsigned i; if (rdev == NULL) { return; } - spin_lock_irqsave(&rdev->irq.lock, irqflags); /* Disable *all* interrupts */ for (i = 0; i < RADEON_NUM_RINGS; i++) - atomic_set(&rdev->irq.ring_int[i], 0); + rdev->irq.sw_int[i] = false; rdev->irq.gui_idle = false; for (i = 0; i < RADEON_MAX_HPD_PINS; i++) rdev->irq.hpd[i] = false; for (i = 0; i < RADEON_MAX_CRTCS; i++) { rdev->irq.crtc_vblank_int[i] = false; - atomic_set(&rdev->irq.pflip[i], 0); + rdev->irq.pflip[i] = false; rdev->irq.afmt[i] = false; } radeon_irq_set(rdev); - spin_unlock_irqrestore(&rdev->irq.lock, irqflags); } -/** - * radeon_msi_ok - asic specific msi checks - * - * @rdev: radeon device pointer - * - * Handles asic specific MSI checks to determine if - * MSIs should be enabled on a particular chip (all asics). - * Returns true if MSIs should be enabled, false if MSIs - * should not be enabled. - */ static bool radeon_msi_ok(struct radeon_device *rdev) { /* RV370/RV380 was first asic with MSI support */ @@ -221,22 +166,17 @@ static bool radeon_msi_ok(struct radeon_device *rdev) return true; } -/** - * radeon_irq_kms_init - init driver interrupt info - * - * @rdev: radeon device pointer - * - * Sets up the work irq handlers, vblank init, MSIs, etc. (all asics). - * Returns 0 for success, error for failure. - */ int radeon_irq_kms_init(struct radeon_device *rdev) { + int i; int r = 0; INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func); INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi); - spin_lock_init(&rdev->irq.lock); + spin_lock_init(&rdev->irq.sw_lock); + for (i = 0; i < rdev->num_crtc; i++) + spin_lock_init(&rdev->irq.pflip_lock[i]); r = drm_vblank_init(rdev->ddev, rdev->num_crtc); if (r) { return r; @@ -261,13 +201,6 @@ int radeon_irq_kms_init(struct radeon_device *rdev) return 0; } -/** - * radeon_irq_kms_fini - tear down driver interrrupt info - * - * @rdev: radeon device pointer - * - * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics). - */ void radeon_irq_kms_fini(struct radeon_device *rdev) { drm_vblank_cleanup(rdev->ddev); @@ -280,63 +213,31 @@ void radeon_irq_kms_fini(struct radeon_device *rdev) flush_work_sync(&rdev->hotplug_work); } -/** - * radeon_irq_kms_sw_irq_get - enable software interrupt - * - * @rdev: radeon device pointer - * @ring: ring whose interrupt you want to enable - * - * Enables the software interrupt for a specific ring (all asics). - * The software interrupt is generally used to signal a fence on - * a particular ring. - */ void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring) { unsigned long irqflags; - if (!rdev->ddev->irq_enabled) - return; - - if (atomic_inc_return(&rdev->irq.ring_int[ring]) == 1) { - spin_lock_irqsave(&rdev->irq.lock, irqflags); + spin_lock_irqsave(&rdev->irq.sw_lock, irqflags); + if (rdev->ddev->irq_enabled && (++rdev->irq.sw_refcount[ring] == 1)) { + rdev->irq.sw_int[ring] = true; radeon_irq_set(rdev); - spin_unlock_irqrestore(&rdev->irq.lock, irqflags); } + spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags); } -/** - * radeon_irq_kms_sw_irq_put - disable software interrupt - * - * @rdev: radeon device pointer - * @ring: ring whose interrupt you want to disable - * - * Disables the software interrupt for a specific ring (all asics). - * The software interrupt is generally used to signal a fence on - * a particular ring. - */ void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring) { unsigned long irqflags; - if (!rdev->ddev->irq_enabled) - return; - - if (atomic_dec_and_test(&rdev->irq.ring_int[ring])) { - spin_lock_irqsave(&rdev->irq.lock, irqflags); + spin_lock_irqsave(&rdev->irq.sw_lock, irqflags); + BUG_ON(rdev->ddev->irq_enabled && rdev->irq.sw_refcount[ring] <= 0); + if (rdev->ddev->irq_enabled && (--rdev->irq.sw_refcount[ring] == 0)) { + rdev->irq.sw_int[ring] = false; radeon_irq_set(rdev); - spin_unlock_irqrestore(&rdev->irq.lock, irqflags); } + spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags); } -/** - * radeon_irq_kms_pflip_irq_get - enable pageflip interrupt - * - * @rdev: radeon device pointer - * @crtc: crtc whose interrupt you want to enable - * - * Enables the pageflip interrupt for a specific crtc (all asics). - * For pageflips we use the vblank interrupt source. - */ void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) { unsigned long irqflags; @@ -344,25 +245,14 @@ void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) if (crtc < 0 || crtc >= rdev->num_crtc) return; - if (!rdev->ddev->irq_enabled) - return; - - if (atomic_inc_return(&rdev->irq.pflip[crtc]) == 1) { - spin_lock_irqsave(&rdev->irq.lock, irqflags); + spin_lock_irqsave(&rdev->irq.pflip_lock[crtc], irqflags); + if (rdev->ddev->irq_enabled && (++rdev->irq.pflip_refcount[crtc] == 1)) { + rdev->irq.pflip[crtc] = true; radeon_irq_set(rdev); - spin_unlock_irqrestore(&rdev->irq.lock, irqflags); } + spin_unlock_irqrestore(&rdev->irq.pflip_lock[crtc], irqflags); } -/** - * radeon_irq_kms_pflip_irq_put - disable pageflip interrupt - * - * @rdev: radeon device pointer - * @crtc: crtc whose interrupt you want to disable - * - * Disables the pageflip interrupt for a specific crtc (all asics). - * For pageflips we use the vblank interrupt source. - */ void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) { unsigned long irqflags; @@ -370,121 +260,12 @@ void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) if (crtc < 0 || crtc >= rdev->num_crtc) return; - if (!rdev->ddev->irq_enabled) - return; - - if (atomic_dec_and_test(&rdev->irq.pflip[crtc])) { - spin_lock_irqsave(&rdev->irq.lock, irqflags); + spin_lock_irqsave(&rdev->irq.pflip_lock[crtc], irqflags); + BUG_ON(rdev->ddev->irq_enabled && rdev->irq.pflip_refcount[crtc] <= 0); + if (rdev->ddev->irq_enabled && (--rdev->irq.pflip_refcount[crtc] == 0)) { + rdev->irq.pflip[crtc] = false; radeon_irq_set(rdev); - spin_unlock_irqrestore(&rdev->irq.lock, irqflags); } + spin_unlock_irqrestore(&rdev->irq.pflip_lock[crtc], irqflags); } -/** - * radeon_irq_kms_enable_afmt - enable audio format change interrupt - * - * @rdev: radeon device pointer - * @block: afmt block whose interrupt you want to enable - * - * Enables the afmt change interrupt for a specific afmt block (all asics). - */ -void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block) -{ - unsigned long irqflags; - - spin_lock_irqsave(&rdev->irq.lock, irqflags); - rdev->irq.afmt[block] = true; - radeon_irq_set(rdev); - spin_unlock_irqrestore(&rdev->irq.lock, irqflags); - -} - -/** - * radeon_irq_kms_disable_afmt - disable audio format change interrupt - * - * @rdev: radeon device pointer - * @block: afmt block whose interrupt you want to disable - * - * Disables the afmt change interrupt for a specific afmt block (all asics). - */ -void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block) -{ - unsigned long irqflags; - - spin_lock_irqsave(&rdev->irq.lock, irqflags); - rdev->irq.afmt[block] = false; - radeon_irq_set(rdev); - spin_unlock_irqrestore(&rdev->irq.lock, irqflags); -} - -/** - * radeon_irq_kms_enable_hpd - enable hotplug detect interrupt - * - * @rdev: radeon device pointer - * @hpd_mask: mask of hpd pins you want to enable. - * - * Enables the hotplug detect interrupt for a specific hpd pin (all asics). - */ -void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask) -{ - unsigned long irqflags; - int i; - - spin_lock_irqsave(&rdev->irq.lock, irqflags); - for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) - rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i)); - radeon_irq_set(rdev); - spin_unlock_irqrestore(&rdev->irq.lock, irqflags); -} - -/** - * radeon_irq_kms_disable_hpd - disable hotplug detect interrupt - * - * @rdev: radeon device pointer - * @hpd_mask: mask of hpd pins you want to disable. - * - * Disables the hotplug detect interrupt for a specific hpd pin (all asics). - */ -void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask) -{ - unsigned long irqflags; - int i; - - spin_lock_irqsave(&rdev->irq.lock, irqflags); - for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) - rdev->irq.hpd[i] &= !(hpd_mask & (1 << i)); - radeon_irq_set(rdev); - spin_unlock_irqrestore(&rdev->irq.lock, irqflags); -} - -/** - * radeon_irq_kms_wait_gui_idle - waits for drawing engine to be idle - * - * @rdev: radeon device pointer - * - * Enabled the GUI idle interrupt and waits for it to fire (r6xx+). - * This is currently used to make sure the 3D engine is idle for power - * management, but should be replaces with proper fence waits. - * GUI idle interrupts don't work very well on pre-r6xx hw and it also - * does not take into account other aspects of the chip that may be busy. - * DO NOT USE GOING FORWARD. - */ -int radeon_irq_kms_wait_gui_idle(struct radeon_device *rdev) -{ - unsigned long irqflags; - int r; - - spin_lock_irqsave(&rdev->irq.lock, irqflags); - rdev->irq.gui_idle = true; - radeon_irq_set(rdev); - spin_unlock_irqrestore(&rdev->irq.lock, irqflags); - - r = wait_event_timeout(rdev->irq.idle_queue, radeon_gui_idle(rdev), - msecs_to_jiffies(RADEON_WAIT_IDLE_TIMEOUT)); - - spin_lock_irqsave(&rdev->irq.lock, irqflags); - rdev->irq.gui_idle = false; - radeon_irq_set(rdev); - spin_unlock_irqrestore(&rdev->irq.lock, irqflags); - return r; -} diff --git a/trunk/drivers/gpu/drm/radeon/radeon_kms.c b/trunk/drivers/gpu/drm/radeon/radeon_kms.c index 1d73f16b5d97..5c58d7d90cb2 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_kms.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_kms.c @@ -33,17 +33,6 @@ #include #include -/** - * radeon_driver_unload_kms - Main unload function for KMS. - * - * @dev: drm dev pointer - * - * This is the main unload function for KMS (all asics). - * It calls radeon_modeset_fini() to tear down the - * displays, and radeon_device_fini() to tear down - * the rest of the device (CP, writeback, etc.). - * Returns 0 on success. - */ int radeon_driver_unload_kms(struct drm_device *dev) { struct radeon_device *rdev = dev->dev_private; @@ -57,19 +46,6 @@ int radeon_driver_unload_kms(struct drm_device *dev) return 0; } -/** - * radeon_driver_load_kms - Main load function for KMS. - * - * @dev: drm dev pointer - * @flags: device flags - * - * This is the main load function for KMS (all asics). - * It calls radeon_device_init() to set up the non-display - * parts of the chip (asic init, CP, writeback, etc.), and - * radeon_modeset_init() to set up the display parts - * (crtcs, encoders, hotplug detect, etc.). - * Returns 0 on success, error on failure. - */ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) { struct radeon_device *rdev; @@ -120,16 +96,6 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) return r; } -/** - * radeon_set_filp_rights - Set filp right. - * - * @dev: drm dev pointer - * @owner: drm file - * @applier: drm file - * @value: value - * - * Sets the filp rights for the device (all asics). - */ static void radeon_set_filp_rights(struct drm_device *dev, struct drm_file **owner, struct drm_file *applier, @@ -152,18 +118,6 @@ static void radeon_set_filp_rights(struct drm_device *dev, /* * Userspace get information ioctl */ -/** - * radeon_info_ioctl - answer a device specific request. - * - * @rdev: radeon device pointer - * @data: request object - * @filp: drm filp - * - * This function is used to pass device specific parameters to the userspace - * drivers. Examples include: pci device id, pipeline parms, tiling params, - * etc. (all asics). - * Returns 0 on success, -EINVAL on failure. - */ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct radeon_device *rdev = dev->dev_private; @@ -347,40 +301,16 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) /* * Outdated mess for old drm with Xorg being in charge (void function now). */ -/** - * radeon_driver_firstopen_kms - drm callback for first open - * - * @dev: drm dev pointer - * - * Nothing to be done for KMS (all asics). - * Returns 0 on success. - */ int radeon_driver_firstopen_kms(struct drm_device *dev) { return 0; } -/** - * radeon_driver_firstopen_kms - drm callback for last close - * - * @dev: drm dev pointer - * - * Switch vga switcheroo state after last close (all asics). - */ void radeon_driver_lastclose_kms(struct drm_device *dev) { vga_switcheroo_process_delayed_switch(); } -/** - * radeon_driver_open_kms - drm callback for open - * - * @dev: drm dev pointer - * @file_priv: drm file - * - * On device open, init vm on cayman+ (all asics). - * Returns 0 on success, error on failure. - */ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) { struct radeon_device *rdev = dev->dev_private; @@ -409,14 +339,6 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) return 0; } -/** - * radeon_driver_postclose_kms - drm callback for post close - * - * @dev: drm dev pointer - * @file_priv: drm file - * - * On device post close, tear down vm on cayman+ (all asics). - */ void radeon_driver_postclose_kms(struct drm_device *dev, struct drm_file *file_priv) { @@ -432,15 +354,6 @@ void radeon_driver_postclose_kms(struct drm_device *dev, } } -/** - * radeon_driver_preclose_kms - drm callback for pre close - * - * @dev: drm dev pointer - * @file_priv: drm file - * - * On device pre close, tear down hyperz and cmask filps on r1xx-r5xx - * (all asics). - */ void radeon_driver_preclose_kms(struct drm_device *dev, struct drm_file *file_priv) { @@ -454,15 +367,6 @@ void radeon_driver_preclose_kms(struct drm_device *dev, /* * VBlank related functions. */ -/** - * radeon_get_vblank_counter_kms - get frame count - * - * @dev: drm dev pointer - * @crtc: crtc to get the frame count from - * - * Gets the frame count on the requested crtc (all asics). - * Returns frame count on success, -EINVAL on failure. - */ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) { struct radeon_device *rdev = dev->dev_private; @@ -475,70 +379,34 @@ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) return radeon_get_vblank_counter(rdev, crtc); } -/** - * radeon_enable_vblank_kms - enable vblank interrupt - * - * @dev: drm dev pointer - * @crtc: crtc to enable vblank interrupt for - * - * Enable the interrupt on the requested crtc (all asics). - * Returns 0 on success, -EINVAL on failure. - */ int radeon_enable_vblank_kms(struct drm_device *dev, int crtc) { struct radeon_device *rdev = dev->dev_private; - unsigned long irqflags; - int r; if (crtc < 0 || crtc >= rdev->num_crtc) { DRM_ERROR("Invalid crtc %d\n", crtc); return -EINVAL; } - spin_lock_irqsave(&rdev->irq.lock, irqflags); rdev->irq.crtc_vblank_int[crtc] = true; - r = radeon_irq_set(rdev); - spin_unlock_irqrestore(&rdev->irq.lock, irqflags); - return r; + + return radeon_irq_set(rdev); } -/** - * radeon_disable_vblank_kms - disable vblank interrupt - * - * @dev: drm dev pointer - * @crtc: crtc to disable vblank interrupt for - * - * Disable the interrupt on the requested crtc (all asics). - */ void radeon_disable_vblank_kms(struct drm_device *dev, int crtc) { struct radeon_device *rdev = dev->dev_private; - unsigned long irqflags; if (crtc < 0 || crtc >= rdev->num_crtc) { DRM_ERROR("Invalid crtc %d\n", crtc); return; } - spin_lock_irqsave(&rdev->irq.lock, irqflags); rdev->irq.crtc_vblank_int[crtc] = false; + radeon_irq_set(rdev); - spin_unlock_irqrestore(&rdev->irq.lock, irqflags); } -/** - * radeon_get_vblank_timestamp_kms - get vblank timestamp - * - * @dev: drm dev pointer - * @crtc: crtc to get the timestamp for - * @max_error: max error - * @vblank_time: time value - * @flags: flags passed to the driver - * - * Gets the timestamp on the requested crtc based on the - * scanout position. (all asics). - * Returns postive status flags on success, negative error on failure. - */ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, int *max_error, struct timeval *vblank_time, diff --git a/trunk/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/trunk/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index d5fd615897ec..210317c7045e 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/trunk/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) } static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) diff --git a/trunk/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/trunk/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 670e9910f869..a0c82229e8f0 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -244,7 +244,7 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, } static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_mode.h b/trunk/drivers/gpu/drm/radeon/radeon_mode.h index f380d59c5763..5b10ffd7bb2f 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_mode.h +++ b/trunk/drivers/gpu/drm/radeon/radeon_mode.h @@ -488,7 +488,7 @@ extern void radeon_connector_hotplug(struct drm_connector *connector); extern int radeon_dp_mode_valid_helper(struct drm_connector *connector, struct drm_display_mode *mode); extern void radeon_dp_set_link_config(struct drm_connector *connector, - const struct drm_display_mode *mode); + struct drm_display_mode *mode); extern void radeon_dp_link_train(struct drm_encoder *encoder, struct drm_connector *connector); extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector); @@ -678,7 +678,7 @@ void radeon_enc_destroy(struct drm_encoder *encoder); void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj); void radeon_combios_asic_init(struct drm_device *dev); bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); void radeon_panel_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_object.c b/trunk/drivers/gpu/drm/radeon/radeon_object.c index 1f1a4c803c1d..830f1a7b486f 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_object.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_object.c @@ -115,7 +115,9 @@ int radeon_bo_create(struct radeon_device *rdev, size = ALIGN(size, PAGE_SIZE); - rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; + if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) { + rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; + } if (kernel) { type = ttm_bo_type_kernel; } else if (sg) { @@ -136,6 +138,7 @@ int radeon_bo_create(struct radeon_device *rdev, acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size, sizeof(struct radeon_bo)); +retry: bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); if (bo == NULL) return -ENOMEM; @@ -149,15 +152,13 @@ int radeon_bo_create(struct radeon_device *rdev, bo->surface_reg = -1; INIT_LIST_HEAD(&bo->list); INIT_LIST_HEAD(&bo->va); - -retry: radeon_ttm_placement_from_domain(bo, domain); /* Kernel allocation are uninterruptible */ - down_read(&rdev->pm.mclk_lock); + mutex_lock(&rdev->vram_mutex); r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type, &bo->placement, page_align, 0, !kernel, NULL, acc_size, sg, &radeon_ttm_bo_destroy); - up_read(&rdev->pm.mclk_lock); + mutex_unlock(&rdev->vram_mutex); if (unlikely(r != 0)) { if (r != -ERESTARTSYS) { if (domain == RADEON_GEM_DOMAIN_VRAM) { @@ -218,9 +219,9 @@ void radeon_bo_unref(struct radeon_bo **bo) return; rdev = (*bo)->rdev; tbo = &((*bo)->tbo); - down_read(&rdev->pm.mclk_lock); + mutex_lock(&rdev->vram_mutex); ttm_bo_unref(&tbo); - up_read(&rdev->pm.mclk_lock); + mutex_unlock(&rdev->vram_mutex); if (tbo == NULL) *bo = NULL; } diff --git a/trunk/drivers/gpu/drm/radeon/radeon_pm.c b/trunk/drivers/gpu/drm/radeon/radeon_pm.c index 7ae606600107..5b37e283ec38 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_pm.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_pm.c @@ -34,6 +34,7 @@ #define RADEON_IDLE_LOOP_MS 100 #define RADEON_RECLOCK_DELAY_MS 200 #define RADEON_WAIT_VBLANK_TIMEOUT 200 +#define RADEON_WAIT_IDLE_TIMEOUT 200 static const char *radeon_pm_state_type_name[5] = { "Default", @@ -250,14 +251,21 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) return; mutex_lock(&rdev->ddev->struct_mutex); - down_write(&rdev->pm.mclk_lock); + mutex_lock(&rdev->vram_mutex); mutex_lock(&rdev->ring_lock); /* gui idle int has issues on older chips it seems */ if (rdev->family >= CHIP_R600) { if (rdev->irq.installed) { - /* wait for GPU to become idle */ - radeon_irq_kms_wait_gui_idle(rdev); + /* wait for GPU idle */ + rdev->pm.gui_idle = false; + rdev->irq.gui_idle = true; + radeon_irq_set(rdev); + wait_event_interruptible_timeout( + rdev->irq.idle_queue, rdev->pm.gui_idle, + msecs_to_jiffies(RADEON_WAIT_IDLE_TIMEOUT)); + rdev->irq.gui_idle = false; + radeon_irq_set(rdev); } } else { struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; @@ -295,7 +303,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; mutex_unlock(&rdev->ring_lock); - up_write(&rdev->pm.mclk_lock); + mutex_unlock(&rdev->vram_mutex); mutex_unlock(&rdev->ddev->struct_mutex); } diff --git a/trunk/drivers/gpu/drm/radeon/radeon_ring.c b/trunk/drivers/gpu/drm/radeon/radeon_ring.c index ec79b3750430..983658c91358 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_ring.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_ring.c @@ -35,97 +35,47 @@ #include "atom.h" /* - * IB - * IBs (Indirect Buffers) and areas of GPU accessible memory where - * commands are stored. You can put a pointer to the IB in the - * command ring and the hw will fetch the commands from the IB - * and execute them. Generally userspace acceleration drivers - * produce command buffers which are send to the kernel and - * put in IBs for execution by the requested ring. + * IB. */ int radeon_debugfs_sa_init(struct radeon_device *rdev); -/** - * radeon_ib_get - request an IB (Indirect Buffer) - * - * @rdev: radeon_device pointer - * @ring: ring index the IB is associated with - * @ib: IB object returned - * @size: requested IB size - * - * Request an IB (all asics). IBs are allocated using the - * suballocator. - * Returns 0 on success, error on failure. - */ int radeon_ib_get(struct radeon_device *rdev, int ring, struct radeon_ib *ib, unsigned size) { - int i, r; + int r; r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &ib->sa_bo, size, 256, true); if (r) { dev_err(rdev->dev, "failed to get a new IB (%d)\n", r); return r; } - - r = radeon_semaphore_create(rdev, &ib->semaphore); + r = radeon_fence_create(rdev, &ib->fence, ring); if (r) { + dev_err(rdev->dev, "failed to create fence for new IB (%d)\n", r); + radeon_sa_bo_free(rdev, &ib->sa_bo, NULL); return r; } - ib->ring = ring; - ib->fence = NULL; ib->ptr = radeon_sa_bo_cpu_addr(ib->sa_bo); ib->gpu_addr = radeon_sa_bo_gpu_addr(ib->sa_bo); ib->vm_id = 0; ib->is_const_ib = false; - for (i = 0; i < RADEON_NUM_RINGS; ++i) - ib->sync_to[i] = NULL; + ib->semaphore = NULL; return 0; } -/** - * radeon_ib_free - free an IB (Indirect Buffer) - * - * @rdev: radeon_device pointer - * @ib: IB object to free - * - * Free an IB (all asics). - */ void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib) { - radeon_semaphore_free(rdev, &ib->semaphore, ib->fence); + radeon_semaphore_free(rdev, ib->semaphore, ib->fence); radeon_sa_bo_free(rdev, &ib->sa_bo, ib->fence); radeon_fence_unref(&ib->fence); } -/** - * radeon_ib_schedule - schedule an IB (Indirect Buffer) on the ring - * - * @rdev: radeon_device pointer - * @ib: IB object to schedule - * @const_ib: Const IB to schedule (SI only) - * - * Schedule an IB on the associated ring (all asics). - * Returns 0 on success, error on failure. - * - * On SI, there are two parallel engines fed from the primary ring, - * the CE (Constant Engine) and the DE (Drawing Engine). Since - * resource descriptors have moved to memory, the CE allows you to - * prime the caches while the DE is updating register state so that - * the resource descriptors will be already in cache when the draw is - * processed. To accomplish this, the userspace driver submits two - * IBs, one for the CE and one for the DE. If there is a CE IB (called - * a CONST_IB), it will be put on the ring prior to the DE IB. Prior - * to SI there was just a DE IB. - */ -int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, - struct radeon_ib *const_ib) +int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) { - struct radeon_ring *ring = &rdev->ring[ib->ring]; - bool need_sync = false; - int i, r = 0; + struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; + int r = 0; if (!ib->length_dw || !ring->ready) { /* TODO: Nothings in the ib we should report. */ @@ -134,51 +84,17 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, } /* 64 dwords should be enough for fence too */ - r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_RINGS * 8); + r = radeon_ring_lock(rdev, ring, 64); if (r) { dev_err(rdev->dev, "scheduling IB failed (%d).\n", r); return r; } - for (i = 0; i < RADEON_NUM_RINGS; ++i) { - struct radeon_fence *fence = ib->sync_to[i]; - if (radeon_fence_need_sync(fence, ib->ring)) { - need_sync = true; - radeon_semaphore_sync_rings(rdev, ib->semaphore, - fence->ring, ib->ring); - radeon_fence_note_sync(fence, ib->ring); - } - } - /* immediately free semaphore when we don't need to sync */ - if (!need_sync) { - radeon_semaphore_free(rdev, &ib->semaphore, NULL); - } - if (const_ib) { - radeon_ring_ib_execute(rdev, const_ib->ring, const_ib); - radeon_semaphore_free(rdev, &const_ib->semaphore, NULL); - } - radeon_ring_ib_execute(rdev, ib->ring, ib); - r = radeon_fence_emit(rdev, &ib->fence, ib->ring); - if (r) { - dev_err(rdev->dev, "failed to emit fence for new IB (%d)\n", r); - radeon_ring_unlock_undo(rdev, ring); - return r; - } - if (const_ib) { - const_ib->fence = radeon_fence_ref(ib->fence); - } + radeon_ring_ib_execute(rdev, ib->fence->ring, ib); + radeon_fence_emit(rdev, ib->fence); radeon_ring_unlock_commit(rdev, ring); return 0; } -/** - * radeon_ib_pool_init - Init the IB (Indirect Buffer) pool - * - * @rdev: radeon_device pointer - * - * Initialize the suballocator to manage a pool of memory - * for use as IBs (all asics). - * Returns 0 on success, error on failure. - */ int radeon_ib_pool_init(struct radeon_device *rdev) { int r; @@ -192,12 +108,6 @@ int radeon_ib_pool_init(struct radeon_device *rdev) if (r) { return r; } - - r = radeon_sa_bo_manager_start(rdev, &rdev->ring_tmp_bo); - if (r) { - return r; - } - rdev->ib_pool_ready = true; if (radeon_debugfs_sa_init(rdev)) { dev_err(rdev->dev, "failed to register debugfs file for SA\n"); @@ -205,33 +115,24 @@ int radeon_ib_pool_init(struct radeon_device *rdev) return 0; } -/** - * radeon_ib_pool_fini - Free the IB (Indirect Buffer) pool - * - * @rdev: radeon_device pointer - * - * Tear down the suballocator managing the pool of memory - * for use as IBs (all asics). - */ void radeon_ib_pool_fini(struct radeon_device *rdev) { if (rdev->ib_pool_ready) { - radeon_sa_bo_manager_suspend(rdev, &rdev->ring_tmp_bo); radeon_sa_bo_manager_fini(rdev, &rdev->ring_tmp_bo); rdev->ib_pool_ready = false; } } -/** - * radeon_ib_ring_tests - test IBs on the rings - * - * @rdev: radeon_device pointer - * - * Test an IB (Indirect Buffer) on each ring. - * If the test fails, disable the ring. - * Returns 0 on success, error if the primary GFX ring - * IB test fails. - */ +int radeon_ib_pool_start(struct radeon_device *rdev) +{ + return radeon_sa_bo_manager_start(rdev, &rdev->ring_tmp_bo); +} + +int radeon_ib_pool_suspend(struct radeon_device *rdev) +{ + return radeon_sa_bo_manager_suspend(rdev, &rdev->ring_tmp_bo); +} + int radeon_ib_ring_tests(struct radeon_device *rdev) { unsigned i; @@ -263,28 +164,10 @@ int radeon_ib_ring_tests(struct radeon_device *rdev) } /* - * Rings - * Most engines on the GPU are fed via ring buffers. Ring - * buffers are areas of GPU accessible memory that the host - * writes commands into and the GPU reads commands out of. - * There is a rptr (read pointer) that determines where the - * GPU is currently reading, and a wptr (write pointer) - * which determines where the host has written. When the - * pointers are equal, the ring is idle. When the host - * writes commands to the ring buffer, it increments the - * wptr. The GPU then starts fetching commands and executes - * them until the pointers are equal again. + * Ring. */ int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring); -/** - * radeon_ring_write - write a value to the ring - * - * @ring: radeon_ring structure holding ring information - * @v: dword (dw) value to write - * - * Write a value to the requested ring buffer (all asics). - */ void radeon_ring_write(struct radeon_ring *ring, uint32_t v) { #if DRM_DEBUG_CODE @@ -298,37 +181,21 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v) ring->ring_free_dw--; } -/** - * radeon_ring_supports_scratch_reg - check if the ring supports - * writing to scratch registers - * - * @rdev: radeon_device pointer - * @ring: radeon_ring structure holding ring information - * - * Check if a specific ring supports writing to scratch registers (all asics). - * Returns true if the ring supports writing to scratch regs, false if not. - */ -bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev, - struct radeon_ring *ring) +int radeon_ring_index(struct radeon_device *rdev, struct radeon_ring *ring) { - switch (ring->idx) { - case RADEON_RING_TYPE_GFX_INDEX: - case CAYMAN_RING_TYPE_CP1_INDEX: - case CAYMAN_RING_TYPE_CP2_INDEX: - return true; - default: - return false; + /* r1xx-r5xx only has CP ring */ + if (rdev->family < CHIP_R600) + return RADEON_RING_TYPE_GFX_INDEX; + + if (rdev->family >= CHIP_CAYMAN) { + if (ring == &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]) + return CAYMAN_RING_TYPE_CP1_INDEX; + else if (ring == &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]) + return CAYMAN_RING_TYPE_CP2_INDEX; } + return RADEON_RING_TYPE_GFX_INDEX; } -/** - * radeon_ring_free_size - update the free size - * - * @rdev: radeon_device pointer - * @ring: radeon_ring structure holding ring information - * - * Update the free dw slots in the ring buffer (all asics). - */ void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) { u32 rptr; @@ -347,16 +214,7 @@ void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) } } -/** - * radeon_ring_alloc - allocate space on the ring buffer - * - * @rdev: radeon_device pointer - * @ring: radeon_ring structure holding ring information - * @ndw: number of dwords to allocate in the ring buffer - * - * Allocate @ndw dwords in the ring buffer (all asics). - * Returns 0 on success, error on failure. - */ + int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) { int r; @@ -369,7 +227,7 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi if (ndw < ring->ring_free_dw) { break; } - r = radeon_fence_wait_next_locked(rdev, ring->idx); + r = radeon_fence_wait_next_locked(rdev, radeon_ring_index(rdev, ring)); if (r) return r; } @@ -378,17 +236,6 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi return 0; } -/** - * radeon_ring_lock - lock the ring and allocate space on it - * - * @rdev: radeon_device pointer - * @ring: radeon_ring structure holding ring information - * @ndw: number of dwords to allocate in the ring buffer - * - * Lock the ring and allocate @ndw dwords in the ring buffer - * (all asics). - * Returns 0 on success, error on failure. - */ int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) { int r; @@ -402,20 +249,15 @@ int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsig return 0; } -/** - * radeon_ring_commit - tell the GPU to execute the new - * commands on the ring buffer - * - * @rdev: radeon_device pointer - * @ring: radeon_ring structure holding ring information - * - * Update the wptr (write pointer) to tell the GPU to - * execute new commands on the ring buffer (all asics). - */ void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring) { + unsigned count_dw_pad; + unsigned i; + /* We pad to match fetch size */ - while (ring->wptr & ring->align_mask) { + count_dw_pad = (ring->align_mask + 1) - + (ring->wptr & ring->align_mask); + for (i = 0; i < count_dw_pad; i++) { radeon_ring_write(ring, ring->nop); } DRM_MEMORYBARRIER(); @@ -423,55 +265,23 @@ void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring) (void)RREG32(ring->wptr_reg); } -/** - * radeon_ring_unlock_commit - tell the GPU to execute the new - * commands on the ring buffer and unlock it - * - * @rdev: radeon_device pointer - * @ring: radeon_ring structure holding ring information - * - * Call radeon_ring_commit() then unlock the ring (all asics). - */ void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring) { radeon_ring_commit(rdev, ring); mutex_unlock(&rdev->ring_lock); } -/** - * radeon_ring_undo - reset the wptr - * - * @ring: radeon_ring structure holding ring information - * - * Reset the driver's copy of the wtpr (all asics). - */ void radeon_ring_undo(struct radeon_ring *ring) { ring->wptr = ring->wptr_old; } -/** - * radeon_ring_unlock_undo - reset the wptr and unlock the ring - * - * @ring: radeon_ring structure holding ring information - * - * Call radeon_ring_undo() then unlock the ring (all asics). - */ void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *ring) { radeon_ring_undo(ring); mutex_unlock(&rdev->ring_lock); } -/** - * radeon_ring_force_activity - add some nop packets to the ring - * - * @rdev: radeon_device pointer - * @ring: radeon_ring structure holding ring information - * - * Add some nop packets to the ring to force activity (all asics). - * Used for lockup detection to see if the rptr is advancing. - */ void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring) { int r; @@ -486,13 +296,6 @@ void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring * } } -/** - * radeon_ring_force_activity - update lockup variables - * - * @ring: radeon_ring structure holding ring information - * - * Update the last rptr value and timestamp (all asics). - */ void radeon_ring_lockup_update(struct radeon_ring *ring) { ring->last_rptr = ring->rptr; @@ -546,116 +349,6 @@ bool radeon_ring_test_lockup(struct radeon_device *rdev, struct radeon_ring *rin return false; } -/** - * radeon_ring_backup - Back up the content of a ring - * - * @rdev: radeon_device pointer - * @ring: the ring we want to back up - * - * Saves all unprocessed commits from a ring, returns the number of dwords saved. - */ -unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring, - uint32_t **data) -{ - unsigned size, ptr, i; - - /* just in case lock the ring */ - mutex_lock(&rdev->ring_lock); - *data = NULL; - - if (ring->ring_obj == NULL) { - mutex_unlock(&rdev->ring_lock); - return 0; - } - - /* it doesn't make sense to save anything if all fences are signaled */ - if (!radeon_fence_count_emitted(rdev, ring->idx)) { - mutex_unlock(&rdev->ring_lock); - return 0; - } - - /* calculate the number of dw on the ring */ - if (ring->rptr_save_reg) - ptr = RREG32(ring->rptr_save_reg); - else if (rdev->wb.enabled) - ptr = le32_to_cpu(*ring->next_rptr_cpu_addr); - else { - /* no way to read back the next rptr */ - mutex_unlock(&rdev->ring_lock); - return 0; - } - - size = ring->wptr + (ring->ring_size / 4); - size -= ptr; - size &= ring->ptr_mask; - if (size == 0) { - mutex_unlock(&rdev->ring_lock); - return 0; - } - - /* and then save the content of the ring */ - *data = kmalloc_array(size, sizeof(uint32_t), GFP_KERNEL); - if (!*data) { - mutex_unlock(&rdev->ring_lock); - return 0; - } - for (i = 0; i < size; ++i) { - (*data)[i] = ring->ring[ptr++]; - ptr &= ring->ptr_mask; - } - - mutex_unlock(&rdev->ring_lock); - return size; -} - -/** - * radeon_ring_restore - append saved commands to the ring again - * - * @rdev: radeon_device pointer - * @ring: ring to append commands to - * @size: number of dwords we want to write - * @data: saved commands - * - * Allocates space on the ring and restore the previously saved commands. - */ -int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring, - unsigned size, uint32_t *data) -{ - int i, r; - - if (!size || !data) - return 0; - - /* restore the saved ring content */ - r = radeon_ring_lock(rdev, ring, size); - if (r) - return r; - - for (i = 0; i < size; ++i) { - radeon_ring_write(ring, data[i]); - } - - radeon_ring_unlock_commit(rdev, ring); - kfree(data); - return 0; -} - -/** - * radeon_ring_init - init driver ring struct. - * - * @rdev: radeon_device pointer - * @ring: radeon_ring structure holding ring information - * @ring_size: size of the ring - * @rptr_offs: offset of the rptr writeback location in the WB buffer - * @rptr_reg: MMIO offset of the rptr register - * @wptr_reg: MMIO offset of the wptr register - * @ptr_reg_shift: bit offset of the rptr/wptr values - * @ptr_reg_mask: bit mask of the rptr/wptr values - * @nop: nop packet for this ring - * - * Initialize the driver information for the selected ring (all asics). - * Returns 0 on success, error on failure. - */ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size, unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop) @@ -698,25 +391,12 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig } ring->ptr_mask = (ring->ring_size / 4) - 1; ring->ring_free_dw = ring->ring_size / 4; - if (rdev->wb.enabled) { - u32 index = RADEON_WB_RING0_NEXT_RPTR + (ring->idx * 4); - ring->next_rptr_gpu_addr = rdev->wb.gpu_addr + index; - ring->next_rptr_cpu_addr = &rdev->wb.wb[index/4]; - } if (radeon_debugfs_ring_init(rdev, ring)) { DRM_ERROR("Failed to register debugfs file for rings !\n"); } return 0; } -/** - * radeon_ring_fini - tear down the driver ring struct. - * - * @rdev: radeon_device pointer - * @ring: radeon_ring structure holding ring information - * - * Tear down the driver information for the selected ring (all asics). - */ void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *ring) { int r; @@ -758,10 +438,6 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data) count = (ring->ring_size / 4) - ring->ring_free_dw; seq_printf(m, "wptr(0x%04x): 0x%08x\n", ring->wptr_reg, RREG32(ring->wptr_reg)); seq_printf(m, "rptr(0x%04x): 0x%08x\n", ring->rptr_reg, RREG32(ring->rptr_reg)); - if (ring->rptr_save_reg) { - seq_printf(m, "rptr next(0x%04x): 0x%08x\n", ring->rptr_save_reg, - RREG32(ring->rptr_save_reg)); - } seq_printf(m, "driver's copy of the wptr: 0x%08x\n", ring->wptr); seq_printf(m, "driver's copy of the rptr: 0x%08x\n", ring->rptr); seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_sa.c b/trunk/drivers/gpu/drm/radeon/radeon_sa.c index 4e771240fdd0..32059b745728 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_sa.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_sa.c @@ -54,7 +54,7 @@ int radeon_sa_bo_manager_init(struct radeon_device *rdev, { int i, r; - init_waitqueue_head(&sa_manager->wq); + spin_lock_init(&sa_manager->lock); sa_manager->bo = NULL; sa_manager->size = size; sa_manager->domain = domain; @@ -211,39 +211,6 @@ static bool radeon_sa_bo_try_alloc(struct radeon_sa_manager *sa_manager, return false; } -/** - * radeon_sa_event - Check if we can stop waiting - * - * @sa_manager: pointer to the sa_manager - * @size: number of bytes we want to allocate - * @align: alignment we need to match - * - * Check if either there is a fence we can wait for or - * enough free memory to satisfy the allocation directly - */ -static bool radeon_sa_event(struct radeon_sa_manager *sa_manager, - unsigned size, unsigned align) -{ - unsigned soffset, eoffset, wasted; - int i; - - for (i = 0; i < RADEON_NUM_RINGS; ++i) { - if (!list_empty(&sa_manager->flist[i])) { - return true; - } - } - - soffset = radeon_sa_bo_hole_soffset(sa_manager); - eoffset = radeon_sa_bo_hole_eoffset(sa_manager); - wasted = (align - (soffset % align)) % align; - - if ((eoffset - soffset) >= (size + wasted)) { - return true; - } - - return false; -} - static bool radeon_sa_bo_next_hole(struct radeon_sa_manager *sa_manager, struct radeon_fence **fences, unsigned *tries) @@ -330,8 +297,8 @@ int radeon_sa_bo_new(struct radeon_device *rdev, INIT_LIST_HEAD(&(*sa_bo)->olist); INIT_LIST_HEAD(&(*sa_bo)->flist); - spin_lock(&sa_manager->wq.lock); - while(1) { + spin_lock(&sa_manager->lock); + do { for (i = 0; i < RADEON_NUM_RINGS; ++i) { fences[i] = NULL; tries[i] = 0; @@ -342,34 +309,30 @@ int radeon_sa_bo_new(struct radeon_device *rdev, if (radeon_sa_bo_try_alloc(sa_manager, *sa_bo, size, align)) { - spin_unlock(&sa_manager->wq.lock); + spin_unlock(&sa_manager->lock); return 0; } /* see if we can skip over some allocations */ } while (radeon_sa_bo_next_hole(sa_manager, fences, tries)); - if (!block) { - break; - } - - spin_unlock(&sa_manager->wq.lock); - r = radeon_fence_wait_any(rdev, fences, false); - spin_lock(&sa_manager->wq.lock); - /* if we have nothing to wait for block */ - if (r == -ENOENT) { - r = wait_event_interruptible_locked( - sa_manager->wq, - radeon_sa_event(sa_manager, size, align) - ); - } - if (r) { - goto out_err; + if (block) { + spin_unlock(&sa_manager->lock); + r = radeon_fence_wait_any(rdev, fences, false); + spin_lock(&sa_manager->lock); + if (r) { + /* if we have nothing to wait for we + are practically out of memory */ + if (r == -ENOENT) { + r = -ENOMEM; + } + goto out_err; + } } - }; + } while (block); out_err: - spin_unlock(&sa_manager->wq.lock); + spin_unlock(&sa_manager->lock); kfree(*sa_bo); *sa_bo = NULL; return r; @@ -385,16 +348,15 @@ void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo **sa_bo, } sa_manager = (*sa_bo)->manager; - spin_lock(&sa_manager->wq.lock); - if (fence && !radeon_fence_signaled(fence)) { + spin_lock(&sa_manager->lock); + if (fence && fence->seq && fence->seq < RADEON_FENCE_NOTEMITED_SEQ) { (*sa_bo)->fence = radeon_fence_ref(fence); list_add_tail(&(*sa_bo)->flist, &sa_manager->flist[fence->ring]); } else { radeon_sa_bo_remove_locked(*sa_bo); } - wake_up_all_locked(&sa_manager->wq); - spin_unlock(&sa_manager->wq.lock); + spin_unlock(&sa_manager->lock); *sa_bo = NULL; } @@ -404,7 +366,7 @@ void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager, { struct radeon_sa_bo *i; - spin_lock(&sa_manager->wq.lock); + spin_lock(&sa_manager->lock); list_for_each_entry(i, &sa_manager->olist, olist) { if (&i->olist == sa_manager->hole) { seq_printf(m, ">"); @@ -419,6 +381,6 @@ void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager, } seq_printf(m, "\n"); } - spin_unlock(&sa_manager->wq.lock); + spin_unlock(&sa_manager->lock); } #endif diff --git a/trunk/drivers/gpu/drm/radeon/radeon_semaphore.c b/trunk/drivers/gpu/drm/radeon/radeon_semaphore.c index 7cc78de6ddc3..e2ace5dce117 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_semaphore.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_semaphore.c @@ -68,49 +68,70 @@ void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, true); } -/* caller must hold ring lock */ int radeon_semaphore_sync_rings(struct radeon_device *rdev, struct radeon_semaphore *semaphore, - int signaler, int waiter) + bool sync_to[RADEON_NUM_RINGS], + int dst_ring) { - int r; + int i = 0, r; - /* no need to signal and wait on the same ring */ - if (signaler == waiter) { - return 0; + mutex_lock(&rdev->ring_lock); + r = radeon_ring_alloc(rdev, &rdev->ring[dst_ring], RADEON_NUM_RINGS * 8); + if (r) { + goto error; } - /* prevent GPU deadlocks */ - if (!rdev->ring[signaler].ready) { - dev_err(rdev->dev, "Trying to sync to a disabled ring!"); - return -EINVAL; - } + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + /* no need to sync to our own or unused rings */ + if (!sync_to[i] || i == dst_ring) + continue; - r = radeon_ring_alloc(rdev, &rdev->ring[signaler], 8); - if (r) { - return r; + /* prevent GPU deadlocks */ + if (!rdev->ring[i].ready) { + dev_err(rdev->dev, "Trying to sync to a disabled ring!"); + r = -EINVAL; + goto error; + } + + r = radeon_ring_alloc(rdev, &rdev->ring[i], 8); + if (r) { + goto error; + } + + radeon_semaphore_emit_signal(rdev, i, semaphore); + radeon_semaphore_emit_wait(rdev, dst_ring, semaphore); + + radeon_ring_commit(rdev, &rdev->ring[i]); } - radeon_semaphore_emit_signal(rdev, signaler, semaphore); - radeon_ring_commit(rdev, &rdev->ring[signaler]); - /* we assume caller has already allocated space on waiters ring */ - radeon_semaphore_emit_wait(rdev, waiter, semaphore); + radeon_ring_commit(rdev, &rdev->ring[dst_ring]); + mutex_unlock(&rdev->ring_lock); return 0; + +error: + /* unlock all locks taken so far */ + for (--i; i >= 0; --i) { + if (sync_to[i] || i == dst_ring) { + radeon_ring_undo(&rdev->ring[i]); + } + } + radeon_ring_undo(&rdev->ring[dst_ring]); + mutex_unlock(&rdev->ring_lock); + return r; } void radeon_semaphore_free(struct radeon_device *rdev, - struct radeon_semaphore **semaphore, + struct radeon_semaphore *semaphore, struct radeon_fence *fence) { - if (semaphore == NULL || *semaphore == NULL) { + if (semaphore == NULL) { return; } - if ((*semaphore)->waiters > 0) { + if (semaphore->waiters > 0) { dev_err(rdev->dev, "semaphore %p has more waiters than signalers," - " hardware lockup imminent!\n", *semaphore); + " hardware lockup imminent!\n", semaphore); } - radeon_sa_bo_free(rdev, &(*semaphore)->sa_bo, fence); - kfree(*semaphore); - *semaphore = NULL; + radeon_sa_bo_free(rdev, &semaphore->sa_bo, fence); + kfree(semaphore); } diff --git a/trunk/drivers/gpu/drm/radeon/radeon_test.c b/trunk/drivers/gpu/drm/radeon/radeon_test.c index 7c16540c10ff..efff929ea49d 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_test.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_test.c @@ -106,7 +106,13 @@ void radeon_test_moves(struct radeon_device *rdev) radeon_bo_kunmap(gtt_obj[i]); - r = radeon_copy(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, &fence); + r = radeon_fence_create(rdev, &fence, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + DRM_ERROR("Failed to create GTT->VRAM fence %d\n", i); + goto out_cleanup; + } + + r = radeon_copy(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, fence); if (r) { DRM_ERROR("Failed GTT->VRAM copy %d\n", i); goto out_cleanup; @@ -149,7 +155,13 @@ void radeon_test_moves(struct radeon_device *rdev) radeon_bo_kunmap(vram_obj); - r = radeon_copy(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, &fence); + r = radeon_fence_create(rdev, &fence, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + DRM_ERROR("Failed to create VRAM->GTT fence %d\n", i); + goto out_cleanup; + } + + r = radeon_copy(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, fence); if (r) { DRM_ERROR("Failed VRAM->GTT copy %d\n", i); goto out_cleanup; @@ -229,33 +241,36 @@ void radeon_test_ring_sync(struct radeon_device *rdev, { struct radeon_fence *fence1 = NULL, *fence2 = NULL; struct radeon_semaphore *semaphore = NULL; + int ridxA = radeon_ring_index(rdev, ringA); + int ridxB = radeon_ring_index(rdev, ringB); int r; - r = radeon_semaphore_create(rdev, &semaphore); + r = radeon_fence_create(rdev, &fence1, ridxA); if (r) { - DRM_ERROR("Failed to create semaphore\n"); + DRM_ERROR("Failed to create sync fence 1\n"); goto out_cleanup; } - - r = radeon_ring_lock(rdev, ringA, 64); + r = radeon_fence_create(rdev, &fence2, ridxA); if (r) { - DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); + DRM_ERROR("Failed to create sync fence 2\n"); goto out_cleanup; } - radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); - r = radeon_fence_emit(rdev, &fence1, ringA->idx); + + r = radeon_semaphore_create(rdev, &semaphore); if (r) { - DRM_ERROR("Failed to emit fence 1\n"); - radeon_ring_unlock_undo(rdev, ringA); + DRM_ERROR("Failed to create semaphore\n"); goto out_cleanup; } - radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); - r = radeon_fence_emit(rdev, &fence2, ringA->idx); + + r = radeon_ring_lock(rdev, ringA, 64); if (r) { - DRM_ERROR("Failed to emit fence 2\n"); - radeon_ring_unlock_undo(rdev, ringA); + DRM_ERROR("Failed to lock ring A %d\n", ridxA); goto out_cleanup; } + radeon_semaphore_emit_wait(rdev, ridxA, semaphore); + radeon_fence_emit(rdev, fence1); + radeon_semaphore_emit_wait(rdev, ridxA, semaphore); + radeon_fence_emit(rdev, fence2); radeon_ring_unlock_commit(rdev, ringA); mdelay(1000); @@ -270,7 +285,7 @@ void radeon_test_ring_sync(struct radeon_device *rdev, DRM_ERROR("Failed to lock ring B %p\n", ringB); goto out_cleanup; } - radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore); + radeon_semaphore_emit_signal(rdev, ridxB, semaphore); radeon_ring_unlock_commit(rdev, ringB); r = radeon_fence_wait(fence1, false); @@ -291,7 +306,7 @@ void radeon_test_ring_sync(struct radeon_device *rdev, DRM_ERROR("Failed to lock ring B %p\n", ringB); goto out_cleanup; } - radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore); + radeon_semaphore_emit_signal(rdev, ridxB, semaphore); radeon_ring_unlock_commit(rdev, ringB); r = radeon_fence_wait(fence2, false); @@ -301,7 +316,8 @@ void radeon_test_ring_sync(struct radeon_device *rdev, } out_cleanup: - radeon_semaphore_free(rdev, &semaphore, NULL); + if (semaphore) + radeon_semaphore_free(rdev, semaphore, NULL); if (fence1) radeon_fence_unref(&fence1); @@ -320,41 +336,45 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, { struct radeon_fence *fenceA = NULL, *fenceB = NULL; struct radeon_semaphore *semaphore = NULL; + int ridxA = radeon_ring_index(rdev, ringA); + int ridxB = radeon_ring_index(rdev, ringB); + int ridxC = radeon_ring_index(rdev, ringC); bool sigA, sigB; int i, r; - r = radeon_semaphore_create(rdev, &semaphore); + r = radeon_fence_create(rdev, &fenceA, ridxA); if (r) { - DRM_ERROR("Failed to create semaphore\n"); + DRM_ERROR("Failed to create sync fence 1\n"); goto out_cleanup; } - - r = radeon_ring_lock(rdev, ringA, 64); + r = radeon_fence_create(rdev, &fenceB, ridxB); if (r) { - DRM_ERROR("Failed to lock ring A %d\n", ringA->idx); + DRM_ERROR("Failed to create sync fence 2\n"); goto out_cleanup; } - radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore); - r = radeon_fence_emit(rdev, &fenceA, ringA->idx); + + r = radeon_semaphore_create(rdev, &semaphore); if (r) { - DRM_ERROR("Failed to emit sync fence 1\n"); - radeon_ring_unlock_undo(rdev, ringA); + DRM_ERROR("Failed to create semaphore\n"); goto out_cleanup; } - radeon_ring_unlock_commit(rdev, ringA); - r = radeon_ring_lock(rdev, ringB, 64); + r = radeon_ring_lock(rdev, ringA, 64); if (r) { - DRM_ERROR("Failed to lock ring B %d\n", ringB->idx); + DRM_ERROR("Failed to lock ring A %d\n", ridxA); goto out_cleanup; } - radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore); - r = radeon_fence_emit(rdev, &fenceB, ringB->idx); + radeon_semaphore_emit_wait(rdev, ridxA, semaphore); + radeon_fence_emit(rdev, fenceA); + radeon_ring_unlock_commit(rdev, ringA); + + r = radeon_ring_lock(rdev, ringB, 64); if (r) { - DRM_ERROR("Failed to create sync fence 2\n"); - radeon_ring_unlock_undo(rdev, ringB); + DRM_ERROR("Failed to lock ring B %d\n", ridxB); goto out_cleanup; } + radeon_semaphore_emit_wait(rdev, ridxB, semaphore); + radeon_fence_emit(rdev, fenceB); radeon_ring_unlock_commit(rdev, ringB); mdelay(1000); @@ -373,7 +393,7 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, DRM_ERROR("Failed to lock ring B %p\n", ringC); goto out_cleanup; } - radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore); + radeon_semaphore_emit_signal(rdev, ridxC, semaphore); radeon_ring_unlock_commit(rdev, ringC); for (i = 0; i < 30; ++i) { @@ -399,7 +419,7 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, DRM_ERROR("Failed to lock ring B %p\n", ringC); goto out_cleanup; } - radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore); + radeon_semaphore_emit_signal(rdev, ridxC, semaphore); radeon_ring_unlock_commit(rdev, ringC); mdelay(1000); @@ -416,7 +436,8 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, } out_cleanup: - radeon_semaphore_free(rdev, &semaphore, NULL); + if (semaphore) + radeon_semaphore_free(rdev, semaphore, NULL); if (fenceA) radeon_fence_unref(&fenceA); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_ttm.c b/trunk/drivers/gpu/drm/radeon/radeon_ttm.c index 5b71c716d83f..c94a2257761f 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_ttm.c @@ -222,11 +222,15 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, { struct radeon_device *rdev; uint64_t old_start, new_start; - struct radeon_fence *fence; - int r, ridx; + struct radeon_fence *fence, *old_fence; + struct radeon_semaphore *sem = NULL; + int r; rdev = radeon_get_rdev(bo->bdev); - ridx = radeon_copy_ring_index(rdev); + r = radeon_fence_create(rdev, &fence, radeon_copy_ring_index(rdev)); + if (unlikely(r)) { + return r; + } old_start = old_mem->start << PAGE_SHIFT; new_start = new_mem->start << PAGE_SHIFT; @@ -239,6 +243,7 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, break; default: DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); + radeon_fence_unref(&fence); return -EINVAL; } switch (new_mem->mem_type) { @@ -250,23 +255,46 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, break; default: DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); + radeon_fence_unref(&fence); return -EINVAL; } - if (!rdev->ring[ridx].ready) { + if (!rdev->ring[radeon_copy_ring_index(rdev)].ready) { DRM_ERROR("Trying to move memory with ring turned off.\n"); + radeon_fence_unref(&fence); return -EINVAL; } BUILD_BUG_ON((PAGE_SIZE % RADEON_GPU_PAGE_SIZE) != 0); /* sync other rings */ - fence = bo->sync_obj; + old_fence = bo->sync_obj; + if (old_fence && old_fence->ring != fence->ring + && !radeon_fence_signaled(old_fence)) { + bool sync_to_ring[RADEON_NUM_RINGS] = { }; + sync_to_ring[old_fence->ring] = true; + + r = radeon_semaphore_create(rdev, &sem); + if (r) { + radeon_fence_unref(&fence); + return r; + } + + r = radeon_semaphore_sync_rings(rdev, sem, + sync_to_ring, fence->ring); + if (r) { + radeon_semaphore_free(rdev, sem, NULL); + radeon_fence_unref(&fence); + return r; + } + } + r = radeon_copy(rdev, old_start, new_start, new_mem->num_pages * (PAGE_SIZE / RADEON_GPU_PAGE_SIZE), /* GPU pages */ - &fence); + fence); /* FIXME: handle copy error */ r = ttm_bo_move_accel_cleanup(bo, (void *)fence, NULL, evict, no_wait_reserve, no_wait_gpu, new_mem); + radeon_semaphore_free(rdev, sem, fence); radeon_fence_unref(&fence); return r; } @@ -734,7 +762,9 @@ int radeon_ttm_init(struct radeon_device *rdev) } DRM_INFO("radeon: %uM of GTT memory ready.\n", (unsigned)(rdev->mc.gtt_size / (1024 * 1024))); - rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; + if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) { + rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; + } r = radeon_ttm_debugfs_init(rdev); if (r) { @@ -795,9 +825,9 @@ static int radeon_ttm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) return VM_FAULT_NOPAGE; } rdev = radeon_get_rdev(bo->bdev); - down_read(&rdev->pm.mclk_lock); + mutex_lock(&rdev->vram_mutex); r = ttm_vm_ops->fault(vma, vmf); - up_read(&rdev->pm.mclk_lock); + mutex_unlock(&rdev->vram_mutex); return r; } diff --git a/trunk/drivers/gpu/drm/radeon/rs400.c b/trunk/drivers/gpu/drm/radeon/rs400.c index 2752f7f78237..a464eb5e2df2 100644 --- a/trunk/drivers/gpu/drm/radeon/rs400.c +++ b/trunk/drivers/gpu/drm/radeon/rs400.c @@ -426,11 +426,13 @@ static int rs400_startup(struct radeon_device *rdev) return r; } - r = radeon_ib_pool_init(rdev); - if (r) { - dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + r = radeon_ib_pool_start(rdev); + if (r) + return r; + + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } return 0; } @@ -468,6 +470,7 @@ int rs400_resume(struct radeon_device *rdev) int rs400_suspend(struct radeon_device *rdev) { + radeon_ib_pool_suspend(rdev); r100_cp_disable(rdev); radeon_wb_disable(rdev); r100_irq_disable(rdev); @@ -479,7 +482,7 @@ void rs400_fini(struct radeon_device *rdev) { r100_cp_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_gem_fini(rdev); rs400_gart_fini(rdev); radeon_irq_kms_fini(rdev); @@ -547,14 +550,20 @@ int rs400_init(struct radeon_device *rdev) return r; r300_set_reg_safe(rdev); + r = radeon_ib_pool_init(rdev); rdev->accel_working = true; + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + rdev->accel_working = false; + } + r = rs400_startup(rdev); if (r) { /* Somethings want wront with the accel init stop accel */ dev_err(rdev->dev, "Disabling GPU acceleration\n"); r100_cp_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); rs400_gart_fini(rdev); radeon_irq_kms_fini(rdev); rdev->accel_working = false; diff --git a/trunk/drivers/gpu/drm/radeon/rs600.c b/trunk/drivers/gpu/drm/radeon/rs600.c index 5301b3df8466..e95c5e61d4e2 100644 --- a/trunk/drivers/gpu/drm/radeon/rs600.c +++ b/trunk/drivers/gpu/drm/radeon/rs600.c @@ -294,7 +294,6 @@ void rs600_hpd_init(struct radeon_device *rdev) { struct drm_device *dev = rdev->ddev; struct drm_connector *connector; - unsigned enable = 0; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -302,25 +301,26 @@ void rs600_hpd_init(struct radeon_device *rdev) case RADEON_HPD_1: WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, S_007D00_DC_HOT_PLUG_DETECT1_EN(1)); + rdev->irq.hpd[0] = true; break; case RADEON_HPD_2: WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, S_007D10_DC_HOT_PLUG_DETECT2_EN(1)); + rdev->irq.hpd[1] = true; break; default: break; } - enable |= 1 << radeon_connector->hpd.hpd; radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); } - radeon_irq_kms_enable_hpd(rdev, enable); + if (rdev->irq.installed) + rs600_irq_set(rdev); } void rs600_hpd_fini(struct radeon_device *rdev) { struct drm_device *dev = rdev->ddev; struct drm_connector *connector; - unsigned disable = 0; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -328,17 +328,17 @@ void rs600_hpd_fini(struct radeon_device *rdev) case RADEON_HPD_1: WREG32(R_007D00_DC_HOT_PLUG_DETECT1_CONTROL, S_007D00_DC_HOT_PLUG_DETECT1_EN(0)); + rdev->irq.hpd[0] = false; break; case RADEON_HPD_2: WREG32(R_007D10_DC_HOT_PLUG_DETECT2_CONTROL, S_007D10_DC_HOT_PLUG_DETECT2_EN(0)); + rdev->irq.hpd[1] = false; break; default: break; } - disable |= 1 << radeon_connector->hpd.hpd; } - radeon_irq_kms_disable_hpd(rdev, disable); } int rs600_asic_reset(struct radeon_device *rdev) @@ -564,18 +564,18 @@ int rs600_irq_set(struct radeon_device *rdev) WREG32(R_000040_GEN_INT_CNTL, 0); return -EINVAL; } - if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { + if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { tmp |= S_000040_SW_INT_EN(1); } if (rdev->irq.gui_idle) { tmp |= S_000040_GUI_IDLE(1); } if (rdev->irq.crtc_vblank_int[0] || - atomic_read(&rdev->irq.pflip[0])) { + rdev->irq.pflip[0]) { mode_int |= S_006540_D1MODE_VBLANK_INT_MASK(1); } if (rdev->irq.crtc_vblank_int[1] || - atomic_read(&rdev->irq.pflip[1])) { + rdev->irq.pflip[1]) { mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1); } if (rdev->irq.hpd[0]) { @@ -686,6 +686,7 @@ int rs600_irq_process(struct radeon_device *rdev) /* GUI idle */ if (G_000040_GUI_IDLE(status)) { rdev->irq.gui_idle_acked = true; + rdev->pm.gui_idle = true; wake_up(&rdev->irq.idle_queue); } /* Vertical blank interrupts */ @@ -695,7 +696,7 @@ int rs600_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[0])) + if (rdev->irq.pflip[0]) radeon_crtc_handle_flip(rdev, 0); } if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { @@ -704,7 +705,7 @@ int rs600_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[1])) + if (rdev->irq.pflip[1]) radeon_crtc_handle_flip(rdev, 1); } if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { @@ -907,11 +908,13 @@ static int rs600_startup(struct radeon_device *rdev) return r; } - r = radeon_ib_pool_init(rdev); - if (r) { - dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + r = radeon_ib_pool_start(rdev); + if (r) + return r; + + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } r = r600_audio_init(rdev); if (r) { @@ -953,6 +956,7 @@ int rs600_resume(struct radeon_device *rdev) int rs600_suspend(struct radeon_device *rdev) { + radeon_ib_pool_suspend(rdev); r600_audio_fini(rdev); r100_cp_disable(rdev); radeon_wb_disable(rdev); @@ -966,7 +970,7 @@ void rs600_fini(struct radeon_device *rdev) r600_audio_fini(rdev); r100_cp_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_gem_fini(rdev); rs600_gart_fini(rdev); radeon_irq_kms_fini(rdev); @@ -1034,14 +1038,20 @@ int rs600_init(struct radeon_device *rdev) return r; rs600_set_safe_registers(rdev); + r = radeon_ib_pool_init(rdev); rdev->accel_working = true; + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + rdev->accel_working = false; + } + r = rs600_startup(rdev); if (r) { /* Somethings want wront with the accel init stop accel */ dev_err(rdev->dev, "Disabling GPU acceleration\n"); r100_cp_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); rs600_gart_fini(rdev); radeon_irq_kms_fini(rdev); rdev->accel_working = false; diff --git a/trunk/drivers/gpu/drm/radeon/rs690.c b/trunk/drivers/gpu/drm/radeon/rs690.c index 3b663fcfe061..159b6a43fda0 100644 --- a/trunk/drivers/gpu/drm/radeon/rs690.c +++ b/trunk/drivers/gpu/drm/radeon/rs690.c @@ -637,11 +637,13 @@ static int rs690_startup(struct radeon_device *rdev) return r; } - r = radeon_ib_pool_init(rdev); - if (r) { - dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + r = radeon_ib_pool_start(rdev); + if (r) + return r; + + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } r = r600_audio_init(rdev); if (r) { @@ -683,6 +685,7 @@ int rs690_resume(struct radeon_device *rdev) int rs690_suspend(struct radeon_device *rdev) { + radeon_ib_pool_suspend(rdev); r600_audio_fini(rdev); r100_cp_disable(rdev); radeon_wb_disable(rdev); @@ -696,7 +699,7 @@ void rs690_fini(struct radeon_device *rdev) r600_audio_fini(rdev); r100_cp_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_gem_fini(rdev); rs400_gart_fini(rdev); radeon_irq_kms_fini(rdev); @@ -765,14 +768,20 @@ int rs690_init(struct radeon_device *rdev) return r; rs600_set_safe_registers(rdev); + r = radeon_ib_pool_init(rdev); rdev->accel_working = true; + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + rdev->accel_working = false; + } + r = rs690_startup(rdev); if (r) { /* Somethings want wront with the accel init stop accel */ dev_err(rdev->dev, "Disabling GPU acceleration\n"); r100_cp_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); rs400_gart_fini(rdev); radeon_irq_kms_fini(rdev); rdev->accel_working = false; diff --git a/trunk/drivers/gpu/drm/radeon/rv515.c b/trunk/drivers/gpu/drm/radeon/rv515.c index a12fbcc8ccb6..7f08cedb5333 100644 --- a/trunk/drivers/gpu/drm/radeon/rv515.c +++ b/trunk/drivers/gpu/drm/radeon/rv515.c @@ -408,11 +408,13 @@ static int rv515_startup(struct radeon_device *rdev) return r; } - r = radeon_ib_pool_init(rdev); - if (r) { - dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + r = radeon_ib_pool_start(rdev); + if (r) + return r; + + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } return 0; } @@ -467,7 +469,7 @@ void rv515_fini(struct radeon_device *rdev) { r100_cp_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_gem_fini(rdev); rv370_pcie_gart_fini(rdev); radeon_agp_fini(rdev); @@ -541,14 +543,20 @@ int rv515_init(struct radeon_device *rdev) return r; rv515_set_safe_registers(rdev); + r = radeon_ib_pool_init(rdev); rdev->accel_working = true; + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + rdev->accel_working = false; + } + r = rv515_startup(rdev); if (r) { /* Somethings want wront with the accel init stop accel */ dev_err(rdev->dev, "Disabling GPU acceleration\n"); r100_cp_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_irq_kms_fini(rdev); rv370_pcie_gart_fini(rdev); radeon_agp_fini(rdev); diff --git a/trunk/drivers/gpu/drm/radeon/rv770.c b/trunk/drivers/gpu/drm/radeon/rv770.c index ca8ffec10ff6..b4f51c569c36 100644 --- a/trunk/drivers/gpu/drm/radeon/rv770.c +++ b/trunk/drivers/gpu/drm/radeon/rv770.c @@ -358,10 +358,8 @@ static int rv770_cp_load_microcode(struct radeon_device *rdev) void r700_cp_fini(struct radeon_device *rdev) { - struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; r700_cp_stop(rdev); - radeon_ring_fini(rdev, ring); - radeon_scratch_free(rdev, ring->rptr_save_reg); + radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); } /* @@ -953,11 +951,13 @@ static int rv770_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_ib_pool_init(rdev); - if (r) { - dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + r = radeon_ib_pool_start(rdev); + if (r) + return r; + + r = radeon_ib_ring_tests(rdev); + if (r) return r; - } r = r600_audio_init(rdev); if (r) { @@ -994,6 +994,9 @@ int rv770_resume(struct radeon_device *rdev) int rv770_suspend(struct radeon_device *rdev) { r600_audio_fini(rdev); + radeon_ib_pool_suspend(rdev); + r600_blit_suspend(rdev); + /* FIXME: we should wait for ring to be empty */ r700_cp_stop(rdev); rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; r600_irq_suspend(rdev); @@ -1073,14 +1076,20 @@ int rv770_init(struct radeon_device *rdev) if (r) return r; + r = radeon_ib_pool_init(rdev); rdev->accel_working = true; + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + rdev->accel_working = false; + } + r = rv770_startup(rdev); if (r) { dev_err(rdev->dev, "disabling GPU acceleration\n"); r700_cp_fini(rdev); r600_irq_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_irq_kms_fini(rdev); rv770_pcie_gart_fini(rdev); rdev->accel_working = false; @@ -1095,7 +1104,7 @@ void rv770_fini(struct radeon_device *rdev) r700_cp_fini(rdev); r600_irq_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_irq_kms_fini(rdev); rv770_pcie_gart_fini(rdev); r600_vram_scratch_fini(rdev); @@ -1112,8 +1121,6 @@ static void rv770_pcie_gen2_enable(struct radeon_device *rdev) { u32 link_width_cntl, lanes, speed_cntl, tmp; u16 link_cntl2; - u32 mask; - int ret; if (radeon_pcie_gen2 == 0) return; @@ -1128,15 +1135,6 @@ static void rv770_pcie_gen2_enable(struct radeon_device *rdev) if (ASIC_IS_X2(rdev)) return; - ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); - if (ret != 0) - return; - - if (!(mask & DRM_PCIE_SPEED_50)) - return; - - DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); - /* advertise upconfig capability */ link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL); link_width_cntl &= ~LC_UPCONFIGURE_DIS; diff --git a/trunk/drivers/gpu/drm/radeon/si.c b/trunk/drivers/gpu/drm/radeon/si.c index c053f8193771..0b0279291a73 100644 --- a/trunk/drivers/gpu/drm/radeon/si.c +++ b/trunk/drivers/gpu/drm/radeon/si.c @@ -1762,34 +1762,13 @@ void si_fence_ring_emit(struct radeon_device *rdev, */ void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) { - struct radeon_ring *ring = &rdev->ring[ib->ring]; + struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; u32 header; - if (ib->is_const_ib) { - /* set switch buffer packet before const IB */ - radeon_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0)); - radeon_ring_write(ring, 0); - + if (ib->is_const_ib) header = PACKET3(PACKET3_INDIRECT_BUFFER_CONST, 2); - } else { - u32 next_rptr; - if (ring->rptr_save_reg) { - next_rptr = ring->wptr + 3 + 4 + 8; - radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); - radeon_ring_write(ring, ((ring->rptr_save_reg - - PACKET3_SET_CONFIG_REG_START) >> 2)); - radeon_ring_write(ring, next_rptr); - } else if (rdev->wb.enabled) { - next_rptr = ring->wptr + 5 + 4 + 8; - radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); - radeon_ring_write(ring, (1 << 8)); - radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); - radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff); - radeon_ring_write(ring, next_rptr); - } - + else header = PACKET3(PACKET3_INDIRECT_BUFFER, 2); - } radeon_ring_write(ring, header); radeon_ring_write(ring, @@ -1800,20 +1779,18 @@ void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF); radeon_ring_write(ring, ib->length_dw | (ib->vm_id << 24)); - if (!ib->is_const_ib) { - /* flush read cache over gart for this vmid */ - radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); - radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); - radeon_ring_write(ring, ib->vm_id); - radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); - radeon_ring_write(ring, PACKET3_TCL1_ACTION_ENA | - PACKET3_TC_ACTION_ENA | - PACKET3_SH_KCACHE_ACTION_ENA | - PACKET3_SH_ICACHE_ACTION_ENA); - radeon_ring_write(ring, 0xFFFFFFFF); - radeon_ring_write(ring, 0); - radeon_ring_write(ring, 10); /* poll interval */ - } + /* flush read cache over gart for this vmid */ + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); + radeon_ring_write(ring, ib->vm_id); + radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); + radeon_ring_write(ring, PACKET3_TCL1_ACTION_ENA | + PACKET3_TC_ACTION_ENA | + PACKET3_SH_KCACHE_ACTION_ENA | + PACKET3_SH_ICACHE_ACTION_ENA); + radeon_ring_write(ring, 0xFFFFFFFF); + radeon_ring_write(ring, 0); + radeon_ring_write(ring, 10); /* poll interval */ } /* @@ -1940,20 +1917,10 @@ static int si_cp_start(struct radeon_device *rdev) static void si_cp_fini(struct radeon_device *rdev) { - struct radeon_ring *ring; si_cp_enable(rdev, false); - - ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; - radeon_ring_fini(rdev, ring); - radeon_scratch_free(rdev, ring->rptr_save_reg); - - ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; - radeon_ring_fini(rdev, ring); - radeon_scratch_free(rdev, ring->rptr_save_reg); - - ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; - radeon_ring_fini(rdev, ring); - radeon_scratch_free(rdev, ring->rptr_save_reg); + radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); + radeon_ring_fini(rdev, &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]); + radeon_ring_fini(rdev, &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]); } static int si_cp_resume(struct radeon_device *rdev) @@ -2735,7 +2702,7 @@ int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) if (ib->is_const_ib) ret = si_vm_packet3_ce_check(rdev, ib->ptr, &pkt); else { - switch (ib->ring) { + switch (ib->fence->ring) { case RADEON_RING_TYPE_GFX_INDEX: ret = si_vm_packet3_gfx_check(rdev, ib->ptr, &pkt); break; @@ -2744,7 +2711,7 @@ int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) ret = si_vm_packet3_compute_check(rdev, ib->ptr, &pkt); break; default: - dev_err(rdev->dev, "Non-PM4 ring %d !\n", ib->ring); + dev_err(rdev->dev, "Non-PM4 ring %d !\n", ib->fence->ring); ret = -EINVAL; break; } @@ -2975,6 +2942,7 @@ static void si_disable_interrupts(struct radeon_device *rdev) WREG32(IH_RB_RPTR, 0); WREG32(IH_RB_WPTR, 0); rdev->ih.enabled = false; + rdev->ih.wptr = 0; rdev->ih.rptr = 0; } @@ -3125,45 +3093,45 @@ int si_irq_set(struct radeon_device *rdev) hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; /* enable CP interrupts on all rings */ - if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { + if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { DRM_DEBUG("si_irq_set: sw int gfx\n"); cp_int_cntl |= TIME_STAMP_INT_ENABLE; } - if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP1_INDEX])) { + if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP1_INDEX]) { DRM_DEBUG("si_irq_set: sw int cp1\n"); cp_int_cntl1 |= TIME_STAMP_INT_ENABLE; } - if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP2_INDEX])) { + if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP2_INDEX]) { DRM_DEBUG("si_irq_set: sw int cp2\n"); cp_int_cntl2 |= TIME_STAMP_INT_ENABLE; } if (rdev->irq.crtc_vblank_int[0] || - atomic_read(&rdev->irq.pflip[0])) { + rdev->irq.pflip[0]) { DRM_DEBUG("si_irq_set: vblank 0\n"); crtc1 |= VBLANK_INT_MASK; } if (rdev->irq.crtc_vblank_int[1] || - atomic_read(&rdev->irq.pflip[1])) { + rdev->irq.pflip[1]) { DRM_DEBUG("si_irq_set: vblank 1\n"); crtc2 |= VBLANK_INT_MASK; } if (rdev->irq.crtc_vblank_int[2] || - atomic_read(&rdev->irq.pflip[2])) { + rdev->irq.pflip[2]) { DRM_DEBUG("si_irq_set: vblank 2\n"); crtc3 |= VBLANK_INT_MASK; } if (rdev->irq.crtc_vblank_int[3] || - atomic_read(&rdev->irq.pflip[3])) { + rdev->irq.pflip[3]) { DRM_DEBUG("si_irq_set: vblank 3\n"); crtc4 |= VBLANK_INT_MASK; } if (rdev->irq.crtc_vblank_int[4] || - atomic_read(&rdev->irq.pflip[4])) { + rdev->irq.pflip[4]) { DRM_DEBUG("si_irq_set: vblank 4\n"); crtc5 |= VBLANK_INT_MASK; } if (rdev->irq.crtc_vblank_int[5] || - atomic_read(&rdev->irq.pflip[5])) { + rdev->irq.pflip[5]) { DRM_DEBUG("si_irq_set: vblank 5\n"); crtc6 |= VBLANK_INT_MASK; } @@ -3391,27 +3359,29 @@ int si_irq_process(struct radeon_device *rdev) u32 rptr; u32 src_id, src_data, ring_id; u32 ring_index; + unsigned long flags; bool queue_hotplug = false; if (!rdev->ih.enabled || rdev->shutdown) return IRQ_NONE; wptr = si_get_ih_wptr(rdev); - -restart_ih: - /* is somebody else already processing irqs? */ - if (atomic_xchg(&rdev->ih.lock, 1)) - return IRQ_NONE; - rptr = rdev->ih.rptr; DRM_DEBUG("si_irq_process start: rptr %d, wptr %d\n", rptr, wptr); + spin_lock_irqsave(&rdev->ih.lock, flags); + if (rptr == wptr) { + spin_unlock_irqrestore(&rdev->ih.lock, flags); + return IRQ_NONE; + } +restart_ih: /* Order reading of wptr vs. reading of IH ring data */ rmb(); /* display interrupts */ si_irq_ack(rdev); + rdev->ih.wptr = wptr; while (rptr != wptr) { /* wptr/rptr are in bytes! */ ring_index = rptr / 4; @@ -3429,7 +3399,7 @@ int si_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[0])) + if (rdev->irq.pflip[0]) radeon_crtc_handle_flip(rdev, 0); rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); @@ -3455,7 +3425,7 @@ int si_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[1])) + if (rdev->irq.pflip[1]) radeon_crtc_handle_flip(rdev, 1); rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); @@ -3481,7 +3451,7 @@ int si_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[2])) + if (rdev->irq.pflip[2]) radeon_crtc_handle_flip(rdev, 2); rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; DRM_DEBUG("IH: D3 vblank\n"); @@ -3507,7 +3477,7 @@ int si_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[3])) + if (rdev->irq.pflip[3]) radeon_crtc_handle_flip(rdev, 3); rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; DRM_DEBUG("IH: D4 vblank\n"); @@ -3533,7 +3503,7 @@ int si_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[4])) + if (rdev->irq.pflip[4]) radeon_crtc_handle_flip(rdev, 4); rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; DRM_DEBUG("IH: D5 vblank\n"); @@ -3559,7 +3529,7 @@ int si_irq_process(struct radeon_device *rdev) rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); } - if (atomic_read(&rdev->irq.pflip[5])) + if (rdev->irq.pflip[5]) radeon_crtc_handle_flip(rdev, 5); rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; DRM_DEBUG("IH: D6 vblank\n"); @@ -3650,6 +3620,7 @@ int si_irq_process(struct radeon_device *rdev) break; case 233: /* GUI IDLE */ DRM_DEBUG("IH: GUI idle\n"); + rdev->pm.gui_idle = true; wake_up(&rdev->irq.idle_queue); break; default: @@ -3661,17 +3632,15 @@ int si_irq_process(struct radeon_device *rdev) rptr += 16; rptr &= rdev->ih.ptr_mask; } + /* make sure wptr hasn't changed while processing */ + wptr = si_get_ih_wptr(rdev); + if (wptr != rdev->ih.wptr) + goto restart_ih; if (queue_hotplug) schedule_work(&rdev->hotplug_work); rdev->ih.rptr = rptr; WREG32(IH_RB_RPTR, rdev->ih.rptr); - atomic_set(&rdev->ih.lock, 0); - - /* make sure wptr hasn't changed while processing */ - wptr = si_get_ih_wptr(rdev); - if (wptr != rptr) - goto restart_ih; - + spin_unlock_irqrestore(&rdev->ih.lock, flags); return IRQ_HANDLED; } @@ -3783,18 +3752,35 @@ static int si_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_ib_pool_init(rdev); + r = radeon_ib_pool_start(rdev); + if (r) + return r; + + r = radeon_ib_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); if (r) { - dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + DRM_ERROR("radeon: failed testing IB (%d) on CP ring 0\n", r); + rdev->accel_working = false; return r; } - r = radeon_vm_manager_init(rdev); + r = radeon_ib_test(rdev, CAYMAN_RING_TYPE_CP1_INDEX, &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]); if (r) { - dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); + DRM_ERROR("radeon: failed testing IB (%d) on CP ring 1\n", r); + rdev->accel_working = false; return r; } + r = radeon_ib_test(rdev, CAYMAN_RING_TYPE_CP2_INDEX, &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]); + if (r) { + DRM_ERROR("radeon: failed testing IB (%d) on CP ring 2\n", r); + rdev->accel_working = false; + return r; + } + + r = radeon_vm_manager_start(rdev); + if (r) + return r; + return 0; } @@ -3823,6 +3809,12 @@ int si_resume(struct radeon_device *rdev) int si_suspend(struct radeon_device *rdev) { + /* FIXME: we should wait for ring to be empty */ + radeon_ib_pool_suspend(rdev); + radeon_vm_manager_suspend(rdev); +#if 0 + r600_blit_suspend(rdev); +#endif si_cp_enable(rdev, false); rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; @@ -3911,7 +3903,17 @@ int si_init(struct radeon_device *rdev) if (r) return r; + r = radeon_ib_pool_init(rdev); rdev->accel_working = true; + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + rdev->accel_working = false; + } + r = radeon_vm_manager_init(rdev); + if (r) { + dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); + } + r = si_startup(rdev); if (r) { dev_err(rdev->dev, "disabling GPU acceleration\n"); @@ -3919,7 +3921,7 @@ int si_init(struct radeon_device *rdev) si_irq_fini(rdev); si_rlc_fini(rdev); radeon_wb_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_vm_manager_fini(rdev); radeon_irq_kms_fini(rdev); si_pcie_gart_fini(rdev); @@ -3948,7 +3950,7 @@ void si_fini(struct radeon_device *rdev) si_rlc_fini(rdev); radeon_wb_fini(rdev); radeon_vm_manager_fini(rdev); - radeon_ib_pool_fini(rdev); + r100_ib_fini(rdev); radeon_irq_kms_fini(rdev); si_pcie_gart_fini(rdev); r600_vram_scratch_fini(rdev); diff --git a/trunk/drivers/gpu/drm/radeon/sid.h b/trunk/drivers/gpu/drm/radeon/sid.h index 7869089e8761..db4067962868 100644 --- a/trunk/drivers/gpu/drm/radeon/sid.h +++ b/trunk/drivers/gpu/drm/radeon/sid.h @@ -901,6 +901,5 @@ #define PACKET3_WAIT_ON_DE_COUNTER_DIFF 0x88 #define PACKET3_SET_CE_DE_COUNTERS 0x89 #define PACKET3_WAIT_ON_AVAIL_BUFFER 0x8A -#define PACKET3_SWITCH_BUFFER 0x8B #endif diff --git a/trunk/drivers/gpu/drm/savage/savage_bci.c b/trunk/drivers/gpu/drm/savage/savage_bci.c index 1efbb9075837..6eb507a5d130 100644 --- a/trunk/drivers/gpu/drm/savage/savage_bci.c +++ b/trunk/drivers/gpu/drm/savage/savage_bci.c @@ -1050,7 +1050,6 @@ void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) { struct drm_device_dma *dma = dev->dma; drm_savage_private_t *dev_priv = dev->dev_private; - int release_idlelock = 0; int i; if (!dma) @@ -1060,10 +1059,7 @@ void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) if (!dma->buflist) return; - if (file_priv->master && file_priv->master->lock.hw_lock) { - drm_idlelock_take(&file_priv->master->lock); - release_idlelock = 1; - } + /*i830_flush_queue(dev); */ for (i = 0; i < dma->buf_count; i++) { struct drm_buf *buf = dma->buflist[i]; @@ -1079,8 +1075,7 @@ void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) } } - if (release_idlelock) - drm_idlelock_release(&file_priv->master->lock); + drm_core_reclaim_buffers(dev, file_priv); } struct drm_ioctl_desc savage_ioctls[] = { diff --git a/trunk/drivers/gpu/drm/savage/savage_drv.c b/trunk/drivers/gpu/drm/savage/savage_drv.c index d31d4cca9a4c..89afe0b83643 100644 --- a/trunk/drivers/gpu/drm/savage/savage_drv.c +++ b/trunk/drivers/gpu/drm/savage/savage_drv.c @@ -52,9 +52,9 @@ static struct drm_driver driver = { .dev_priv_size = sizeof(drm_savage_buf_priv_t), .load = savage_driver_load, .firstopen = savage_driver_firstopen, - .preclose = savage_reclaim_buffers, .lastclose = savage_driver_lastclose, .unload = savage_driver_unload, + .reclaim_buffers = savage_reclaim_buffers, .ioctls = savage_ioctls, .dma_ioctl = savage_bci_buffers, .fops = &savage_driver_fops, diff --git a/trunk/drivers/gpu/drm/sis/sis_drv.c b/trunk/drivers/gpu/drm/sis/sis_drv.c index 7f119870147c..dd14cd1a0033 100644 --- a/trunk/drivers/gpu/drm/sis/sis_drv.c +++ b/trunk/drivers/gpu/drm/sis/sis_drv.c @@ -105,9 +105,10 @@ static struct drm_driver driver = { .load = sis_driver_load, .unload = sis_driver_unload, .open = sis_driver_open, - .preclose = sis_reclaim_buffers_locked, .postclose = sis_driver_postclose, .dma_quiescent = sis_idle, + .reclaim_buffers = NULL, + .reclaim_buffers_idlelocked = sis_reclaim_buffers_locked, .lastclose = sis_lastclose, .ioctls = sis_ioctls, .fops = &sis_driver_fops, diff --git a/trunk/drivers/gpu/drm/sis/sis_mm.c b/trunk/drivers/gpu/drm/sis/sis_mm.c index 2c231070d250..dd4a316c3d74 100644 --- a/trunk/drivers/gpu/drm/sis/sis_mm.c +++ b/trunk/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 dev_priv->vram_offset = fb->offset; mutex_unlock(&dev->struct_mutex); - DRM_DEBUG("offset = %lu, size = %lu\n", fb->offset, fb->size); + DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size); return 0; } @@ -161,7 +161,7 @@ static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file, mem->size = 0; mem->free = 0; - DRM_DEBUG("alloc %d, size = %ld, offset = %ld\n", pool, mem->size, + DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem->size, mem->offset); return retval; @@ -215,7 +215,7 @@ static int sis_ioctl_agp_init(struct drm_device *dev, void *data, dev_priv->agp_offset = agp->offset; mutex_unlock(&dev->struct_mutex); - DRM_DEBUG("offset = %lu, size = %lu\n", agp->offset, agp->size); + DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size); return 0; } @@ -321,20 +321,14 @@ void sis_reclaim_buffers_locked(struct drm_device *dev, struct sis_file_private *file_priv = file->driver_priv; struct sis_memblock *entry, *next; - if (!(file->minor->master && file->master->lock.hw_lock)) - return; - - drm_idlelock_take(&file->master->lock); - mutex_lock(&dev->struct_mutex); if (list_empty(&file_priv->obj_list)) { mutex_unlock(&dev->struct_mutex); - drm_idlelock_release(&file->master->lock); - return; } - sis_idle(dev); + if (dev->driver->dma_quiescent) + dev->driver->dma_quiescent(dev); list_for_each_entry_safe(entry, next, &file_priv->obj_list, @@ -349,9 +343,6 @@ void sis_reclaim_buffers_locked(struct drm_device *dev, kfree(entry); } mutex_unlock(&dev->struct_mutex); - - drm_idlelock_release(&file->master->lock); - return; } diff --git a/trunk/drivers/gpu/drm/tdfx/tdfx_drv.c b/trunk/drivers/gpu/drm/tdfx/tdfx_drv.c index 90f6b13acfac..1613c78544c0 100644 --- a/trunk/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/trunk/drivers/gpu/drm/tdfx/tdfx_drv.c @@ -54,6 +54,7 @@ static const struct file_operations tdfx_driver_fops = { static struct drm_driver driver = { .driver_features = DRIVER_USE_MTRR, + .reclaim_buffers = drm_core_reclaim_buffers, .fops = &tdfx_driver_fops, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/trunk/drivers/gpu/drm/udl/udl_encoder.c b/trunk/drivers/gpu/drm/udl/udl_encoder.c index 0731ab2e6c06..56e75f0f1df5 100644 --- a/trunk/drivers/gpu/drm/udl/udl_encoder.c +++ b/trunk/drivers/gpu/drm/udl/udl_encoder.c @@ -27,7 +27,7 @@ static void udl_encoder_disable(struct drm_encoder *encoder) } static bool udl_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; diff --git a/trunk/drivers/gpu/drm/udl/udl_modeset.c b/trunk/drivers/gpu/drm/udl/udl_modeset.c index f5dd89e891de..0d7816789da1 100644 --- a/trunk/drivers/gpu/drm/udl/udl_modeset.c +++ b/trunk/drivers/gpu/drm/udl/udl_modeset.c @@ -45,25 +45,12 @@ static char *udl_vidreg_unlock(char *buf) * 0x01 H and V sync off (screen blank but powered) * 0x07 DPMS powerdown (requires modeset to come back) */ -static char *udl_set_blank(char *buf, int dpms_mode) +static char *udl_enable_hvsync(char *buf, bool enable) { - u8 reg; - switch (dpms_mode) { - case DRM_MODE_DPMS_OFF: - reg = 0x07; - break; - case DRM_MODE_DPMS_STANDBY: - reg = 0x05; - break; - case DRM_MODE_DPMS_SUSPEND: - reg = 0x01; - break; - case DRM_MODE_DPMS_ON: - reg = 0x00; - break; - } - - return udl_set_register(buf, 0x1f, reg); + if (enable) + return udl_set_register(buf, 0x1F, 0x00); + else + return udl_set_register(buf, 0x1F, 0x07); } static char *udl_set_color_depth(char *buf, u8 selection) @@ -212,20 +199,6 @@ static char *udl_set_vid_cmds(char *wrptr, struct drm_display_mode *mode) return wrptr; } -static char *udl_dummy_render(char *wrptr) -{ - *wrptr++ = 0xAF; - *wrptr++ = 0x6A; /* copy */ - *wrptr++ = 0x00; /* from addr */ - *wrptr++ = 0x00; - *wrptr++ = 0x00; - *wrptr++ = 0x01; /* one pixel */ - *wrptr++ = 0x00; /* to address */ - *wrptr++ = 0x00; - *wrptr++ = 0x00; - return wrptr; -} - static int udl_crtc_write_mode_to_hw(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -262,10 +235,9 @@ static void udl_crtc_dpms(struct drm_crtc *crtc, int mode) buf = (char *)urb->transfer_buffer; buf = udl_vidreg_lock(buf); - buf = udl_set_blank(buf, mode); + buf = udl_enable_hvsync(buf, false); buf = udl_vidreg_unlock(buf); - buf = udl_dummy_render(buf); retval = udl_submit_urb(dev, urb, buf - (char *) urb->transfer_buffer); } else { @@ -279,7 +251,7 @@ static void udl_crtc_dpms(struct drm_crtc *crtc, int mode) } static bool udl_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { @@ -334,11 +306,9 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc, wrptr = udl_set_base8bpp(wrptr, 2 * mode->vdisplay * mode->hdisplay); wrptr = udl_set_vid_cmds(wrptr, adjusted_mode); - wrptr = udl_set_blank(wrptr, DRM_MODE_DPMS_ON); + wrptr = udl_enable_hvsync(wrptr, true); wrptr = udl_vidreg_unlock(wrptr); - wrptr = udl_dummy_render(wrptr); - ufb->active_16 = true; if (old_fb) { struct udl_framebuffer *uold_fb = to_udl_fb(old_fb); diff --git a/trunk/drivers/gpu/drm/via/via_drv.c b/trunk/drivers/gpu/drm/via/via_drv.c index e927b4c052f5..02661f35f7a0 100644 --- a/trunk/drivers/gpu/drm/via/via_drv.c +++ b/trunk/drivers/gpu/drm/via/via_drv.c @@ -75,7 +75,6 @@ static struct drm_driver driver = { .load = via_driver_load, .unload = via_driver_unload, .open = via_driver_open, - .preclose = via_reclaim_buffers_locked, .postclose = via_driver_postclose, .context_dtor = via_final_context, .get_vblank_counter = via_get_vblank_counter, @@ -86,6 +85,9 @@ static struct drm_driver driver = { .irq_uninstall = via_driver_irq_uninstall, .irq_handler = via_driver_irq_handler, .dma_quiescent = via_driver_dma_quiescent, + .reclaim_buffers = drm_core_reclaim_buffers, + .reclaim_buffers_locked = NULL, + .reclaim_buffers_idlelocked = via_reclaim_buffers_locked, .lastclose = via_lastclose, .ioctls = via_ioctls, .fops = &via_driver_fops, diff --git a/trunk/drivers/gpu/drm/via/via_mm.c b/trunk/drivers/gpu/drm/via/via_mm.c index acfcb358e7b7..a3574d09a07d 100644 --- a/trunk/drivers/gpu/drm/via/via_mm.c +++ b/trunk/drivers/gpu/drm/via/via_mm.c @@ -215,20 +215,14 @@ void via_reclaim_buffers_locked(struct drm_device *dev, struct via_file_private *file_priv = file->driver_priv; struct via_memblock *entry, *next; - if (!(file->minor->master && file->master->lock.hw_lock)) - return; - - drm_idlelock_take(&file->master->lock); - mutex_lock(&dev->struct_mutex); if (list_empty(&file_priv->obj_list)) { mutex_unlock(&dev->struct_mutex); - drm_idlelock_release(&file->master->lock); - return; } - via_driver_dma_quiescent(dev); + if (dev->driver->dma_quiescent) + dev->driver->dma_quiescent(dev); list_for_each_entry_safe(entry, next, &file_priv->obj_list, owner_list) { @@ -237,8 +231,5 @@ void via_reclaim_buffers_locked(struct drm_device *dev, kfree(entry); } mutex_unlock(&dev->struct_mutex); - - drm_idlelock_release(&file->master->lock); - return; } diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 4d9edead01ac..ee24d216aa85 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -769,7 +769,10 @@ static int vmw_driver_open(struct drm_device *dev, struct drm_file *file_priv) goto out_no_tfile; file_priv->driver_priv = vmw_fp; - dev_priv->bdev.dev_mapping = dev->dev_mapping; + + if (unlikely(dev_priv->bdev.dev_mapping == NULL)) + dev_priv->bdev.dev_mapping = + file_priv->filp->f_path.dentry->d_inode->i_mapping; return 0; @@ -1144,6 +1147,7 @@ static struct drm_driver driver = { .get_vblank_counter = vmw_get_vblank_counter, .enable_vblank = vmw_enable_vblank, .disable_vblank = vmw_disable_vblank, + .reclaim_buffers_locked = NULL, .ioctls = vmw_ioctls, .num_ioctls = DRM_ARRAY_SIZE(vmw_ioctls), .dma_quiescent = NULL, /*vmw_dma_quiescent, */ diff --git a/trunk/drivers/md/raid1.c b/trunk/drivers/md/raid1.c index 240ff3125040..8c2754f835ef 100644 --- a/trunk/drivers/md/raid1.c +++ b/trunk/drivers/md/raid1.c @@ -2485,10 +2485,9 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp */ if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { atomic_set(&r1_bio->remaining, read_targets); - for (i = 0; i < conf->raid_disks * 2 && read_targets; i++) { + for (i = 0; i < conf->raid_disks * 2; i++) { bio = r1_bio->bios[i]; if (bio->bi_end_io == end_sync_read) { - read_targets--; md_sync_acct(bio->bi_bdev, nr_sectors); generic_make_request(bio); } diff --git a/trunk/drivers/staging/omapdrm/omap_crtc.c b/trunk/drivers/staging/omapdrm/omap_crtc.c index 62e0022561bc..8b864afb40b6 100644 --- a/trunk/drivers/staging/omapdrm/omap_crtc.c +++ b/trunk/drivers/staging/omapdrm/omap_crtc.c @@ -60,7 +60,7 @@ static void omap_crtc_dpms(struct drm_crtc *crtc, int mode) } static bool omap_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { return true; diff --git a/trunk/drivers/staging/omapdrm/omap_encoder.c b/trunk/drivers/staging/omapdrm/omap_encoder.c index 31c735d39217..06c52cb62d2f 100644 --- a/trunk/drivers/staging/omapdrm/omap_encoder.c +++ b/trunk/drivers/staging/omapdrm/omap_encoder.c @@ -48,7 +48,7 @@ static void omap_encoder_dpms(struct drm_encoder *encoder, int mode) } static bool omap_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct omap_encoder *omap_encoder = to_omap_encoder(encoder); diff --git a/trunk/include/drm/drmP.h b/trunk/include/drm/drmP.h index d6b67bb9075f..31ad880ca2ef 100644 --- a/trunk/include/drm/drmP.h +++ b/trunk/include/drm/drmP.h @@ -348,6 +348,7 @@ struct drm_buf { struct drm_buf *next; /**< Kernel-only: used for free list */ __volatile__ int waiting; /**< On kernel DMA queue */ __volatile__ int pending; /**< On hardware DMA queue */ + wait_queue_head_t dma_wait; /**< Processes waiting */ struct drm_file *file_priv; /**< Private of holding file descr */ int context; /**< Kernel queue for this buffer */ int while_locked; /**< Dispatch this buffer while locked */ @@ -875,6 +876,12 @@ struct drm_driver { void (*irq_preinstall) (struct drm_device *dev); int (*irq_postinstall) (struct drm_device *dev); void (*irq_uninstall) (struct drm_device *dev); + void (*reclaim_buffers) (struct drm_device *dev, + struct drm_file * file_priv); + void (*reclaim_buffers_locked) (struct drm_device *dev, + struct drm_file *file_priv); + void (*reclaim_buffers_idlelocked) (struct drm_device *dev, + struct drm_file *file_priv); void (*set_version) (struct drm_device *dev, struct drm_set_version *sv); @@ -1101,8 +1108,12 @@ struct drm_device { /*@} */ - /** \name DMA support */ + /** \name DMA queues (contexts) */ /*@{ */ + int queue_count; /**< Number of active DMA queues */ + int queue_reserved; /**< Number of reserved DMA queues */ + int queue_slots; /**< Actual length of queuelist */ + struct drm_queue **queuelist; /**< Vector of pointers to DMA queues */ struct drm_device_dma *dma; /**< Optional pointer for DMA support */ /*@} */ @@ -1529,6 +1540,7 @@ extern int drm_debugfs_cleanup(struct drm_minor *minor); /* Info file support */ extern int drm_name_info(struct seq_file *m, void *data); extern int drm_vm_info(struct seq_file *m, void *data); +extern int drm_queues_info(struct seq_file *m, void *data); extern int drm_bufs_info(struct seq_file *m, void *data); extern int drm_vblank_info(struct seq_file *m, void *data); extern int drm_clients_info(struct seq_file *m, void* data); @@ -1749,11 +1761,6 @@ extern int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver); -#define DRM_PCIE_SPEED_25 1 -#define DRM_PCIE_SPEED_50 2 -#define DRM_PCIE_SPEED_80 4 - -extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask); /* platform section */ extern int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device); diff --git a/trunk/include/drm/drm_crtc.h b/trunk/include/drm/drm_crtc.h index a1a0386e0160..bac55c215113 100644 --- a/trunk/include/drm/drm_crtc.h +++ b/trunk/include/drm/drm_crtc.h @@ -676,6 +676,8 @@ struct drm_plane { * This is used to set modes. */ struct drm_mode_set { + struct list_head head; + struct drm_framebuffer *fb; struct drm_crtc *crtc; struct drm_display_mode *mode; diff --git a/trunk/include/drm/drm_crtc_helper.h b/trunk/include/drm/drm_crtc_helper.h index e01cc80c9c30..7988e55c98d0 100644 --- a/trunk/include/drm/drm_crtc_helper.h +++ b/trunk/include/drm/drm_crtc_helper.h @@ -62,7 +62,7 @@ struct drm_crtc_helper_funcs { /* Provider can fixup or change mode timings before modeset occurs */ bool (*mode_fixup)(struct drm_crtc *crtc, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); /* Actually set the mode */ int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, @@ -96,7 +96,7 @@ struct drm_encoder_helper_funcs { void (*restore)(struct drm_encoder *encoder); bool (*mode_fixup)(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); void (*prepare)(struct drm_encoder *encoder); void (*commit)(struct drm_encoder *encoder); diff --git a/trunk/include/drm/drm_encoder_slave.h b/trunk/include/drm/drm_encoder_slave.h index 7dc385233805..2f65633d28a7 100644 --- a/trunk/include/drm/drm_encoder_slave.h +++ b/trunk/include/drm/drm_encoder_slave.h @@ -54,7 +54,7 @@ struct drm_encoder_slave_funcs { void (*save)(struct drm_encoder *encoder); void (*restore)(struct drm_encoder *encoder); bool (*mode_fixup)(struct drm_encoder *encoder, - const struct drm_display_mode *mode, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); int (*mode_valid)(struct drm_encoder *encoder, struct drm_display_mode *mode); diff --git a/trunk/include/drm/drm_mm.h b/trunk/include/drm/drm_mm.h index 06d7f798a08c..564b14aa7e16 100644 --- a/trunk/include/drm/drm_mm.h +++ b/trunk/include/drm/drm_mm.h @@ -50,7 +50,6 @@ struct drm_mm_node { unsigned scanned_next_free : 1; unsigned scanned_preceeds_hole : 1; unsigned allocated : 1; - unsigned long color; unsigned long start; unsigned long size; struct drm_mm *mm; @@ -67,7 +66,6 @@ struct drm_mm { spinlock_t unused_lock; unsigned int scan_check_range : 1; unsigned scan_alignment; - unsigned long scan_color; unsigned long scan_size; unsigned long scan_hit_start; unsigned scan_hit_size; @@ -75,9 +73,6 @@ struct drm_mm { unsigned long scan_start; unsigned long scan_end; struct drm_mm_node *prev_scanned_node; - - void (*color_adjust)(struct drm_mm_node *node, unsigned long color, - unsigned long *start, unsigned long *end); }; static inline bool drm_mm_node_allocated(struct drm_mm_node *node) @@ -105,13 +100,11 @@ static inline bool drm_mm_initialized(struct drm_mm *mm) extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, unsigned long size, unsigned alignment, - unsigned long color, int atomic); extern struct drm_mm_node *drm_mm_get_block_range_generic( struct drm_mm_node *node, unsigned long size, unsigned alignment, - unsigned long color, unsigned long start, unsigned long end, int atomic); @@ -119,13 +112,13 @@ static inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent, unsigned long size, unsigned alignment) { - return drm_mm_get_block_generic(parent, size, alignment, 0, 0); + return drm_mm_get_block_generic(parent, size, alignment, 0); } static inline struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *parent, unsigned long size, unsigned alignment) { - return drm_mm_get_block_generic(parent, size, alignment, 0, 1); + return drm_mm_get_block_generic(parent, size, alignment, 1); } static inline struct drm_mm_node *drm_mm_get_block_range( struct drm_mm_node *parent, @@ -134,19 +127,8 @@ static inline struct drm_mm_node *drm_mm_get_block_range( unsigned long start, unsigned long end) { - return drm_mm_get_block_range_generic(parent, size, alignment, 0, - start, end, 0); -} -static inline struct drm_mm_node *drm_mm_get_color_block_range( - struct drm_mm_node *parent, - unsigned long size, - unsigned alignment, - unsigned long color, - unsigned long start, - unsigned long end) -{ - return drm_mm_get_block_range_generic(parent, size, alignment, color, - start, end, 0); + return drm_mm_get_block_range_generic(parent, size, alignment, + start, end, 0); } static inline struct drm_mm_node *drm_mm_get_block_atomic_range( struct drm_mm_node *parent, @@ -155,7 +137,7 @@ static inline struct drm_mm_node *drm_mm_get_block_atomic_range( unsigned long start, unsigned long end) { - return drm_mm_get_block_range_generic(parent, size, alignment, 0, + return drm_mm_get_block_range_generic(parent, size, alignment, start, end, 1); } extern int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, @@ -167,59 +149,18 @@ extern int drm_mm_insert_node_in_range(struct drm_mm *mm, extern void drm_mm_put_block(struct drm_mm_node *cur); extern void drm_mm_remove_node(struct drm_mm_node *node); extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new); -extern struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, - unsigned long size, - unsigned alignment, - unsigned long color, - bool best_match); -extern struct drm_mm_node *drm_mm_search_free_in_range_generic( - const struct drm_mm *mm, - unsigned long size, - unsigned alignment, - unsigned long color, - unsigned long start, - unsigned long end, - bool best_match); -static inline struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, - unsigned long size, - unsigned alignment, - bool best_match) -{ - return drm_mm_search_free_generic(mm,size, alignment, 0, best_match); -} -static inline struct drm_mm_node *drm_mm_search_free_in_range( +extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, + unsigned long size, + unsigned alignment, + int best_match); +extern struct drm_mm_node *drm_mm_search_free_in_range( const struct drm_mm *mm, unsigned long size, unsigned alignment, unsigned long start, unsigned long end, - bool best_match) -{ - return drm_mm_search_free_in_range_generic(mm, size, alignment, 0, - start, end, best_match); -} -static inline struct drm_mm_node *drm_mm_search_free_color(const struct drm_mm *mm, - unsigned long size, - unsigned alignment, - unsigned long color, - bool best_match) -{ - return drm_mm_search_free_generic(mm,size, alignment, color, best_match); -} -static inline struct drm_mm_node *drm_mm_search_free_in_range_color( - const struct drm_mm *mm, - unsigned long size, - unsigned alignment, - unsigned long color, - unsigned long start, - unsigned long end, - bool best_match) -{ - return drm_mm_search_free_in_range_generic(mm, size, alignment, color, - start, end, best_match); -} -extern int drm_mm_init(struct drm_mm *mm, - unsigned long start, + int best_match); +extern int drm_mm_init(struct drm_mm *mm, unsigned long start, unsigned long size); extern void drm_mm_takedown(struct drm_mm *mm); extern int drm_mm_clean(struct drm_mm *mm); @@ -230,14 +171,10 @@ static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block) return block->mm; } -void drm_mm_init_scan(struct drm_mm *mm, - unsigned long size, - unsigned alignment, - unsigned long color); -void drm_mm_init_scan_with_range(struct drm_mm *mm, - unsigned long size, +void drm_mm_init_scan(struct drm_mm *mm, unsigned long size, + unsigned alignment); +void drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size, unsigned alignment, - unsigned long color, unsigned long start, unsigned long end); int drm_mm_scan_add_block(struct drm_mm_node *node); diff --git a/trunk/include/drm/drm_pciids.h b/trunk/include/drm/drm_pciids.h index 7ff5c99b1638..a7aec391b7b7 100644 --- a/trunk/include/drm/drm_pciids.h +++ b/trunk/include/drm/drm_pciids.h @@ -686,6 +686,14 @@ {0x8086, 0x1132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0, 0, 0} +#define i830_PCI_IDS \ + {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x358e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0, 0, 0} + #define gamma_PCI_IDS \ {0x3d3d, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0, 0, 0} @@ -718,3 +726,37 @@ #define ffb_PCI_IDS \ {0, 0, 0} + +#define i915_PCI_IDS \ + {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x258a, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x27a2, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x27ae, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x2972, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x2982, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x2992, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x29a2, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x29b2, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x29c2, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x29d2, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x2a02, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x2a12, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x2a42, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x2e02, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x2e12, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x2e22, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x2e32, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x2e42, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0xa001, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0xa011, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x35e8, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x0042, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x0046, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x0102, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0, 0, 0} diff --git a/trunk/include/drm/i915_drm.h b/trunk/include/drm/i915_drm.h index 8cc70837f929..f3f82242bf1d 100644 --- a/trunk/include/drm/i915_drm.h +++ b/trunk/include/drm/i915_drm.h @@ -200,9 +200,6 @@ typedef struct _drm_i915_sarea { #define DRM_I915_GEM_EXECBUFFER2 0x29 #define DRM_I915_GET_SPRITE_COLORKEY 0x2a #define DRM_I915_SET_SPRITE_COLORKEY 0x2b -#define DRM_I915_GEM_WAIT 0x2c -#define DRM_I915_GEM_CONTEXT_CREATE 0x2d -#define DRM_I915_GEM_CONTEXT_DESTROY 0x2e #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -246,9 +243,6 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs) #define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) #define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey) -#define DRM_IOCTL_I915_GEM_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait) -#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create) -#define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -304,7 +298,6 @@ typedef struct drm_i915_irq_wait { #define I915_PARAM_HAS_GEN7_SOL_RESET 16 #define I915_PARAM_HAS_LLC 17 #define I915_PARAM_HAS_ALIASING_PPGTT 18 -#define I915_PARAM_HAS_WAIT_TIMEOUT 19 typedef struct drm_i915_getparam { int param; @@ -663,19 +656,13 @@ struct drm_i915_gem_execbuffer2 { #define I915_EXEC_CONSTANTS_ABSOLUTE (1<<6) #define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */ __u64 flags; - __u64 rsvd1; /* now used for context info */ + __u64 rsvd1; __u64 rsvd2; }; /** Resets the SO write offset registers for transform feedback on gen7. */ #define I915_EXEC_GEN7_SOL_RESET (1<<8) -#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) -#define i915_execbuffer2_set_context_id(eb2, context) \ - (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK -#define i915_execbuffer2_get_context_id(eb2) \ - ((eb2).rsvd1 & I915_EXEC_CONTEXT_ID_MASK) - struct drm_i915_gem_pin { /** Handle of the buffer to be pinned. */ __u32 handle; @@ -899,23 +886,4 @@ struct drm_intel_sprite_colorkey { __u32 flags; }; -struct drm_i915_gem_wait { - /** Handle of BO we shall wait on */ - __u32 bo_handle; - __u32 flags; - /** Number of nanoseconds to wait, Returns time remaining. */ - __s64 timeout_ns; -}; - -struct drm_i915_gem_context_create { - /* output: id of new context*/ - __u32 ctx_id; - __u32 pad; -}; - -struct drm_i915_gem_context_destroy { - __u32 ctx_id; - __u32 pad; -}; - #endif /* _I915_DRM_H_ */ diff --git a/trunk/include/drm/intel-gtt.h b/trunk/include/drm/intel-gtt.h index 8e29d551bb3c..923afb5dcf0c 100644 --- a/trunk/include/drm/intel-gtt.h +++ b/trunk/include/drm/intel-gtt.h @@ -19,16 +19,8 @@ const struct intel_gtt { dma_addr_t scratch_page_dma; /* for ppgtt PDE access */ u32 __iomem *gtt; - /* needed for ioremap in drm/i915 */ - phys_addr_t gma_bus_addr; } *intel_gtt_get(void); -int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, - struct agp_bridge_data *bridge); -void intel_gmch_remove(void); - -bool intel_enable_gtt(void); - void intel_gtt_chipset_flush(void); void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg); void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries); diff --git a/trunk/include/drm/sis_drm.h b/trunk/include/drm/sis_drm.h index df3763222d73..035b804dda6d 100644 --- a/trunk/include/drm/sis_drm.h +++ b/trunk/include/drm/sis_drm.h @@ -51,17 +51,17 @@ typedef struct { int context; - unsigned long offset; - unsigned long size; + unsigned int offset; + unsigned int size; unsigned long free; } drm_sis_mem_t; typedef struct { - unsigned long offset, size; + unsigned int offset, size; } drm_sis_agp_t; typedef struct { - unsigned long offset, size; + unsigned int offset, size; } drm_sis_fb_t; struct sis_file_private { diff --git a/trunk/include/drm/ttm/ttm_bo_driver.h b/trunk/include/drm/ttm/ttm_bo_driver.h index 084e8989a6e1..a05f1b55714d 100644 --- a/trunk/include/drm/ttm/ttm_bo_driver.h +++ b/trunk/include/drm/ttm/ttm_bo_driver.h @@ -39,6 +39,8 @@ #include "linux/fs.h" #include "linux/spinlock.h" +struct ttm_backend; + struct ttm_backend_func { /** * struct ttm_backend_func member bind @@ -117,6 +119,7 @@ struct ttm_tt { unsigned long num_pages; struct sg_table *sg; /* for SG objects via dma-buf */ struct ttm_bo_global *glob; + struct ttm_backend *be; struct file *swap_storage; enum ttm_caching_state caching_state; enum { diff --git a/trunk/include/linux/hrtimer.h b/trunk/include/linux/hrtimer.h index cc07d2777bbe..fd0dc30c9f15 100644 --- a/trunk/include/linux/hrtimer.h +++ b/trunk/include/linux/hrtimer.h @@ -165,7 +165,6 @@ enum hrtimer_base_type { * @lock: lock protecting the base and associated clock bases * and timers * @active_bases: Bitfield to mark bases with active timers - * @clock_was_set: Indicates that clock was set from irq context. * @expires_next: absolute time of the next event which was scheduled * via clock_set_next_event() * @hres_active: State of high resolution mode @@ -178,8 +177,7 @@ enum hrtimer_base_type { */ struct hrtimer_cpu_base { raw_spinlock_t lock; - unsigned int active_bases; - unsigned int clock_was_set; + unsigned long active_bases; #ifdef CONFIG_HIGH_RES_TIMERS ktime_t expires_next; int hres_active; @@ -288,8 +286,6 @@ extern void hrtimer_peek_ahead_timers(void); # define MONOTONIC_RES_NSEC HIGH_RES_NSEC # define KTIME_MONOTONIC_RES KTIME_HIGH_RES -extern void clock_was_set_delayed(void); - #else # define MONOTONIC_RES_NSEC LOW_RES_NSEC @@ -310,9 +306,6 @@ static inline int hrtimer_is_hres_active(struct hrtimer *timer) { return 0; } - -static inline void clock_was_set_delayed(void) { } - #endif extern void clock_was_set(void); @@ -327,7 +320,6 @@ extern ktime_t ktime_get(void); extern ktime_t ktime_get_real(void); extern ktime_t ktime_get_boottime(void); extern ktime_t ktime_get_monotonic_offset(void); -extern ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot); DECLARE_PER_CPU(struct tick_device, tick_cpu_device); diff --git a/trunk/include/linux/pci_regs.h b/trunk/include/linux/pci_regs.h index 7f04132eb02d..4b608f543412 100644 --- a/trunk/include/linux/pci_regs.h +++ b/trunk/include/linux/pci_regs.h @@ -521,11 +521,6 @@ #define PCI_EXP_OBFF_MSGA_EN 0x2000 /* OBFF enable with Message type A */ #define PCI_EXP_OBFF_MSGB_EN 0x4000 /* OBFF enable with Message type B */ #define PCI_EXP_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */ -#define PCI_EXP_LNKCAP2 44 /* Link Capability 2 */ -#define PCI_EXP_LNKCAP2_SLS_2_5GB 0x01 /* Current Link Speed 2.5GT/s */ -#define PCI_EXP_LNKCAP2_SLS_5_0GB 0x02 /* Current Link Speed 5.0GT/s */ -#define PCI_EXP_LNKCAP2_SLS_8_0GB 0x04 /* Current Link Speed 8.0GT/s */ -#define PCI_EXP_LNKCAP2_CROSSLINK 0x100 /* Crosslink supported */ #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ #define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */ diff --git a/trunk/include/linux/rcupdate.h b/trunk/include/linux/rcupdate.h index 9cac722b169c..26d1a47591f1 100644 --- a/trunk/include/linux/rcupdate.h +++ b/trunk/include/linux/rcupdate.h @@ -184,6 +184,7 @@ static inline int rcu_preempt_depth(void) /* Internal to kernel */ extern void rcu_sched_qs(int cpu); extern void rcu_bh_qs(int cpu); +extern void rcu_preempt_note_context_switch(void); extern void rcu_check_callbacks(int cpu, int user); struct notifier_block; extern void rcu_idle_enter(void); diff --git a/trunk/include/linux/rcutiny.h b/trunk/include/linux/rcutiny.h index 4e56a9c69a35..854dc4c5c271 100644 --- a/trunk/include/linux/rcutiny.h +++ b/trunk/include/linux/rcutiny.h @@ -87,10 +87,6 @@ static inline void kfree_call_rcu(struct rcu_head *head, #ifdef CONFIG_TINY_RCU -static inline void rcu_preempt_note_context_switch(void) -{ -} - static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) { *delta_jiffies = ULONG_MAX; @@ -99,7 +95,6 @@ static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) #else /* #ifdef CONFIG_TINY_RCU */ -void rcu_preempt_note_context_switch(void); int rcu_preempt_needs_cpu(void); static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) @@ -113,7 +108,6 @@ static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies) static inline void rcu_note_context_switch(int cpu) { rcu_sched_qs(cpu); - rcu_preempt_note_context_switch(); } /* diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index 4a1f493e0fef..4059c0f33f07 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -1871,12 +1871,22 @@ static inline void rcu_copy_process(struct task_struct *p) INIT_LIST_HEAD(&p->rcu_node_entry); } +static inline void rcu_switch_from(struct task_struct *prev) +{ + if (prev->rcu_read_lock_nesting != 0) + rcu_preempt_note_context_switch(); +} + #else static inline void rcu_copy_process(struct task_struct *p) { } +static inline void rcu_switch_from(struct task_struct *prev) +{ +} + #endif #ifdef CONFIG_SMP @@ -1899,14 +1909,6 @@ static inline int set_cpus_allowed_ptr(struct task_struct *p, } #endif -#ifdef CONFIG_NO_HZ -void calc_load_enter_idle(void); -void calc_load_exit_idle(void); -#else -static inline void calc_load_enter_idle(void) { } -static inline void calc_load_exit_idle(void) { } -#endif /* CONFIG_NO_HZ */ - #ifndef CONFIG_CPUMASK_OFFSTACK static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask) { diff --git a/trunk/kernel/fork.c b/trunk/kernel/fork.c index f00e319d8376..ab5211b9e622 100644 --- a/trunk/kernel/fork.c +++ b/trunk/kernel/fork.c @@ -304,17 +304,12 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) } err = arch_dup_task_struct(tsk, orig); - - /* - * We defer looking at err, because we will need this setup - * for the clean up path to work correctly. - */ - tsk->stack = ti; - setup_thread_stack(tsk, orig); - if (err) goto out; + tsk->stack = ti; + + setup_thread_stack(tsk, orig); clear_user_return_notifier(tsk); clear_tsk_need_resched(tsk); stackend = end_of_stack(tsk); diff --git a/trunk/kernel/hrtimer.c b/trunk/kernel/hrtimer.c index 6db7a5ed52b5..ae34bf51682b 100644 --- a/trunk/kernel/hrtimer.c +++ b/trunk/kernel/hrtimer.c @@ -657,14 +657,6 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, return 0; } -static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base) -{ - ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset; - ktime_t *offs_boot = &base->clock_base[HRTIMER_BASE_BOOTTIME].offset; - - return ktime_get_update_offsets(offs_real, offs_boot); -} - /* * Retrigger next event is called after clock was set * @@ -673,12 +665,22 @@ static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base) static void retrigger_next_event(void *arg) { struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases); + struct timespec realtime_offset, xtim, wtm, sleep; if (!hrtimer_hres_active()) return; + /* Optimized out for !HIGH_RES */ + get_xtime_and_monotonic_and_sleep_offset(&xtim, &wtm, &sleep); + set_normalized_timespec(&realtime_offset, -wtm.tv_sec, -wtm.tv_nsec); + + /* Adjust CLOCK_REALTIME offset */ raw_spin_lock(&base->lock); - hrtimer_update_base(base); + base->clock_base[HRTIMER_BASE_REALTIME].offset = + timespec_to_ktime(realtime_offset); + base->clock_base[HRTIMER_BASE_BOOTTIME].offset = + timespec_to_ktime(sleep); + hrtimer_force_reprogram(base, 0); raw_spin_unlock(&base->lock); } @@ -708,25 +710,13 @@ static int hrtimer_switch_to_hres(void) base->clock_base[i].resolution = KTIME_HIGH_RES; tick_setup_sched_timer(); + /* "Retrigger" the interrupt to get things going */ retrigger_next_event(NULL); local_irq_restore(flags); return 1; } -/* - * Called from timekeeping code to reprogramm the hrtimer interrupt - * device. If called from the timer interrupt context we defer it to - * softirq context. - */ -void clock_was_set_delayed(void) -{ - struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); - - cpu_base->clock_was_set = 1; - __raise_softirq_irqoff(HRTIMER_SOFTIRQ); -} - #else static inline int hrtimer_hres_active(void) { return 0; } @@ -1260,10 +1250,11 @@ void hrtimer_interrupt(struct clock_event_device *dev) cpu_base->nr_events++; dev->next_event.tv64 = KTIME_MAX; - raw_spin_lock(&cpu_base->lock); - entry_time = now = hrtimer_update_base(cpu_base); + entry_time = now = ktime_get(); retry: expires_next.tv64 = KTIME_MAX; + + raw_spin_lock(&cpu_base->lock); /* * We set expires_next to KTIME_MAX here with cpu_base->lock * held to prevent that a timer is enqueued in our queue via @@ -1339,12 +1330,8 @@ void hrtimer_interrupt(struct clock_event_device *dev) * We need to prevent that we loop forever in the hrtimer * interrupt routine. We give it 3 attempts to avoid * overreacting on some spurious event. - * - * Acquire base lock for updating the offsets and retrieving - * the current time. */ - raw_spin_lock(&cpu_base->lock); - now = hrtimer_update_base(cpu_base); + now = ktime_get(); cpu_base->nr_retries++; if (++retries < 3) goto retry; @@ -1356,7 +1343,6 @@ void hrtimer_interrupt(struct clock_event_device *dev) */ cpu_base->nr_hangs++; cpu_base->hang_detected = 1; - raw_spin_unlock(&cpu_base->lock); delta = ktime_sub(now, entry_time); if (delta.tv64 > cpu_base->max_hang_time.tv64) cpu_base->max_hang_time = delta; @@ -1409,13 +1395,6 @@ void hrtimer_peek_ahead_timers(void) static void run_hrtimer_softirq(struct softirq_action *h) { - struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); - - if (cpu_base->clock_was_set) { - cpu_base->clock_was_set = 0; - clock_was_set(); - } - hrtimer_peek_ahead_timers(); } diff --git a/trunk/kernel/rcutree.c b/trunk/kernel/rcutree.c index 4b97bba7396e..38ecdda3f55f 100644 --- a/trunk/kernel/rcutree.c +++ b/trunk/kernel/rcutree.c @@ -201,7 +201,6 @@ void rcu_note_context_switch(int cpu) { trace_rcu_utilization("Start context switch"); rcu_sched_qs(cpu); - rcu_preempt_note_context_switch(cpu); trace_rcu_utilization("End context switch"); } EXPORT_SYMBOL_GPL(rcu_note_context_switch); diff --git a/trunk/kernel/rcutree.h b/trunk/kernel/rcutree.h index 19b61ac1079f..ea056495783e 100644 --- a/trunk/kernel/rcutree.h +++ b/trunk/kernel/rcutree.h @@ -444,7 +444,6 @@ DECLARE_PER_CPU(char, rcu_cpu_has_work); /* Forward declarations for rcutree_plugin.h */ static void rcu_bootup_announce(void); long rcu_batches_completed(void); -static void rcu_preempt_note_context_switch(int cpu); static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp); #ifdef CONFIG_HOTPLUG_CPU static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, diff --git a/trunk/kernel/rcutree_plugin.h b/trunk/kernel/rcutree_plugin.h index 3e4899459f3d..5271a020887e 100644 --- a/trunk/kernel/rcutree_plugin.h +++ b/trunk/kernel/rcutree_plugin.h @@ -153,7 +153,7 @@ static void rcu_preempt_qs(int cpu) * * Caller must disable preemption. */ -static void rcu_preempt_note_context_switch(int cpu) +void rcu_preempt_note_context_switch(void) { struct task_struct *t = current; unsigned long flags; @@ -164,7 +164,7 @@ static void rcu_preempt_note_context_switch(int cpu) (t->rcu_read_unlock_special & RCU_READ_UNLOCK_BLOCKED) == 0) { /* Possibly blocking in an RCU read-side critical section. */ - rdp = per_cpu_ptr(rcu_preempt_state.rda, cpu); + rdp = __this_cpu_ptr(rcu_preempt_state.rda); rnp = rdp->mynode; raw_spin_lock_irqsave(&rnp->lock, flags); t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BLOCKED; @@ -228,7 +228,7 @@ static void rcu_preempt_note_context_switch(int cpu) * means that we continue to block the current grace period. */ local_irq_save(flags); - rcu_preempt_qs(cpu); + rcu_preempt_qs(smp_processor_id()); local_irq_restore(flags); } @@ -1001,14 +1001,6 @@ void rcu_force_quiescent_state(void) } EXPORT_SYMBOL_GPL(rcu_force_quiescent_state); -/* - * Because preemptible RCU does not exist, we never have to check for - * CPUs being in quiescent states. - */ -static void rcu_preempt_note_context_switch(int cpu) -{ -} - /* * Because preemptible RCU does not exist, there are never any preempted * RCU readers. diff --git a/trunk/kernel/sched/core.c b/trunk/kernel/sched/core.c index 468bdd44c1ba..d5594a4268d4 100644 --- a/trunk/kernel/sched/core.c +++ b/trunk/kernel/sched/core.c @@ -2081,6 +2081,7 @@ context_switch(struct rq *rq, struct task_struct *prev, #endif /* Here we just switch the register state and the stack. */ + rcu_switch_from(prev); switch_to(prev, next, prev); barrier(); @@ -2160,73 +2161,11 @@ unsigned long this_cpu_load(void) } -/* - * Global load-average calculations - * - * We take a distributed and async approach to calculating the global load-avg - * in order to minimize overhead. - * - * The global load average is an exponentially decaying average of nr_running + - * nr_uninterruptible. - * - * Once every LOAD_FREQ: - * - * nr_active = 0; - * for_each_possible_cpu(cpu) - * nr_active += cpu_of(cpu)->nr_running + cpu_of(cpu)->nr_uninterruptible; - * - * avenrun[n] = avenrun[0] * exp_n + nr_active * (1 - exp_n) - * - * Due to a number of reasons the above turns in the mess below: - * - * - for_each_possible_cpu() is prohibitively expensive on machines with - * serious number of cpus, therefore we need to take a distributed approach - * to calculating nr_active. - * - * \Sum_i x_i(t) = \Sum_i x_i(t) - x_i(t_0) | x_i(t_0) := 0 - * = \Sum_i { \Sum_j=1 x_i(t_j) - x_i(t_j-1) } - * - * So assuming nr_active := 0 when we start out -- true per definition, we - * can simply take per-cpu deltas and fold those into a global accumulate - * to obtain the same result. See calc_load_fold_active(). - * - * Furthermore, in order to avoid synchronizing all per-cpu delta folding - * across the machine, we assume 10 ticks is sufficient time for every - * cpu to have completed this task. - * - * This places an upper-bound on the IRQ-off latency of the machine. Then - * again, being late doesn't loose the delta, just wrecks the sample. - * - * - cpu_rq()->nr_uninterruptible isn't accurately tracked per-cpu because - * this would add another cross-cpu cacheline miss and atomic operation - * to the wakeup path. Instead we increment on whatever cpu the task ran - * when it went into uninterruptible state and decrement on whatever cpu - * did the wakeup. This means that only the sum of nr_uninterruptible over - * all cpus yields the correct result. - * - * This covers the NO_HZ=n code, for extra head-aches, see the comment below. - */ - /* Variables and functions for calc_load */ static atomic_long_t calc_load_tasks; static unsigned long calc_load_update; unsigned long avenrun[3]; -EXPORT_SYMBOL(avenrun); /* should be removed */ - -/** - * get_avenrun - get the load average array - * @loads: pointer to dest load array - * @offset: offset to add - * @shift: shift count to shift the result left - * - * These values are estimates at best, so no need for locking. - */ -void get_avenrun(unsigned long *loads, unsigned long offset, int shift) -{ - loads[0] = (avenrun[0] + offset) << shift; - loads[1] = (avenrun[1] + offset) << shift; - loads[2] = (avenrun[2] + offset) << shift; -} +EXPORT_SYMBOL(avenrun); static long calc_load_fold_active(struct rq *this_rq) { @@ -2243,9 +2182,6 @@ static long calc_load_fold_active(struct rq *this_rq) return delta; } -/* - * a1 = a0 * e + a * (1 - e) - */ static unsigned long calc_load(unsigned long load, unsigned long exp, unsigned long active) { @@ -2257,118 +2193,30 @@ calc_load(unsigned long load, unsigned long exp, unsigned long active) #ifdef CONFIG_NO_HZ /* - * Handle NO_HZ for the global load-average. - * - * Since the above described distributed algorithm to compute the global - * load-average relies on per-cpu sampling from the tick, it is affected by - * NO_HZ. - * - * The basic idea is to fold the nr_active delta into a global idle-delta upon - * entering NO_HZ state such that we can include this as an 'extra' cpu delta - * when we read the global state. - * - * Obviously reality has to ruin such a delightfully simple scheme: - * - * - When we go NO_HZ idle during the window, we can negate our sample - * contribution, causing under-accounting. - * - * We avoid this by keeping two idle-delta counters and flipping them - * when the window starts, thus separating old and new NO_HZ load. - * - * The only trick is the slight shift in index flip for read vs write. - * - * 0s 5s 10s 15s - * +10 +10 +10 +10 - * |-|-----------|-|-----------|-|-----------|-| - * r:0 0 1 1 0 0 1 1 0 - * w:0 1 1 0 0 1 1 0 0 - * - * This ensures we'll fold the old idle contribution in this window while - * accumlating the new one. - * - * - When we wake up from NO_HZ idle during the window, we push up our - * contribution, since we effectively move our sample point to a known - * busy state. - * - * This is solved by pushing the window forward, and thus skipping the - * sample, for this cpu (effectively using the idle-delta for this cpu which - * was in effect at the time the window opened). This also solves the issue - * of having to deal with a cpu having been in NOHZ idle for multiple - * LOAD_FREQ intervals. + * For NO_HZ we delay the active fold to the next LOAD_FREQ update. * * When making the ILB scale, we should try to pull this in as well. */ -static atomic_long_t calc_load_idle[2]; -static int calc_load_idx; +static atomic_long_t calc_load_tasks_idle; -static inline int calc_load_write_idx(void) +void calc_load_account_idle(struct rq *this_rq) { - int idx = calc_load_idx; - - /* - * See calc_global_nohz(), if we observe the new index, we also - * need to observe the new update time. - */ - smp_rmb(); - - /* - * If the folding window started, make sure we start writing in the - * next idle-delta. - */ - if (!time_before(jiffies, calc_load_update)) - idx++; - - return idx & 1; -} - -static inline int calc_load_read_idx(void) -{ - return calc_load_idx & 1; -} - -void calc_load_enter_idle(void) -{ - struct rq *this_rq = this_rq(); long delta; - /* - * We're going into NOHZ mode, if there's any pending delta, fold it - * into the pending idle delta. - */ delta = calc_load_fold_active(this_rq); - if (delta) { - int idx = calc_load_write_idx(); - atomic_long_add(delta, &calc_load_idle[idx]); - } -} - -void calc_load_exit_idle(void) -{ - struct rq *this_rq = this_rq(); - - /* - * If we're still before the sample window, we're done. - */ - if (time_before(jiffies, this_rq->calc_load_update)) - return; - - /* - * We woke inside or after the sample window, this means we're already - * accounted through the nohz accounting, so skip the entire deal and - * sync up for the next window. - */ - this_rq->calc_load_update = calc_load_update; - if (time_before(jiffies, this_rq->calc_load_update + 10)) - this_rq->calc_load_update += LOAD_FREQ; + if (delta) + atomic_long_add(delta, &calc_load_tasks_idle); } static long calc_load_fold_idle(void) { - int idx = calc_load_read_idx(); long delta = 0; - if (atomic_long_read(&calc_load_idle[idx])) - delta = atomic_long_xchg(&calc_load_idle[idx], 0); + /* + * Its got a race, we don't care... + */ + if (atomic_long_read(&calc_load_tasks_idle)) + delta = atomic_long_xchg(&calc_load_tasks_idle, 0); return delta; } @@ -2454,39 +2302,66 @@ static void calc_global_nohz(void) { long delta, active, n; - if (!time_before(jiffies, calc_load_update + 10)) { - /* - * Catch-up, fold however many we are behind still - */ - delta = jiffies - calc_load_update - 10; - n = 1 + (delta / LOAD_FREQ); - - active = atomic_long_read(&calc_load_tasks); - active = active > 0 ? active * FIXED_1 : 0; - - avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n); - avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n); - avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n); + /* + * If we crossed a calc_load_update boundary, make sure to fold + * any pending idle changes, the respective CPUs might have + * missed the tick driven calc_load_account_active() update + * due to NO_HZ. + */ + delta = calc_load_fold_idle(); + if (delta) + atomic_long_add(delta, &calc_load_tasks); - calc_load_update += n * LOAD_FREQ; - } + /* + * It could be the one fold was all it took, we done! + */ + if (time_before(jiffies, calc_load_update + 10)) + return; /* - * Flip the idle index... - * - * Make sure we first write the new time then flip the index, so that - * calc_load_write_idx() will see the new time when it reads the new - * index, this avoids a double flip messing things up. + * Catch-up, fold however many we are behind still */ - smp_wmb(); - calc_load_idx++; + delta = jiffies - calc_load_update - 10; + n = 1 + (delta / LOAD_FREQ); + + active = atomic_long_read(&calc_load_tasks); + active = active > 0 ? active * FIXED_1 : 0; + + avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n); + avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n); + avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n); + + calc_load_update += n * LOAD_FREQ; +} +#else +void calc_load_account_idle(struct rq *this_rq) +{ } -#else /* !CONFIG_NO_HZ */ -static inline long calc_load_fold_idle(void) { return 0; } -static inline void calc_global_nohz(void) { } +static inline long calc_load_fold_idle(void) +{ + return 0; +} -#endif /* CONFIG_NO_HZ */ +static void calc_global_nohz(void) +{ +} +#endif + +/** + * get_avenrun - get the load average array + * @loads: pointer to dest load array + * @offset: offset to add + * @shift: shift count to shift the result left + * + * These values are estimates at best, so no need for locking. + */ +void get_avenrun(unsigned long *loads, unsigned long offset, int shift) +{ + loads[0] = (avenrun[0] + offset) << shift; + loads[1] = (avenrun[1] + offset) << shift; + loads[2] = (avenrun[2] + offset) << shift; +} /* * calc_load - update the avenrun load estimates 10 ticks after the @@ -2494,18 +2369,11 @@ static inline void calc_global_nohz(void) { } */ void calc_global_load(unsigned long ticks) { - long active, delta; + long active; if (time_before(jiffies, calc_load_update + 10)) return; - /* - * Fold the 'old' idle-delta to include all NO_HZ cpus. - */ - delta = calc_load_fold_idle(); - if (delta) - atomic_long_add(delta, &calc_load_tasks); - active = atomic_long_read(&calc_load_tasks); active = active > 0 ? active * FIXED_1 : 0; @@ -2516,7 +2384,12 @@ void calc_global_load(unsigned long ticks) calc_load_update += LOAD_FREQ; /* - * In case we idled for multiple LOAD_FREQ intervals, catch up in bulk. + * Account one period with whatever state we found before + * folding in the nohz state and ageing the entire idle period. + * + * This avoids loosing a sample when we go idle between + * calc_load_account_active() (10 ticks ago) and now and thus + * under-accounting. */ calc_global_nohz(); } @@ -2533,16 +2406,13 @@ static void calc_load_account_active(struct rq *this_rq) return; delta = calc_load_fold_active(this_rq); + delta += calc_load_fold_idle(); if (delta) atomic_long_add(delta, &calc_load_tasks); this_rq->calc_load_update += LOAD_FREQ; } -/* - * End of global load-average stuff - */ - /* * The exact cpuload at various idx values, calculated at every tick would be * load = (2^idx - 1) / 2^idx * load + 1 / 2^idx * cur_load diff --git a/trunk/kernel/sched/idle_task.c b/trunk/kernel/sched/idle_task.c index b6baf370cae9..b44d604b35d1 100644 --- a/trunk/kernel/sched/idle_task.c +++ b/trunk/kernel/sched/idle_task.c @@ -25,6 +25,7 @@ static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int fl static struct task_struct *pick_next_task_idle(struct rq *rq) { schedstat_inc(rq, sched_goidle); + calc_load_account_idle(rq); return rq->idle; } diff --git a/trunk/kernel/sched/sched.h b/trunk/kernel/sched/sched.h index 55844f24435a..6d52cea7f33d 100644 --- a/trunk/kernel/sched/sched.h +++ b/trunk/kernel/sched/sched.h @@ -942,6 +942,8 @@ static inline u64 sched_avg_period(void) return (u64)sysctl_sched_time_avg * NSEC_PER_MSEC / 2; } +void calc_load_account_idle(struct rq *this_rq); + #ifdef CONFIG_SCHED_HRTICK /* diff --git a/trunk/kernel/time/tick-sched.c b/trunk/kernel/time/tick-sched.c index 4a08472c3ca7..869997833928 100644 --- a/trunk/kernel/time/tick-sched.c +++ b/trunk/kernel/time/tick-sched.c @@ -406,7 +406,6 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts) */ if (!ts->tick_stopped) { select_nohz_load_balancer(1); - calc_load_enter_idle(); ts->idle_tick = hrtimer_get_expires(&ts->sched_timer); ts->tick_stopped = 1; @@ -598,7 +597,6 @@ void tick_nohz_idle_exit(void) account_idle_ticks(ticks); #endif - calc_load_exit_idle(); touch_softlockup_watchdog(); /* * Cancel the scheduled timer and restore the tick diff --git a/trunk/kernel/time/timekeeping.c b/trunk/kernel/time/timekeeping.c index 269b1fe5f2ae..6f46a00a1e8a 100644 --- a/trunk/kernel/time/timekeeping.c +++ b/trunk/kernel/time/timekeeping.c @@ -70,12 +70,6 @@ struct timekeeper { /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */ struct timespec raw_time; - /* Offset clock monotonic -> clock realtime */ - ktime_t offs_real; - - /* Offset clock monotonic -> clock boottime */ - ktime_t offs_boot; - /* Seqlock for all timekeeper values */ seqlock_t lock; }; @@ -178,14 +172,6 @@ static inline s64 timekeeping_get_ns_raw(void) return clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift); } -static void update_rt_offset(void) -{ - struct timespec tmp, *wtm = &timekeeper.wall_to_monotonic; - - set_normalized_timespec(&tmp, -wtm->tv_sec, -wtm->tv_nsec); - timekeeper.offs_real = timespec_to_ktime(tmp); -} - /* must hold write on timekeeper.lock */ static void timekeeping_update(bool clearntp) { @@ -193,7 +179,6 @@ static void timekeeping_update(bool clearntp) timekeeper.ntp_error = 0; ntp_clear(); } - update_rt_offset(); update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic, timekeeper.clock, timekeeper.mult); } @@ -619,7 +604,6 @@ void __init timekeeping_init(void) } set_normalized_timespec(&timekeeper.wall_to_monotonic, -boot.tv_sec, -boot.tv_nsec); - update_rt_offset(); timekeeper.total_sleep_time.tv_sec = 0; timekeeper.total_sleep_time.tv_nsec = 0; write_sequnlock_irqrestore(&timekeeper.lock, flags); @@ -628,12 +612,6 @@ void __init timekeeping_init(void) /* time in seconds when suspend began */ static struct timespec timekeeping_suspend_time; -static void update_sleep_time(struct timespec t) -{ - timekeeper.total_sleep_time = t; - timekeeper.offs_boot = timespec_to_ktime(t); -} - /** * __timekeeping_inject_sleeptime - Internal function to add sleep interval * @delta: pointer to a timespec delta value @@ -652,7 +630,8 @@ static void __timekeeping_inject_sleeptime(struct timespec *delta) timekeeper.xtime = timespec_add(timekeeper.xtime, *delta); timekeeper.wall_to_monotonic = timespec_sub(timekeeper.wall_to_monotonic, *delta); - update_sleep_time(timespec_add(timekeeper.total_sleep_time, *delta)); + timekeeper.total_sleep_time = timespec_add( + timekeeper.total_sleep_time, *delta); } @@ -984,8 +963,6 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift) leap = second_overflow(timekeeper.xtime.tv_sec); timekeeper.xtime.tv_sec += leap; timekeeper.wall_to_monotonic.tv_sec -= leap; - if (leap) - clock_was_set_delayed(); } /* Accumulate raw time */ @@ -1102,8 +1079,6 @@ static void update_wall_time(void) leap = second_overflow(timekeeper.xtime.tv_sec); timekeeper.xtime.tv_sec += leap; timekeeper.wall_to_monotonic.tv_sec -= leap; - if (leap) - clock_was_set_delayed(); } timekeeping_update(false); @@ -1271,40 +1246,6 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim, } while (read_seqretry(&timekeeper.lock, seq)); } -#ifdef CONFIG_HIGH_RES_TIMERS -/** - * ktime_get_update_offsets - hrtimer helper - * @offs_real: pointer to storage for monotonic -> realtime offset - * @offs_boot: pointer to storage for monotonic -> boottime offset - * - * Returns current monotonic time and updates the offsets - * Called from hrtimer_interupt() or retrigger_next_event() - */ -ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot) -{ - ktime_t now; - unsigned int seq; - u64 secs, nsecs; - - do { - seq = read_seqbegin(&timekeeper.lock); - - secs = timekeeper.xtime.tv_sec; - nsecs = timekeeper.xtime.tv_nsec; - nsecs += timekeeping_get_ns(); - /* If arch requires, add in gettimeoffset() */ - nsecs += arch_gettimeoffset(); - - *offs_real = timekeeper.offs_real; - *offs_boot = timekeeper.offs_boot; - } while (read_seqretry(&timekeeper.lock, seq)); - - now = ktime_add_ns(ktime_set(secs, 0), nsecs); - now = ktime_sub(now, *offs_real); - return now; -} -#endif - /** * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format */ diff --git a/trunk/kernel/trace/ring_buffer.c b/trunk/kernel/trace/ring_buffer.c index f765465bffe4..1d0f6a8a0e5e 100644 --- a/trunk/kernel/trace/ring_buffer.c +++ b/trunk/kernel/trace/ring_buffer.c @@ -1075,7 +1075,6 @@ rb_allocate_cpu_buffer(struct ring_buffer *buffer, int nr_pages, int cpu) rb_init_page(bpage->page); INIT_LIST_HEAD(&cpu_buffer->reader_page->list); - INIT_LIST_HEAD(&cpu_buffer->new_pages); ret = rb_allocate_pages(cpu_buffer, nr_pages); if (ret < 0) @@ -1347,9 +1346,10 @@ rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned int nr_pages) * If something was added to this page, it was full * since it is not the tail page. So we deduct the * bytes consumed in ring buffer from here. - * Increment overrun to account for the lost events. + * No need to update overruns, since this page is + * deleted from ring buffer and its entries are + * already accounted for. */ - local_add(page_entries, &cpu_buffer->overrun); local_sub(BUF_PAGE_SIZE, &cpu_buffer->entries_bytes); } diff --git a/trunk/sound/usb/endpoint.c b/trunk/sound/usb/endpoint.c index 0f647d22cb4a..e6906901debb 100644 --- a/trunk/sound/usb/endpoint.c +++ b/trunk/sound/usb/endpoint.c @@ -414,7 +414,7 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, { struct list_head *p; struct snd_usb_endpoint *ep; - int is_playback = direction == SNDRV_PCM_STREAM_PLAYBACK; + int ret, is_playback = direction == SNDRV_PCM_STREAM_PLAYBACK; mutex_lock(&chip->mutex); @@ -434,6 +434,16 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, type == SND_USB_ENDPOINT_TYPE_DATA ? "data" : "sync", ep_num); + /* select the alt setting once so the endpoints become valid */ + ret = usb_set_interface(chip->dev, alts->desc.bInterfaceNumber, + alts->desc.bAlternateSetting); + if (ret < 0) { + snd_printk(KERN_ERR "%s(): usb_set_interface() failed, ret = %d\n", + __func__, ret); + ep = NULL; + goto __exit_unlock; + } + ep = kzalloc(sizeof(*ep), GFP_KERNEL); if (!ep) goto __exit_unlock; @@ -821,6 +831,9 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) if (++ep->use_count != 1) return 0; + if (snd_BUG_ON(!test_bit(EP_FLAG_ACTIVATED, &ep->flags))) + return -EINVAL; + /* just to be sure */ deactivate_urbs(ep, 0, 1); wait_clear_urbs(ep); @@ -898,6 +911,9 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, if (snd_BUG_ON(ep->use_count == 0)) return; + if (snd_BUG_ON(!test_bit(EP_FLAG_ACTIVATED, &ep->flags))) + return; + if (--ep->use_count == 0) { deactivate_urbs(ep, force, can_sleep); ep->data_subs = NULL; @@ -910,6 +926,42 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, } } +/** + * snd_usb_endpoint_activate: activate an snd_usb_endpoint + * + * @ep: the endpoint to activate + * + * If the endpoint is not currently in use, this functions will select the + * correct alternate interface setting for the interface of this endpoint. + * + * In case of any active users, this functions does nothing. + * + * Returns an error if usb_set_interface() failed, 0 in all other + * cases. + */ +int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep) +{ + if (ep->use_count != 0) + return 0; + + if (!ep->chip->shutdown && + !test_and_set_bit(EP_FLAG_ACTIVATED, &ep->flags)) { + int ret; + + ret = usb_set_interface(ep->chip->dev, ep->iface, ep->alt_idx); + if (ret < 0) { + snd_printk(KERN_ERR "%s() usb_set_interface() failed, ret = %d\n", + __func__, ret); + clear_bit(EP_FLAG_ACTIVATED, &ep->flags); + return ret; + } + + return 0; + } + + return -EBUSY; +} + /** * snd_usb_endpoint_deactivate: deactivate an snd_usb_endpoint * @@ -928,15 +980,24 @@ int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep) if (!ep) return -EINVAL; - deactivate_urbs(ep, 1, 1); - wait_clear_urbs(ep); - if (ep->use_count != 0) return 0; - clear_bit(EP_FLAG_ACTIVATED, &ep->flags); + if (!ep->chip->shutdown && + test_and_clear_bit(EP_FLAG_ACTIVATED, &ep->flags)) { + int ret; - return 0; + ret = usb_set_interface(ep->chip->dev, ep->iface, 0); + if (ret < 0) { + snd_printk(KERN_ERR "%s(): usb_set_interface() failed, ret = %d\n", + __func__, ret); + return ret; + } + + return 0; + } + + return -EBUSY; } /** diff --git a/trunk/sound/usb/pcm.c b/trunk/sound/usb/pcm.c index a1298f379428..54607f8c4f66 100644 --- a/trunk/sound/usb/pcm.c +++ b/trunk/sound/usb/pcm.c @@ -261,6 +261,19 @@ static void stop_endpoints(struct snd_usb_substream *subs, force, can_sleep, wait); } +static int activate_endpoints(struct snd_usb_substream *subs) +{ + if (subs->sync_endpoint) { + int ret; + + ret = snd_usb_endpoint_activate(subs->sync_endpoint); + if (ret < 0) + return ret; + } + + return snd_usb_endpoint_activate(subs->data_endpoint); +} + static int deactivate_endpoints(struct snd_usb_substream *subs) { int reta, retb; @@ -301,33 +314,6 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) if (fmt == subs->cur_audiofmt) return 0; - /* close the old interface */ - if (subs->interface >= 0 && subs->interface != fmt->iface) { - err = usb_set_interface(subs->dev, subs->interface, 0); - if (err < 0) { - snd_printk(KERN_ERR "%d:%d:%d: return to setting 0 failed (%d)\n", - dev->devnum, fmt->iface, fmt->altsetting, err); - return -EIO; - } - subs->interface = -1; - subs->altset_idx = 0; - } - - /* set interface */ - if (subs->interface != fmt->iface || - subs->altset_idx != fmt->altset_idx) { - err = usb_set_interface(dev, fmt->iface, fmt->altsetting); - if (err < 0) { - snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed (%d)\n", - dev->devnum, fmt->iface, fmt->altsetting, err); - return -EIO; - } - snd_printdd(KERN_INFO "setting usb interface %d:%d\n", - fmt->iface, fmt->altsetting); - subs->interface = fmt->iface; - subs->altset_idx = fmt->altset_idx; - } - subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip, alts, fmt->endpoint, subs->direction, SND_USB_ENDPOINT_TYPE_DATA); @@ -401,7 +387,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) subs->data_endpoint->sync_master = subs->sync_endpoint; } - if ((err = snd_usb_init_pitch(subs->stream->chip, fmt->iface, alts, fmt)) < 0) + if ((err = snd_usb_init_pitch(subs->stream->chip, subs->interface, alts, fmt)) < 0) return err; subs->cur_audiofmt = fmt; @@ -464,7 +450,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, struct usb_interface *iface; iface = usb_ifnum_to_if(subs->dev, fmt->iface); alts = &iface->altsetting[fmt->altset_idx]; - ret = snd_usb_init_sample_rate(subs->stream->chip, fmt->iface, alts, fmt, rate); + ret = snd_usb_init_sample_rate(subs->stream->chip, subs->interface, alts, fmt, rate); if (ret < 0) return ret; subs->cur_rate = rate; @@ -474,6 +460,12 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, mutex_lock(&subs->stream->chip->shutdown_mutex); /* format changed */ stop_endpoints(subs, 0, 0, 0); + deactivate_endpoints(subs); + + ret = activate_endpoints(subs); + if (ret < 0) + goto unlock; + ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt, subs->sync_endpoint); if (ret < 0) @@ -508,7 +500,6 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) subs->period_bytes = 0; mutex_lock(&subs->stream->chip->shutdown_mutex); stop_endpoints(subs, 0, 1, 1); - deactivate_endpoints(subs); mutex_unlock(&subs->stream->chip->shutdown_mutex); return snd_pcm_lib_free_vmalloc_buffer(substream); } @@ -947,20 +938,16 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) { + int ret; struct snd_usb_stream *as = snd_pcm_substream_chip(substream); struct snd_usb_substream *subs = &as->substream[direction]; stop_endpoints(subs, 0, 0, 0); - - if (!as->chip->shutdown && subs->interface >= 0) { - usb_set_interface(subs->dev, subs->interface, 0); - subs->interface = -1; - } - + ret = deactivate_endpoints(subs); subs->pcm_substream = NULL; snd_usb_autosuspend(subs->stream->chip); - return 0; + return ret; } /* Since a URB can handle only a single linear buffer, we must use double diff --git a/trunk/tools/perf/util/map.c b/trunk/tools/perf/util/map.c index a1f4e3669142..35ae56864e4f 100644 --- a/trunk/tools/perf/util/map.c +++ b/trunk/tools/perf/util/map.c @@ -669,26 +669,25 @@ struct machine *machines__find(struct rb_root *self, pid_t pid) struct machine *machines__findnew(struct rb_root *self, pid_t pid) { char path[PATH_MAX]; - const char *root_dir = ""; + const char *root_dir; struct machine *machine = machines__find(self, pid); - if (machine && (machine->pid == pid)) - goto out; - - if ((pid != HOST_KERNEL_ID) && - (pid != DEFAULT_GUEST_KERNEL_ID) && - (symbol_conf.guestmount)) { - sprintf(path, "%s/%d", symbol_conf.guestmount, pid); - if (access(path, R_OK)) { - pr_err("Can't access file %s\n", path); - machine = NULL; - goto out; + if (!machine || machine->pid != pid) { + if (pid == HOST_KERNEL_ID || pid == DEFAULT_GUEST_KERNEL_ID) + root_dir = ""; + else { + if (!symbol_conf.guestmount) + goto out; + sprintf(path, "%s/%d", symbol_conf.guestmount, pid); + if (access(path, R_OK)) { + pr_err("Can't access file %s\n", path); + goto out; + } + root_dir = path; } - root_dir = path; + machine = machines__add(self, pid, root_dir); } - machine = machines__add(self, pid, root_dir); - out: return machine; } diff --git a/trunk/tools/perf/util/session.c b/trunk/tools/perf/util/session.c index 56142d0fb8d7..c3e399bcf18d 100644 --- a/trunk/tools/perf/util/session.c +++ b/trunk/tools/perf/util/session.c @@ -926,7 +926,7 @@ static struct machine * else pid = event->ip.pid; - return perf_session__findnew_machine(session, pid); + return perf_session__find_machine(session, pid); } return perf_session__find_host_machine(session); diff --git a/trunk/tools/perf/util/trace-event-parse.c b/trunk/tools/perf/util/trace-event-parse.c index 5dd3b5ec8411..df2fddbf0cd2 100644 --- a/trunk/tools/perf/util/trace-event-parse.c +++ b/trunk/tools/perf/util/trace-event-parse.c @@ -198,8 +198,9 @@ void print_trace_event(int cpu, void *data, int size) record.data = data; trace_seq_init(&s); - pevent_event_info(&s, event, &record); + pevent_print_event(pevent, &s, &record); trace_seq_do_printf(&s); + printf("\n"); } void print_event(int cpu, void *data, int size, unsigned long long nsecs,