diff options
author | Dave Airlie <airlied@redhat.com> | 2011-03-14 14:15:13 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2011-03-14 14:15:13 +1000 |
commit | 34db18abd376b2075c760c38f0b861aed379415d (patch) | |
tree | c4174e39a2f445f17c25ab206d45c66217bbbf85 /drivers/gpu | |
parent | e73f88af66fcc50083fae4b7e1c39b469179a97a (diff) | |
parent | 47ae63e0c2e5fdb582d471dc906eb29be94c732f (diff) |
Merge remote branch 'intel/drm-intel-next' of ../drm-next into drm-core-next
* 'intel/drm-intel-next' of ../drm-next: (755 commits)
drm/i915: Only wait on a pending flip if we intend to write to the buffer
drm/i915/dp: Sanity check eDP existence
drm/i915: Rebind the buffer if its alignment constraints changes with tiling
drm/i915: Disable GPU semaphores by default
drm/i915: Do not overflow the MMADDR write FIFO
Revert "drm/i915: fix corruptions on i8xx due to relaxed fencing"
drm/i915: Don't save/restore hardware status page address register
drm/i915: don't store the reg value for HWS_PGA
drm/i915: fix memory corruption with GM965 and >4GB RAM
Linux 2.6.38-rc7
Revert "TPM: Long default timeout fix"
drm/i915: Re-enable GPU semaphores for SandyBridge mobile
drm/i915: Replace vblank PM QoS with "Interrupt-Based AGPBUSY#"
Revert "drm/i915: Use PM QoS to prevent C-State starvation of gen3 GPU"
drm/i915: Allow relocation deltas outside of target bo
drm/i915: Silence an innocuous compiler warning for an unused variable
fs/block_dev.c: fix new kernel-doc warning
ACPI: Fix build for CONFIG_NET unset
mm: <asm-generic/pgtable.h> must include <linux/mm_types.h>
x86: Use u32 instead of long to set reset vector back to 0
...
Conflicts:
drivers/gpu/drm/i915/i915_gem.c
Diffstat (limited to 'drivers/gpu')
67 files changed, 3481 insertions, 2234 deletions
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index 812aaac4438..ab1162da70f 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c @@ -272,17 +272,18 @@ int drm_vma_info(struct seq_file *m, void *data) #endif mutex_lock(&dev->struct_mutex); - seq_printf(m, "vma use count: %d, high_memory = %p, 0x%08llx\n", + seq_printf(m, "vma use count: %d, high_memory = %pK, 0x%pK\n", atomic_read(&dev->vma_count), - high_memory, (u64)virt_to_phys(high_memory)); + high_memory, (void *)virt_to_phys(high_memory)); list_for_each_entry(pt, &dev->vmalist, head) { vma = pt->vma; if (!vma) continue; seq_printf(m, - "\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000", - pt->pid, vma->vm_start, vma->vm_end, + "\n%5d 0x%pK-0x%pK %c%c%c%c%c%c 0x%08lx000", + pt->pid, + (void *)vma->vm_start, (void *)vma->vm_end, vma->vm_flags & VM_READ ? 'r' : '-', vma->vm_flags & VM_WRITE ? 'w' : '-', vma->vm_flags & VM_EXEC ? 'x' : '-', diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index cb49685bde0..a34ef97d3c8 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -154,8 +154,10 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) * available. In that case we can't account for this and just * hope for the best. */ - if ((vblrc > 0) && (abs(diff_ns) > 1000000)) + if ((vblrc > 0) && (abs64(diff_ns) > 1000000)) { atomic_inc(&dev->_vblank_count[crtc]); + smp_mb__after_atomic_inc(); + } /* Invalidate all timestamps while vblank irq's are off. */ clear_vblank_timestamps(dev, crtc); @@ -481,6 +483,12 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc) /* Dot clock in Hz: */ dotclock = (u64) crtc->hwmode.clock * 1000; + /* Fields of interlaced scanout modes are only halve a frame duration. + * Double the dotclock to get halve the frame-/line-/pixelduration. + */ + if (crtc->hwmode.flags & DRM_MODE_FLAG_INTERLACE) + dotclock *= 2; + /* Valid dotclock? */ if (dotclock > 0) { /* Convert scanline length in pixels and video dot clock to @@ -593,14 +601,6 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, return -EAGAIN; } - /* Don't know yet how to handle interlaced or - * double scan modes. Just no-op for now. - */ - if (mode->flags & (DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLSCAN)) { - DRM_DEBUG("crtc %d: Noop due to unsupported mode.\n", crtc); - return -ENOTSUPP; - } - /* Get current scanout position with system timestamp. * Repeat query up to DRM_TIMESTAMP_MAXRETRIES times * if single query takes longer than max_error nanoseconds. @@ -848,10 +848,11 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc) if (rc) { tslot = atomic_read(&dev->_vblank_count[crtc]) + diff; vblanktimestamp(dev, crtc, tslot) = t_vblank; - smp_wmb(); } + smp_mb__before_atomic_inc(); atomic_add(diff, &dev->_vblank_count[crtc]); + smp_mb__after_atomic_inc(); } /** @@ -1001,7 +1002,8 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_modeset_ctl *modeset = data; - int crtc, ret = 0; + int ret = 0; + unsigned int crtc; /* If drm_vblank_init() hasn't been called yet, just no-op */ if (!dev->num_crtcs) @@ -1283,15 +1285,16 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) * e.g., due to spurious vblank interrupts. We need to * ignore those for accounting. */ - if (abs(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS) { + if (abs64(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS) { /* Store new timestamp in ringbuffer. */ vblanktimestamp(dev, crtc, vblcount + 1) = tvblank; - smp_wmb(); /* Increment cooked vblank count. This also atomically commits * the timestamp computed above. */ + smp_mb__before_atomic_inc(); atomic_inc(&dev->_vblank_count[crtc]); + smp_mb__after_atomic_inc(); } else { DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n", crtc, (int) diff_ns); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3601466c550..09e0327fc6c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -326,21 +326,21 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data) struct intel_crtc *crtc; list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { - const char *pipe = crtc->pipe ? "B" : "A"; - const char *plane = crtc->plane ? "B" : "A"; + const char pipe = pipe_name(crtc->pipe); + const char plane = plane_name(crtc->plane); struct intel_unpin_work *work; spin_lock_irqsave(&dev->event_lock, flags); work = crtc->unpin_work; if (work == NULL) { - seq_printf(m, "No flip due on pipe %s (plane %s)\n", + seq_printf(m, "No flip due on pipe %c (plane %c)\n", pipe, plane); } else { if (!work->pending) { - seq_printf(m, "Flip queued on pipe %s (plane %s)\n", + seq_printf(m, "Flip queued on pipe %c (plane %c)\n", pipe, plane); } else { - seq_printf(m, "Flip pending (waiting for vsync) on pipe %s (plane %s)\n", + seq_printf(m, "Flip pending (waiting for vsync) on pipe %c (plane %c)\n", pipe, plane); } if (work->enable_stall_check) @@ -458,7 +458,7 @@ static int i915_interrupt_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; drm_i915_private_t *dev_priv = dev->dev_private; - int ret, i; + int ret, i, pipe; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) @@ -471,10 +471,10 @@ static int i915_interrupt_info(struct seq_file *m, void *data) I915_READ(IIR)); seq_printf(m, "Interrupt mask: %08x\n", I915_READ(IMR)); - seq_printf(m, "Pipe A stat: %08x\n", - I915_READ(PIPEASTAT)); - seq_printf(m, "Pipe B stat: %08x\n", - I915_READ(PIPEBSTAT)); + for_each_pipe(pipe) + seq_printf(m, "Pipe %c stat: %08x\n", + pipe_name(pipe), + I915_READ(PIPESTAT(pipe))); } else { seq_printf(m, "North Display Interrupt enable: %08x\n", I915_READ(DEIER)); @@ -544,11 +544,11 @@ static int i915_hws_info(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; struct intel_ring_buffer *ring; - volatile u32 *hws; + const volatile u32 __iomem *hws; int i; ring = &dev_priv->ring[(uintptr_t)node->info_ent->data]; - hws = (volatile u32 *)ring->status_page.page_addr; + hws = (volatile u32 __iomem *)ring->status_page.page_addr; if (hws == NULL) return 0; @@ -615,7 +615,7 @@ static int i915_ringbuffer_data(struct seq_file *m, void *data) if (!ring->obj) { seq_printf(m, "No ringbuffer setup\n"); } else { - u8 *virt = ring->virtual_start; + const u8 __iomem *virt = ring->virtual_start; uint32_t off; for (off = 0; off < ring->size; off += 4) { @@ -805,15 +805,20 @@ static int i915_error_state(struct seq_file *m, void *unused) } } - if (error->ringbuffer) { - struct drm_i915_error_object *obj = error->ringbuffer; - - seq_printf(m, "--- ringbuffer = 0x%08x\n", obj->gtt_offset); - offset = 0; - for (page = 0; page < obj->page_count; page++) { - for (elt = 0; elt < PAGE_SIZE/4; elt++) { - seq_printf(m, "%08x : %08x\n", offset, obj->pages[page][elt]); - offset += 4; + for (i = 0; i < ARRAY_SIZE(error->ringbuffer); i++) { + if (error->ringbuffer[i]) { + struct drm_i915_error_object *obj = error->ringbuffer[i]; + seq_printf(m, "%s --- ringbuffer = 0x%08x\n", + dev_priv->ring[i].name, + obj->gtt_offset); + offset = 0; + for (page = 0; page < obj->page_count; page++) { + for (elt = 0; elt < PAGE_SIZE/4; elt++) { + seq_printf(m, "%08x : %08x\n", + offset, + obj->pages[page][elt]); + offset += 4; + } } } } @@ -862,19 +867,44 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS); u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); + u32 rpstat; + u32 rpupei, rpcurup, rpprevup; + u32 rpdownei, rpcurdown, rpprevdown; int max_freq; /* RPSTAT1 is in the GT power well */ - __gen6_force_wake_get(dev_priv); + __gen6_gt_force_wake_get(dev_priv); + + rpstat = I915_READ(GEN6_RPSTAT1); + rpupei = I915_READ(GEN6_RP_CUR_UP_EI); + rpcurup = I915_READ(GEN6_RP_CUR_UP); + rpprevup = I915_READ(GEN6_RP_PREV_UP); + rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI); + rpcurdown = I915_READ(GEN6_RP_CUR_DOWN); + rpprevdown = I915_READ(GEN6_RP_PREV_DOWN); seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status); - seq_printf(m, "RPSTAT1: 0x%08x\n", I915_READ(GEN6_RPSTAT1)); + seq_printf(m, "RPSTAT1: 0x%08x\n", rpstat); seq_printf(m, "Render p-state ratio: %d\n", (gt_perf_status & 0xff00) >> 8); seq_printf(m, "Render p-state VID: %d\n", gt_perf_status & 0xff); seq_printf(m, "Render p-state limit: %d\n", rp_state_limits & 0xff); + seq_printf(m, "CAGF: %dMHz\n", ((rpstat & GEN6_CAGF_MASK) >> + GEN6_CAGF_SHIFT) * 100); + seq_printf(m, "RP CUR UP EI: %dus\n", rpupei & + GEN6_CURICONT_MASK); + seq_printf(m, "RP CUR UP: %dus\n", rpcurup & + GEN6_CURBSYTAVG_MASK); + seq_printf(m, "RP PREV UP: %dus\n", rpprevup & + GEN6_CURBSYTAVG_MASK); + seq_printf(m, "RP CUR DOWN EI: %dus\n", rpdownei & + GEN6_CURIAVG_MASK); + seq_printf(m, "RP CUR DOWN: %dus\n", rpcurdown & + GEN6_CURBSYTAVG_MASK); + seq_printf(m, "RP PREV DOWN: %dus\n", rpprevdown & + GEN6_CURBSYTAVG_MASK); max_freq = (rp_state_cap & 0xff0000) >> 16; seq_printf(m, "Lowest (RPN) frequency: %dMHz\n", @@ -888,7 +918,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n", max_freq * 100); - __gen6_force_wake_put(dev_priv); + __gen6_gt_force_wake_put(dev_priv); } else { seq_printf(m, "no P-state info available\n"); } @@ -1259,7 +1289,7 @@ static int i915_wedged_create(struct dentry *root, struct drm_minor *minor) } static struct drm_info_list i915_debugfs_list[] = { - {"i915_capabilities", i915_capabilities, 0, 0}, + {"i915_capabilities", i915_capabilities, 0}, {"i915_gem_objects", i915_gem_object_info, 0}, {"i915_gem_gtt", i915_gem_gtt_info, 0}, {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST}, diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 17bd766f208..72730377a01 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -43,6 +43,17 @@ #include <linux/slab.h> #include <acpi/video.h> +static void i915_write_hws_pga(struct drm_device *dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + u32 addr; + + addr = dev_priv->status_page_dmah->busaddr; + if (INTEL_INFO(dev)->gen >= 4) + addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; + I915_WRITE(HWS_PGA, addr); +} + /** * Sets up the hardware status page for devices that need a physical address * in the register. @@ -60,16 +71,13 @@ static int i915_init_phys_hws(struct drm_device *dev) DRM_ERROR("Can not allocate hardware status page\n"); return -ENOMEM; } - ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; - dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; + ring->status_page.page_addr = + (void __force __iomem *)dev_priv->status_page_dmah->vaddr; - memset(ring->status_page.page_addr, 0, PAGE_SIZE); + memset_io(ring->status_page.page_addr, 0, PAGE_SIZE); - if (INTEL_INFO(dev)->gen >= 4) - dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) & - 0xf0; + i915_write_hws_pga(dev); - I915_WRITE(HWS_PGA, dev_priv->dma_status_page); DRM_DEBUG_DRIVER("Enabled hardware status page\n"); return 0; } @@ -216,7 +224,7 @@ static int i915_dma_resume(struct drm_device * dev) if (ring->status_page.gfx_addr != 0) intel_ring_setup_status_page(ring); else - I915_WRITE(HWS_PGA, dev_priv->dma_status_page); + i915_write_hws_pga(dev); DRM_DEBUG_DRIVER("Enabled hardware status page\n"); @@ -771,6 +779,9 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_HAS_EXEC_CONSTANTS: value = INTEL_INFO(dev)->gen >= 4; break; + case I915_PARAM_HAS_RELAXED_DELTA: + value = 1; + break; default: DRM_DEBUG_DRIVER("Unknown parameter %d\n", param->param); @@ -859,8 +870,9 @@ static int i915_set_status_page(struct drm_device *dev, void *data, " G33 hw status page\n"); return -ENOMEM; } - ring->status_page.page_addr = dev_priv->hws_map.handle; - memset(ring->status_page.page_addr, 0, PAGE_SIZE); + ring->status_page.page_addr = + (void __force __iomem *)dev_priv->hws_map.handle; + memset_io(ring->status_page.page_addr, 0, PAGE_SIZE); I915_WRITE(HWS_PGA, ring->status_page.gfx_addr); DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n", @@ -1895,6 +1907,17 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (IS_GEN2(dev)) dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(30)); + /* 965GM sometimes incorrectly writes to hardware status page (HWS) + * using 32bit addressing, overwriting memory if HWS is located + * above 4GB. + * + * The documentation also mentions an issue with undefined + * behaviour if any general state is accessed within a page above 4GB, + * which also needs to be handled carefully. + */ + if (IS_BROADWATER(dev) || IS_CRESTLINE(dev)) + dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(32)); + mmio_bar = IS_GEN2(dev) ? 1 : 0; dev_priv->regs = pci_iomap(dev->pdev, mmio_bar, 0); if (!dev_priv->regs) { @@ -2002,9 +2025,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->error_lock); - dev_priv->trace_irq_seqno = 0; - ret = drm_vblank_init(dev, I915_NUM_PIPE); + if (IS_MOBILE(dev) || !IS_GEN2(dev)) + dev_priv->num_pipe = 2; + else + dev_priv->num_pipe = 1; + + ret = drm_vblank_init(dev, dev_priv->num_pipe); if (ret) goto out_gem_unload; diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 9ad42d58349..c34a8dd31d0 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -43,16 +43,28 @@ module_param_named(modeset, i915_modeset, int, 0400); unsigned int i915_fbpercrtc = 0; module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400); +int i915_panel_ignore_lid = 0; +module_param_named(panel_ignore_lid, i915_panel_ignore_lid, int, 0600); + unsigned int i915_powersave = 1; module_param_named(powersave, i915_powersave, int, 0600); +unsigned int i915_semaphores = 1; +module_param_named(semaphores, i915_semaphores, int, 0600); + +unsigned int i915_enable_rc6 = 0; +module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600); + unsigned int i915_lvds_downclock = 0; module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400); unsigned int i915_panel_use_ssc = 1; module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600); -bool i915_try_reset = true; +int i915_vbt_sdvo_panel_type = -1; +module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600); + +static bool i915_try_reset = true; module_param_named(reset, i915_try_reset, bool, 0600); static struct drm_driver driver; @@ -251,7 +263,7 @@ void intel_detect_pch (struct drm_device *dev) } } -void __gen6_force_wake_get(struct drm_i915_private *dev_priv) +void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) { int count; @@ -267,12 +279,22 @@ void __gen6_force_wake_get(struct drm_i915_private *dev_priv) udelay(10); } -void __gen6_force_wake_put(struct drm_i915_private *dev_priv) +void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE, 0); POSTING_READ(FORCEWAKE); } +void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) +{ + int loop = 500; + u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); + while (fifo < 20 && loop--) { + udelay(10); + fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); + } +} + static int i915_drm_freeze(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -360,7 +382,7 @@ static int i915_drm_thaw(struct drm_device *dev) /* Resume the modeset for every activated CRTC */ drm_helper_resume_force_mode(dev); |