Skip to content

Commit

Permalink
Merge tag 'drm-intel-fixes-2013-07-03' of git://people.freedesktop.or…
Browse files Browse the repository at this point in the history
…g/~danvet/drm-intel into drm-next

Pile of fixes for 3.11. A bit large in patch count, but that's simply due
to two fixes being split up into really small parts. Also I've included a
few more vlv patches than I'd have included for other platforms. But since
vlv is officially supported for the first time only in 3.11 that shouldn't
result in unbearable risks.

Highlights:
- ghost eDP fixes for hsw from Paulo
- fix PCH detection in virtualized enviroments (Rui Guo)
- duct-tape dma sg construction when swiotlb is in use (Konrad), dupe with
  a patch in your drm-fixes branch
- fix sdvo hotplug on i965g
- tune down a bunch of dmesg ERRORs which can be hit under normal
  conditions
- detect invalid pitches for tiled scanout buffers (Chris)
- a pile of vlv fixes from Ville: rps improvements, fixes for the dpll
  LPF, fixup the sprite mmio offsets
- fix context size on hsw (Ben)
- locking fixes for the hotplug code, specifically the storm handling
- fix get_config on CPT (Xiong Zhang)
- Fix the domain tracking when an unlocked seqno wait was interrupt
  (Chris), this seems to explain tons of little corruption bugs in the
  ddx. Chris also added a nice igt to exercise this.
- work around stack-corrupting vnsprintf in our error state dumper

* tag 'drm-intel-fixes-2013-07-03' of git://people.freedesktop.org/~danvet/drm-intel: (39 commits)
  drm/i915: Don't try to tear down the stolen drm_mm if it's not there
  drm/i915: Break up the large vsnprintf() in print_error_buffers()
  drm/i915: Refactor the wait_rendering completion into a common routine
  drm/i915: Only clear write-domains after a successful wait-seqno
  drm/i915: correct intel_dp_get_config() function for DevCPT
  drm/i915: fix hpd interrupt register locking
  drm/i915: fold the no-irq check into intel_hpd_irq_handler
  drm/i915: fold the queue_work into intel_hpd_irq_handler
  drm/i915: fold the hpd_irq_setup call into intel_hpd_irq_handler
  drm/i915: s/hotplug_irq_storm_detect/intel_hpd_irq_handler/
  drm/i915: close tiny race in the ilk pcu even interrupt setup
  drm/i915: fix locking around ironlake_enable|disable_display_irq
  drm/i915: Fix context sizes on HSW
  drm/i915: Fix VLV sprite register offsets
  Revert "drm/i915: Don't use the HDMI port color range bit on Valleyview"
  drm/i915: s/LFP/LPF in DPIO PLL register names
  drm/i915: Fix VLV PLL LPF coefficients for DAC
  drm/i915: Jump to at least RPe on VLV when increasing the GPU frequency
  drm/i915: Don't increase the GPU frequency from the delayed VLV rps timer
  drm/i915: GEN6_RP_INTERRUPT_LIMITS doesn't seem to exist on VLV
  ...
  • Loading branch information
airlied committed Jul 4, 2013
2 parents 1586ba7 + 446f8d8 commit d0aaa28
Show file tree
Hide file tree
Showing 15 changed files with 498 additions and 322 deletions.
119 changes: 84 additions & 35 deletions drivers/gpu/drm/i915/i915_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -647,41 +647,44 @@ static const char *purgeable_flag(int purgeable)
return purgeable ? " purgeable" : "";
}

