Skip to content

Commit

Permalink
Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Browse files Browse the repository at this point in the history
Pull drm fixes from Dave Airlie:
 "Misc i915, vmwgfx and radeon fixes along with a fix for one of those
  recursive sleep mutex debug cases in the mst code"

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
  drm/vmwgfx: Fix an issue with the device losing its irq line on module unload
  drm/vmwgfx: Correctly NULLify dma buffer pointer on failure
  drm/vmwgfx: Reorder device takedown somewhat
  drm/vmwgfx: Fix a couple of lock dependency violations
  drm/radeon: drop setting UPLL to sleep mode
  drm/radeon: fix wait to actually occur after the signaling callback
  drm/i915: Prevent TLB error on first execution on SNB
  drm/i915: Do both mt and gen6 style forcewake reset on ivb probe
  drm/i915: Make WAIT_IOCTL negative timeouts be indefinite again
  drm/i915: use in_interrupt() not in_irq() to check context
  drm/mst: fix recursive sleep warning on qlock
  drm: Don't assign fbs for universal cursor support to files
  • Loading branch information
torvalds committed Mar 14, 2015
2 parents 60b3e7b + e2cdcaf commit 7cd9beb
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 110 deletions.
35 changes: 19 additions & 16 deletions drivers/gpu/drm/drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@
#include "drm_crtc_internal.h"
#include "drm_internal.h"

static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
struct drm_mode_fb_cmd2 *r,
struct drm_file *file_priv);
static struct drm_framebuffer *
internal_framebuffer_create(struct drm_device *dev,
struct drm_mode_fb_cmd2 *r,
struct drm_file *file_priv);

/* Avoid boilerplate. I'm tired of typing. */
#define DRM_ENUM_NAME_FN(fnname, list) \
Expand Down Expand Up @@ -2908,13 +2909,11 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
*/
if (req->flags & DRM_MODE_CURSOR_BO) {
if (req->handle) {
fb = add_framebuffer_internal(dev, &fbreq, file_priv);
fb = internal_framebuffer_create(dev, &fbreq, file_priv);
if (IS_ERR(fb)) {
DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n");
return PTR_ERR(fb);
}

drm_framebuffer_reference(fb);
} else {
fb = NULL;
}
Expand Down Expand Up @@ -3267,9 +3266,10 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
return 0;
}

static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
struct drm_mode_fb_cmd2 *r,
struct drm_file *file_priv)
static struct drm_framebuffer *
internal_framebuffer_create(struct drm_device *dev,
struct drm_mode_fb_cmd2 *r,
struct drm_file *file_priv)
{
struct drm_mode_config *config = &dev->mode_config;
struct drm_framebuffer *fb;
Expand Down Expand Up @@ -3301,12 +3301,6 @@ static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
return fb;
}

mutex_lock(&file_priv->fbs_lock);
r->fb_id = fb->base.id;
list_add(&fb->filp_head, &file_priv->fbs);
DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
mutex_unlock(&file_priv->fbs_lock);

return fb;
}

Expand All @@ -3328,15 +3322,24 @@ static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
int drm_mode_addfb2(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
struct drm_mode_fb_cmd2 *r = data;
struct drm_framebuffer *fb;

if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;

fb = add_framebuffer_internal(dev, data, file_priv);
fb = internal_framebuffer_create(dev, r, file_priv);
if (IS_ERR(fb))
return PTR_ERR(fb);

/* Transfer ownership to the filp for reaping on close */

DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
mutex_lock(&file_priv->fbs_lock);
r->fb_id = fb->base.id;
list_add(&fb->filp_head, &file_priv->fbs);
mutex_unlock(&file_priv->fbs_lock);

return 0;
}

