Skip to content

Commit

Permalink
Merge branch 'drm-intel-fixes' of git://people.freedesktop.org/~danve…
Browse files Browse the repository at this point in the history
…t/drm-intel into drm-next

Daniel writes:
A few leftover fixes for 3.8:
- VIC support for hdmi infoframes with the associated drm helper, fixes
  some black TVs (Paulo Zanoni)
- Modeset state check (and fixup if the BIOS messed with the hw) for
  lid-open. modeset-rework fallout. Somehow the original reporter went
  awol, so this stalled for way too long until we've found a new
  victim^Wreporter with broken BIOS.
- seqno wrap fixes from Mika and Chris.
- Some minor fixes all over from various people.
- Another race fix in the pageflip vs. unpin code from Chris.
- hsw vga resume support and a few more fdi link fixes (only used for vga
  on hsw) from Paulo.
- Regression fix for DMAR from Zhenyu Wang - I've scavenged memory from my
  DMAR for a while and it broke right away :(
- Regression fix from Takashi Iwai for ivb lvds - some w/a needs to be
  (partially) moved back into place. Note that these are regressions in
  -next.
- One more fix for ivb 3 pipe support - it now actually seems to work.

* 'drm-intel-fixes' of git://people.freedesktop.org/~danvet/drm-intel: (25 commits)
  drm/i915: Fix missed needs_dmar setting
  drm/i915: Fix shifted screen on top of LVDS on IVY laptop
  drm/i915: disable cpt phase pointer fdi rx workaround
  drm/i915: set the LPT FDI RX polarity reversal bit when needed
  drm/i915: add lpt_init_pch_refclk
  drm/i915: add support for mPHY destination on intel_sbi_{read, write}
  drm/i915: reject modes the LPT FDI receiver can't handle
  drm/i915: fix hsw_fdi_link_train "retry" code
  drm/i915: Close race between processing unpin task and queueing the flip
  drm/i915: fixup l3 parity sysfs access check
  drm/i915: Clear the existing watermarks for g4x when modifying the cursor sr
  drm/i915: do not access BLC_PWM_CTL2 on pre-gen4 hardware
  drm/i915: Don't allow ring tail to reach the same cacheline as head
  drm/i915: Decouple the object from the unbound list before freeing pages
  drm/i915: Set sync_seqno properly after seqno wrap
  drm/i915: Include the last semaphore sync point in the error-state
  drm/i915: Rearrange code to only have a single method for waiting upon the ring
  drm/i915: Simplify flushing activity on the ring
  drm/i915: Preallocate next seqno before touching the ring
  drm/i915: force restore on lid open
  ...
  • Loading branch information
airlied committed Dec 16, 2012
2 parents 2f3f240 + 2065209 commit 55bde6b
Show file tree
Hide file tree
Showing 24 changed files with 591 additions and 280 deletions.
19 changes: 19 additions & 0 deletions drivers/gpu/drm/drm_edid.c
Original file line number Diff line number Diff line change
Expand Up @@ -2079,3 +2079,22 @@ int drm_add_modes_noedid(struct drm_connector *connector,
return num_modes;
}
EXPORT_SYMBOL(drm_add_modes_noedid);

/**
* drm_mode_cea_vic - return the CEA-861 VIC of a given mode
* @mode: mode
*
* RETURNS:
* The VIC number, 0 in case it's not a CEA-861 mode.
*/
uint8_t drm_mode_cea_vic(const struct drm_display_mode *mode)
{
uint8_t i;

for (i = 0; i < drm_num_cea_modes; i++)
if (drm_mode_equal(mode, &edid_cea_modes[i]))
return i + 1;

return 0;
}
EXPORT_SYMBOL(drm_mode_cea_vic);
14 changes: 8 additions & 6 deletions drivers/gpu/drm/i915/i915_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data)
seq_printf(m, "No flip due on pipe %c (plane %c)\n",
pipe, plane);
} else {
if (!work->pending) {
if (atomic_read(&work->pending) < INTEL_FLIP_COMPLETE) {
seq_printf(m, "Flip queued on pipe %c (plane %c)\n",
pipe, plane);
} else {
Expand All @@ -328,7 +328,7 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data)
seq_printf(m, "Stall check enabled, ");
else
seq_printf(m, "Stall check waiting for page flip ioctl, ");
seq_printf(m, "%d prepares\n", work->pending);
seq_printf(m, "%d prepares\n", atomic_read(&work->pending));

if (work->old_fb_obj) {
struct drm_i915_gem_object *obj = work->old_fb_obj;
Expand Down Expand Up @@ -655,10 +655,12 @@ static void i915_ring_error_state(struct seq_file *m,
if (INTEL_INFO(dev)->gen >= 6) {
seq_printf(m, " RC PSMI: 0x%08x\n", error->rc_psmi[ring]);
seq_printf(m, " FAULT_REG: 0x%08x\n", error->fault_reg[ring]);
seq_printf(m, " SYNC_0: 0x%08x\n",
error->semaphore_mboxes[ring][0]);
seq_printf(m, " SYNC_1: 0x%08x\n",
error->semaphore_mboxes[ring][1]);
seq_printf(m, " SYNC_0: 0x%08x [last synced 0x%08x]\n",
error->semaphore_mboxes[ring][0],
error->semaphore_seqno[ring][0]);
seq_printf(m, " SYNC_1: 0x%08x [last synced 0x%08x]\n",
error->semaphore_mboxes[ring][1],
error->semaphore_seqno[ring][1]);
}
seq_printf(m, " seqno: 0x%08x\n", error->seqno[ring]);
seq_printf(m, " waiting: %s\n", yesno(error->waiting[ring]));
Expand Down
9 changes: 4 additions & 5 deletions drivers/gpu/drm/i915/i915_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ void i915_kernel_lost_context(struct drm_device * dev)

ring->head = I915_READ_HEAD(ring) & HEAD_ADDR;
ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
ring->space = ring->head - (ring->tail + 8);
ring->space = ring->head - (ring->tail + I915_RING_FREE_SPACE);
if (ring->space < 0)
ring->space += ring->size;

Expand Down Expand Up @@ -592,10 +592,8 @@ static int i915_dispatch_flip(struct drm_device * dev)

static int i915_quiescent(struct drm_device *dev)
{
struct intel_ring_buffer *ring = LP_RING(dev->dev_private);

i915_kernel_lost_context(dev);
return intel_wait_ring_idle(ring);
return intel_ring_idle(LP_RING(dev->dev_private));
}

static int i915_flush_ioctl(struct drm_device *dev, void *data,
Expand Down Expand Up @@ -1045,7 +1043,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
{
drm_i915_private_t *dev_priv = dev->dev_private;
drm_i915_hws_addr_t *hws = data;
struct intel_ring_buffer *ring = LP_RING(dev_priv);
struct intel_ring_buffer *ring;

if (drm_core_check_feature(dev, DRIVER_MODESET))
return -ENODEV;
Expand All @@ -1065,6 +1063,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,

DRM_DEBUG_DRIVER("set status page addr 0x%08x\n", (u32)hws->addr);

ring = LP_RING(dev_priv);
ring->status_page.gfx_addr = hws->addr & (0x1ffff<<12);

dev_priv->dri1.gfx_hws_cpu_addr =
Expand Down
5 changes: 2 additions & 3 deletions drivers/gpu/drm/i915/i915_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -554,8 +554,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))
ironlake_init_pch_refclk(dev);
intel_init_pch_refclk(dev);

mutex_lock(&dev->struct_mutex);
dev_priv->mm.suspended = 0;
Expand All @@ -564,7 +563,7 @@ static int __i915_drm_thaw(struct drm_device *dev)
mutex_unlock(&dev->struct_mutex);

intel_modeset_init_hw(dev);
intel_modeset_setup_hw_state(dev);
intel_modeset_setup_hw_state(dev, false);
drm_irq_install(dev);
}

Expand Down
18 changes: 13 additions & 5 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ struct drm_i915_error_state {
u32 instdone[I915_NUM_RINGS];
u32 acthd[I915_NUM_RINGS];
u32 semaphore_mboxes[I915_NUM_RINGS][I915_NUM_RINGS - 1];
u32 semaphore_seqno[I915_NUM_RINGS][I915_NUM_RINGS - 1];
u32 rc_psmi[I915_NUM_RINGS]; /* sleep state */
/* our own tracking of ring head and tail */
u32 cpu_ring_head[I915_NUM_RINGS];
Expand Down Expand Up @@ -381,6 +382,11 @@ enum intel_pch {
PCH_LPT, /* Lynxpoint PCH */
};

enum intel_sbi_destination {
SBI_ICLK,
SBI_MPHY,
};

#define QUIRK_PIPEA_FORCE (1<<0)
#define QUIRK_LVDS_SSC_DISABLE (1<<1)
#define QUIRK_INVERT_BRIGHTNESS (1<<2)
Expand Down Expand Up @@ -909,6 +915,8 @@ typedef struct drm_i915_private {
bool hw_contexts_disabled;
uint32_t hw_context_size;

bool fdi_rx_polarity_reversed;

struct i915_suspend_saved_registers regfile;

/* Old dri1 support infrastructure, beware the dragons ya fools entering
Expand Down Expand Up @@ -1417,8 +1425,7 @@ int __must_check i915_mutex_lock_interruptible(struct drm_device *dev);
int i915_gem_object_sync(struct drm_i915_gem_object *obj,
struct intel_ring_buffer *to);
void i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
struct intel_ring_buffer *ring,
u32 seqno);
struct intel_ring_buffer *ring);

int i915_gem_dumb_create(struct drm_file *file_priv,
struct drm_device *dev,
Expand All @@ -1436,7 +1443,7 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2)
return (int32_t)(seq1 - seq2) >= 0;
}

u32 i915_gem_next_request_seqno(struct intel_ring_buffer *ring);
extern int i915_gem_get_seqno(struct drm_device *dev, u32 *seqno);

int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj);
int __must_check i915_gem_object_put_fence(struct drm_i915_gem_object *obj);
Expand Down Expand Up @@ -1652,11 +1659,12 @@ extern void intel_modeset_init(struct drm_device *dev);
extern void intel_modeset_gem_init(struct drm_device *dev);
extern void intel_modeset_cleanup(struct drm_device *dev);
extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
extern void intel_modeset_setup_hw_state(struct drm_device *dev);
extern void intel_modeset_setup_hw_state(struct drm_device *dev,
bool force_restore);
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 intel_init_pch_refclk(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);
Expand Down
96 changes: 58 additions & 38 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1696,10 +1696,14 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj)
if (obj->pages_pin_count)
return -EBUSY;

/* ->put_pages might need to allocate memory for the bit17 swizzle
* array, hence protect them from being reaped by removing them from gtt
* lists early. */
list_del(&obj->gtt_list);

ops->put_pages(obj);
obj->pages = NULL;

list_del(&obj->gtt_list);
if (i915_gem_object_is_purgeable(obj))
i915_gem_object_truncate(obj);

Expand Down Expand Up @@ -1857,11 +1861,11 @@ i915_gem_object_get_pages(struct drm_i915_gem_object *obj)

void
i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
struct intel_ring_buffer *ring,
u32 seqno)
struct intel_ring_buffer *ring)
{
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 seqno = intel_ring_get_seqno(ring);

BUG_ON(ring == NULL);
obj->ring = ring;
Expand Down Expand Up @@ -1922,26 +1926,54 @@ i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)
WARN_ON(i915_verify_lists(dev));
}

static u32
i915_gem_get_seqno(struct drm_device *dev)
static int
i915_gem_handle_seqno_wrap(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
u32 seqno = dev_priv->next_seqno;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_ring_buffer *ring;
int ret, i, j;

/* reserve 0 for non-seqno */
if (++dev_priv->next_seqno == 0)
dev_priv->next_seqno = 1;
/* The hardware uses various monotonic 32-bit counters, if we
* detect that they will wraparound we need to idle the GPU
* and reset those counters.
*/
ret = 0;
for_each_ring(ring, dev_priv, i) {
for (j = 0; j < ARRAY_SIZE(ring->sync_seqno); j++)
ret |= ring->sync_seqno[j] != 0;
}
if (ret == 0)
return ret;

ret = i915_gpu_idle(dev);
if (ret)
return ret;

i915_gem_retire_requests(dev);
for_each_ring(ring, dev_priv, i) {
for (j = 0; j < ARRAY_SIZE(ring->sync_seqno); j++)
ring->sync_seqno[j] = 0;
}

return seqno;
return 0;
}

u32
i915_gem_next_request_seqno(struct intel_ring_buffer *ring)
int
i915_gem_get_seqno(struct drm_device *dev, u32 *seqno)
{
if (ring->outstanding_lazy_request == 0)
ring->outstanding_lazy_request = i915_gem_get_seqno(ring->dev);
struct drm_i915_private *dev_priv = dev->dev_private;

/* reserve 0 for non-seqno */
if (dev_priv->next_seqno == 0) {
int ret = i915_gem_handle_seqno_wrap(dev);
if (ret)
return ret;

dev_priv->next_seqno = 1;
}

return ring->outstanding_lazy_request;
*seqno = dev_priv->next_seqno++;
return 0;
}

int
Expand All @@ -1952,7 +1984,6 @@ i915_add_request(struct intel_ring_buffer *ring,
drm_i915_private_t *dev_priv = ring->dev->dev_private;
struct drm_i915_gem_request *request;
u32 request_ring_position;
u32 seqno;
int was_empty;
int ret;

Expand All @@ -1971,7 +2002,6 @@ i915_add_request(struct intel_ring_buffer *ring,
if (request == NULL)
return -ENOMEM;

seqno = i915_gem_next_request_seqno(ring);

/* Record the position of the start of the request so that
* should we detect the updated seqno part-way through the
Expand All @@ -1980,15 +2010,13 @@ i915_add_request(struct intel_ring_buffer *ring,
*/
request_ring_position = intel_ring_get_tail(ring);

ret = ring->add_request(ring, &seqno);
ret = ring->add_request(ring);
if (ret) {
kfree(request);
return ret;
}

trace_i915_gem_request_add(ring, seqno);

request->seqno = seqno;
request->seqno = intel_ring_get_seqno(ring);
request->ring = ring;
request->tail = request_ring_position;
request->emitted_jiffies = jiffies;
Expand All @@ -2006,6 +2034,7 @@ i915_add_request(struct intel_ring_buffer *ring,
spin_unlock(&file_priv->mm.lock);
}

trace_i915_gem_request_add(ring, request->seqno);
ring->outstanding_lazy_request = 0;

if (!dev_priv->mm.suspended) {
Expand All @@ -2022,7 +2051,7 @@ i915_add_request(struct intel_ring_buffer *ring,
}

if (out_seqno)
*out_seqno = seqno;
*out_seqno = request->seqno;
return 0;
}

Expand Down Expand Up @@ -2120,7 +2149,6 @@ void
i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
{
uint32_t seqno;
int i;

if (list_empty(&ring->request_list))
return;
Expand All @@ -2129,10 +2157,6 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)

seqno = ring->get_seqno(ring, true);

for (i = 0; i < ARRAY_SIZE(ring->sync_seqno); i++)
if (seqno >= ring->sync_seqno[i])
ring->sync_seqno[i] = 0;

while (!list_empty(&ring->request_list)) {
struct drm_i915_gem_request *request;

Expand Down Expand Up @@ -2377,7 +2401,11 @@ i915_gem_object_sync(struct drm_i915_gem_object *obj,

ret = to->sync_to(to, from, seqno);
if (!ret)
from->sync_seqno[idx] = seqno;
/* We use last_read_seqno because sync_to()
* might have just caused seqno wrap under
* the radar.
*/
from->sync_seqno[idx] = obj->last_read_seqno;

return ret;
}
Expand Down Expand Up @@ -2460,14 +2488,6 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
return 0;
}

static int i915_ring_idle(struct intel_ring_buffer *ring)
{
if (list_empty(&ring->active_list))
return 0;

return i915_wait_seqno(ring, i915_gem_next_request_seqno(ring));
}

int i915_gpu_idle(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
Expand All @@ -2480,7 +2500,7 @@ int i915_gpu_idle(struct drm_device *dev)
if (ret)
return ret;

ret = i915_ring_idle(ring);
ret = intel_ring_idle(ring);
if (ret)
return ret;
}
Expand Down
3 changes: 1 addition & 2 deletions drivers/gpu/drm/i915/i915_gem_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,9 +410,8 @@ static int do_switch(struct i915_hw_context *to)
* MI_SET_CONTEXT instead of when the next seqno has completed.
*/
if (from_obj != NULL) {
u32 seqno = i915_gem_next_request_seqno(ring);
from_obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
i915_gem_object_move_to_active(from_obj, ring, seqno);
i915_gem_object_move_to_active(from_obj, ring);
/* 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
Expand Down
Loading

0 comments on commit 55bde6b

Please sign in to comment.