static void i915_error_vprintf(struct drm_i915_error_state_buf *e,
const char *f, va_list args)
static bool __i915_error_ok(struct drm_i915_error_state_buf *e)
{
unsigned len;

if (!e->err && WARN(e->bytes > (e->size - 1), "overflow")) {
e->err = -ENOSPC;
return;
return false;
}

if (e->bytes == e->size - 1 || e->err)
return;
return false;

/* Seek the first printf which is hits start position */
if (e->pos < e->start) {
len = vsnprintf(NULL, 0, f, args);
if (e->pos + len <= e->start) {
e->pos += len;
return;
}
return true;
}

/* First vsnprintf needs to fit in full for memmove*/
if (len >= e->size) {
e->err = -EIO;
return;
}
static bool __i915_error_seek(struct drm_i915_error_state_buf *e,
unsigned len)
{
if (e->pos + len <= e->start) {
e->pos += len;
return false;
}

len = vsnprintf(e->buf + e->bytes, e->size - e->bytes, f, args);
if (len >= e->size - e->bytes)
len = e->size - e->bytes - 1;
/* First vsnprintf needs to fit in its entirety for memmove */
if (len >= e->size) {
e->err = -EIO;
return false;
}

return true;
}

static void __i915_error_advance(struct drm_i915_error_state_buf *e,
unsigned len)
{
/* If this is first printf in this window, adjust it so that
* start position matches start of the buffer
*/

if (e->pos < e->start) {
const size_t off = e->start - e->pos;

Expand All @@ -701,6 +704,51 @@ static void i915_error_vprintf(struct drm_i915_error_state_buf *e,
e->pos += len;
}

static void i915_error_vprintf(struct drm_i915_error_state_buf *e,
const char *f, va_list args)
{
unsigned len;

if (!__i915_error_ok(e))
return;

/* Seek the first printf which is hits start position */
if (e->pos < e->start) {
len = vsnprintf(NULL, 0, f, args);
if (!__i915_error_seek(e, len))
return;
}

len = vsnprintf(e->buf + e->bytes, e->size - e->bytes, f, args);
if (len >= e->size - e->bytes)
len = e->size - e->bytes - 1;

__i915_error_advance(e, len);
}

static void i915_error_puts(struct drm_i915_error_state_buf *e,
const char *str)
{
unsigned len;

if (!__i915_error_ok(e))
return;

len = strlen(str);

/* Seek the first printf which is hits start position */
if (e->pos < e->start) {
if (!__i915_error_seek(e, len))
return;
}

if (len >= e->size - e->bytes)
len = e->size - e->bytes - 1;
memcpy(e->buf + e->bytes, str, len);

__i915_error_advance(e, len);
}

void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...)
{
va_list args;
Expand All @@ -711,6 +759,7 @@ void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...)
}

#define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__)
#define err_puts(e, s) i915_error_puts(e, s)

static void print_error_buffers(struct drm_i915_error_state_buf *m,
const char *name,
Expand All @@ -720,26 +769,26 @@ static void print_error_buffers(struct drm_i915_error_state_buf *m,
err_printf(m, "%s [%d]:\n", name, count);

while (count--) {
err_printf(m, " %08x %8u %02x %02x %x %x%s%s%s%s%s%s%s",
err_printf(m, " %08x %8u %02x %02x %x %x",
err->gtt_offset,
err->size,
err->read_domains,
err->write_domain,
err->rseqno, err->wseqno,
pin_flag(err->pinned),
tiling_flag(err->tiling),
dirty_flag(err->dirty),
purgeable_flag(err->purgeable),
err->ring != -1 ? " " : "",
ring_str(err->ring),
cache_level_str(err->cache_level));
err->rseqno, err->wseqno);
err_puts(m, pin_flag(err->pinned));
err_puts(m, tiling_flag(err->tiling));
err_puts(m, dirty_flag(err->dirty));
err_puts(m, purgeable_flag(err->purgeable));
err_puts(m, err->ring != -1 ? " " : "");
err_puts(m, ring_str(err->ring));
err_puts(m, cache_level_str(err->cache_level));

if (err->name)
err_printf(m, " (name: %d)", err->name);
if (err->fence_reg != I915_FENCE_REG_NONE)
err_printf(m, " (fence: %d)", err->fence_reg);

err_printf(m, "\n");
err_puts(m, "\n");
err++;
}
}
Expand Down Expand Up @@ -1483,7 +1532,7 @@ static int i915_ips_status(struct seq_file *m, void *unused)
struct drm_device *dev = node->minor->dev;
struct drm_i915_private *dev_priv = dev->dev_private;

if (!IS_ULT(dev)) {
if (!HAS_IPS(dev)) {
seq_puts(m, "not supported\n");
return 0;
}
Expand Down Expand Up @@ -1862,10 +1911,10 @@ static int i915_dpio_info(struct seq_file *m, void *data)
seq_printf(m, "DPIO_CORE_CLK_B: 0x%08x\n",
vlv_dpio_read(dev_priv, _DPIO_CORE_CLK_B));

seq_printf(m, "DPIO_LFP_COEFF_A: 0x%08x\n",
vlv_dpio_read(dev_priv, _DPIO_LFP_COEFF_A));
seq_printf(m, "DPIO_LFP_COEFF_B: 0x%08x\n",
vlv_dpio_read(dev_priv, _DPIO_LFP_COEFF_B));
seq_printf(m, "DPIO_LPF_COEFF_A: 0x%08x\n",
vlv_dpio_read(dev_priv, _DPIO_LPF_COEFF_A));
seq_printf(m, "DPIO_LPF_COEFF_B: 0x%08x\n",
vlv_dpio_read(dev_priv, _DPIO_LPF_COEFF_B));

seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n",
vlv_dpio_read(dev_priv, DPIO_FASTCLK_DISABLE));
Expand Down
18 changes: 16 additions & 2 deletions drivers/gpu/drm/i915/i915_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,9 +465,15 @@ void intel_detect_pch(struct drm_device *dev)
* make graphics device passthrough work easy for VMM, that only
* need to expose ISA bridge to let driver know the real hardware
* underneath. This is a requirement from virtualization team.
*
* In some virtualized environments (e.g. XEN), there is irrelevant
* ISA bridge in the system. To work reliably, we should scan trhough
* all the ISA bridge devices and check for the first match, instead
* of only checking the first one.
*/
pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
if (pch) {
while (pch) {
struct pci_dev *curr = pch;
if (pch->vendor == PCI_VENDOR_ID_INTEL) {
unsigned short id;
id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
Expand Down Expand Up @@ -496,10 +502,18 @@ void intel_detect_pch(struct drm_device *dev)
DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");
WARN_ON(!IS_HASWELL(dev));
WARN_ON(!IS_ULT(dev));
} else {
goto check_next;
}
pci_dev_put(pch);
break;
}
pci_dev_put(pch);
check_next:
pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, curr);
pci_dev_put(curr);
}
if (!pch)
DRM_DEBUG_KMS("No PCH found?\n");
}