Expand Down
11 changes: 8 additions & 3 deletions drivers/gpu/drm/drm_dp_mst_topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -733,10 +733,14 @@ static bool check_txmsg_state(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_sideband_msg_tx *txmsg)
{
bool ret;
mutex_lock(&mgr->qlock);

/*
* All updates to txmsg->state are protected by mgr->qlock, and the two
* cases we check here are terminal states. For those the barriers
* provided by the wake_up/wait_event pair are enough.
*/
ret = (txmsg->state == DRM_DP_SIDEBAND_TX_RX ||
txmsg->state == DRM_DP_SIDEBAND_TX_TIMEOUT);
mutex_unlock(&mgr->qlock);
return ret;
}

Expand Down Expand Up @@ -1363,12 +1367,13 @@ static int process_single_tx_qlock(struct drm_dp_mst_topology_mgr *mgr,
return 0;
}

/* must be called holding qlock */
static void process_single_down_tx_qlock(struct drm_dp_mst_topology_mgr *mgr)
{
struct drm_dp_sideband_msg_tx *txmsg;
int ret;

WARN_ON(!mutex_is_locked(&mgr->qlock));

/* construct a chunk from the first msg in the tx_msg queue */
if (list_empty(&mgr->tx_msg_downq)) {
mgr->tx_down_in_progress = false;
Expand Down
25 changes: 20 additions & 5 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -2936,9 +2936,9 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
req = obj->last_read_req;

/* Do this after OLR check to make sure we make forward progress polling
* on this IOCTL with a timeout <=0 (like busy ioctl)
* on this IOCTL with a timeout == 0 (like busy ioctl)
*/
if (args->timeout_ns <= 0) {
if (args->timeout_ns == 0) {
ret = -ETIME;
goto out;
}
Expand All @@ -2948,7 +2948,8 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
i915_gem_request_reference(req);
mutex_unlock(&dev->struct_mutex);

ret = __i915_wait_request(req, reset_counter, true, &args->timeout_ns,
ret = __i915_wait_request(req, reset_counter, true,
args->timeout_ns > 0 ? &args->timeout_ns : NULL,
file->driver_priv);
mutex_lock(&dev->struct_mutex);
i915_gem_request_unreference(req);
Expand Down Expand Up @@ -4792,6 +4793,9 @@ i915_gem_init_hw(struct drm_device *dev)
if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt())
return -EIO;

/* Double layer security blanket, see i915_gem_init() */
intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);

if (dev_priv->ellc_size)
I915_WRITE(HSW_IDICR, I915_READ(HSW_IDICR) | IDIHASHMSK(0xf));

Expand Down Expand Up @@ -4824,7 +4828,7 @@ i915_gem_init_hw(struct drm_device *dev)
for_each_ring(ring, dev_priv, i) {
ret = ring->init_hw(ring);
if (ret)
return ret;
goto out;
}

for (i = 0; i < NUM_L3_SLICES(dev); i++)
Expand All @@ -4841,9 +4845,11 @@ i915_gem_init_hw(struct drm_device *dev)
DRM_ERROR("Context enable failed %d\n", ret);
i915_gem_cleanup_ringbuffer(dev);

return ret;
goto out;
}

out:
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
return ret;
}

Expand Down Expand Up @@ -4877,6 +4883,14 @@ int i915_gem_init(struct drm_device *dev)
dev_priv->gt.stop_ring = intel_logical_ring_stop;
}

/* This is just a security blanket to placate dragons.
* On some systems, we very sporadically observe that the first TLBs
* used by the CS may be stale, despite us poking the TLB reset. If
* we hold the forcewake during initialisation these problems
* just magically go away.
*/
intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);

ret = i915_gem_init_userptr(dev);
if (ret)
goto out_unlock;
Expand All @@ -4903,6 +4917,7 @@ int i915_gem_init(struct drm_device *dev)
}

out_unlock:
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
mutex_unlock(&dev->struct_mutex);

return ret;
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -9716,7 +9716,7 @@ void intel_check_page_flip(struct drm_device *dev, int pipe)
struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);

WARN_ON(!in_irq());
WARN_ON(!in_interrupt());