bool i915_semaphore_is_enabled(struct drm_device *dev)
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1474,6 +1474,8 @@ 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_IPS(dev) (IS_ULT(dev))

#define HAS_PIPE_CONTROL(dev) (INTEL_INFO(dev)->gen >= 5)

#define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi)
Expand Down
64 changes: 36 additions & 28 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,25 @@ i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno)
interruptible, NULL);
}

static int
i915_gem_object_wait_rendering__tail(struct drm_i915_gem_object *obj,
struct intel_ring_buffer *ring)
{
i915_gem_retire_requests_ring(ring);

/* Manually manage the write flush as we may have not yet
* retired the buffer.
*
* Note that the last_write_seqno is always the earlier of
* the two (read/write) seqno, so if we haved successfully waited,
* we know we have passed the last write.
*/
obj->last_write_seqno = 0;
obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS;

return 0;
}

/**
* Ensures that all rendering to the object has completed and the object is
* safe to unbind from the GTT or access from the CPU.
Expand All @@ -1107,18 +1126,7 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
if (ret)
return ret;

i915_gem_retire_requests_ring(ring);

/* Manually manage the write flush as we may have not yet
* retired the buffer.
*/
if (obj->last_write_seqno &&
i915_seqno_passed(seqno, obj->last_write_seqno)) {
obj->last_write_seqno = 0;
obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS;
}

return 0;
return i915_gem_object_wait_rendering__tail(obj, ring);
}