if (crtc == NULL)
return;
Expand Down
8 changes: 7 additions & 1 deletion drivers/gpu/drm/i915/intel_uncore.c
Original file line number Diff line number Diff line change
Expand Up @@ -1048,8 +1048,14 @@ static void intel_uncore_fw_domains_init(struct drm_device *dev)

/* We need to init first for ECOBUS access and then
* determine later if we want to reinit, in case of MT access is
* not working
* not working. In this stage we don't know which flavour this
* ivb is, so it is better to reset also the gen6 fw registers
* before the ecobus check.
*/

__raw_i915_write32(dev_priv, FORCEWAKE, 0);
__raw_posting_read(dev_priv, ECOBUS);

fw_domain_init(dev_priv, FW_DOMAIN_ID_RENDER,
FORCEWAKE_MT, FORCEWAKE_MT_ACK);

Expand Down
68 changes: 45 additions & 23 deletions drivers/gpu/drm/radeon/radeon_fence.c
Original file line number Diff line number Diff line change
Expand Up @@ -1030,37 +1030,59 @@ static inline bool radeon_test_signaled(struct radeon_fence *fence)
return test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags);
}

struct radeon_wait_cb {
struct fence_cb base;
struct task_struct *task;
};

static void
radeon_fence_wait_cb(struct fence *fence, struct fence_cb *cb)
{
struct radeon_wait_cb *wait =
container_of(cb, struct radeon_wait_cb, base);

wake_up_process(wait->task);
}

static signed long radeon_fence_default_wait(struct fence *f, bool intr,
signed long t)
{
struct radeon_fence *fence = to_radeon_fence(f);
struct radeon_device *rdev = fence->rdev;
bool signaled;
struct radeon_wait_cb cb;

fence_enable_sw_signaling(&fence->base);
cb.task = current;

/*
* This function has to return -EDEADLK, but cannot hold
* exclusive_lock during the wait because some callers
* may already hold it. This means checking needs_reset without
* lock, and not fiddling with any gpu internals.
*
* The callback installed with fence_enable_sw_signaling will
* run before our wait_event_*timeout call, so we will see
* both the signaled fence and the changes to needs_reset.
*/
if (fence_add_callback(f, &cb.base, radeon_fence_wait_cb))
return t;

while (t > 0) {
if (intr)
set_current_state(TASK_INTERRUPTIBLE);
else
set_current_state(TASK_UNINTERRUPTIBLE);

/*
* radeon_test_signaled must be called after
* set_current_state to prevent a race with wake_up_process
*/
if (radeon_test_signaled(fence))
break;

if (rdev->needs_reset) {
t = -EDEADLK;
break;
}

t = schedule_timeout(t);

if (t > 0 && intr && signal_pending(current))
t = -ERESTARTSYS;
}

__set_current_state(TASK_RUNNING);
fence_remove_callback(f, &cb.base);

if (intr)
t = wait_event_interruptible_timeout(rdev->fence_queue,
((signaled = radeon_test_signaled(fence)) ||
rdev->needs_reset), t);
else
t = wait_event_timeout(rdev->fence_queue,
((signaled = radeon_test_signaled(fence)) ||
rdev->needs_reset), t);

if (t > 0 && !signaled)
return -EDEADLK;
return t;
}

Expand Down
6 changes: 2 additions & 4 deletions drivers/gpu/drm/radeon/si.c
Original file line number Diff line number Diff line change
Expand Up @@ -7130,8 +7130,7 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK);

if (!vclk || !dclk) {
/* keep the Bypass mode, put PLL to sleep */
WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK);
/* keep the Bypass mode */
return 0;
}

Expand All @@ -7147,8 +7146,7 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
/* set VCO_MODE to 1 */
WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_VCO_MODE_MASK, ~UPLL_VCO_MODE_MASK);

/* toggle UPLL_SLEEP to 1 then back to 0 */
WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK);
/* disable sleep mode */
WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_SLEEP_MASK);

/* deassert UPLL_RESET */
Expand Down
Loading

0 comments on commit 7cd9beb

Please sign in to comment.