/* A nonblocking variant of the above wait. This is a highly dangerous routine
Expand Down Expand Up @@ -1154,19 +1162,10 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj,
mutex_unlock(&dev->struct_mutex);
ret = __wait_seqno(ring, seqno, reset_counter, true, NULL);
mutex_lock(&dev->struct_mutex);
if (ret)
return ret;

i915_gem_retire_requests_ring(ring);

/* Manually manage the write flush as we may have not yet
* retired the buffer.
*/
if (obj->last_write_seqno &&
i915_seqno_passed(seqno, obj->last_write_seqno)) {
obj->last_write_seqno = 0;
obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS;
}

return ret;
return i915_gem_object_wait_rendering__tail(obj, ring);
}

/**
Expand Down Expand Up @@ -1802,7 +1801,14 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD;
gfp &= ~(__GFP_IO | __GFP_WAIT);
}

#ifdef CONFIG_SWIOTLB
if (swiotlb_nr_tbl()) {
st->nents++;
sg_set_page(sg, page, PAGE_SIZE, 0);
sg = sg_next(sg);
continue;
}
#endif
if (!i || page_to_pfn(page) != last_pfn + 1) {
if (i)
sg = sg_next(sg);
Expand All @@ -1813,8 +1819,10 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
}
last_pfn = page_to_pfn(page);
}

sg_mark_end(sg);
#ifdef CONFIG_SWIOTLB
if (!swiotlb_nr_tbl())
#endif
sg_mark_end(sg);
obj->pages = st;

if (i915_gem_object_needs_bit17_swizzle(obj))
Expand Down Expand Up @@ -3103,7 +3111,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
* before evicting everything in a vain attempt to find space.
*/
if (obj->base.size > gtt_max) {
DRM_ERROR("Attempting to bind an object larger than the aperture: object=%zd > %s aperture=%ld\n",
DRM_ERROR("Attempting to bind an object larger than the aperture: object=%zd > %s aperture=%zu\n",
obj->base.size,
map_and_fenceable ? "mappable" : "total",
gtt_max);
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/i915_gem_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ static int get_context_size(struct drm_device *dev)
case 7:
reg = I915_READ(GEN7_CXT_SIZE);
if (IS_HASWELL(dev))
ret = HSW_CXT_TOTAL_SIZE(reg) * 64;
ret = HSW_CXT_TOTAL_SIZE;
else
ret = GEN7_CXT_TOTAL_SIZE(reg) * 64;
break;
Expand Down
9 changes: 6 additions & 3 deletions drivers/gpu/drm/i915/i915_gem_stolen.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ int i915_gem_stolen_setup_compression(struct drm_device *dev, int size)
{
struct drm_i915_private *dev_priv = dev->dev_private;

if (dev_priv->mm.stolen_base == 0)
if (!drm_mm_initialized(&dev_priv->mm.stolen))
return -ENODEV;

if (size < dev_priv->cfb_size)
Expand Down Expand Up @@ -179,6 +179,9 @@ void i915_gem_cleanup_stolen(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;

if (!drm_mm_initialized(&dev_priv->mm.stolen))
return;

i915_gem_stolen_cleanup_compression(dev);
drm_mm_takedown(&dev_priv->mm.stolen);
}
Expand Down Expand Up @@ -300,7 +303,7 @@ i915_gem_object_create_stolen(struct drm_device *dev, u32 size)
struct drm_i915_gem_object *obj;
struct drm_mm_node *stolen;

if (dev_priv->mm.stolen_base == 0)
if (!drm_mm_initialized(&dev_priv->mm.stolen))
return NULL;

DRM_DEBUG_KMS("creating stolen object: size=%x\n", size);
Expand Down Expand Up @@ -331,7 +334,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
struct drm_i915_gem_object *obj;
struct drm_mm_node *stolen;

if (dev_priv->mm.stolen_base == 0)
if (!drm_mm_initialized(&dev_priv->mm.stolen))
return NULL;

DRM_DEBUG_KMS("creating preallocated stolen object: stolen_offset=%x, gtt_offset=%x, size=%x\n",
Expand Down
Loading

0 comments on commit d0aaa28

Please sign in to comment.