Commit 79c9089f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'drm-fixes-for-v4.10-rc7' of git://people.freedesktop.org/~airlied/linux

Pull drm fixes from Dave Airlie:
 "Another fixes pull for v4.10, it's a bit big due to the backport of
  the VMA fixes for i915 that should fix the oops on shutdown problems
  that you've worked around.

  There are also two drm core connector registration fixes, a bunch of
  nouveau regression fixes and two AMD fixes"

* tag 'drm-fixes-for-v4.10-rc7' of git://people.freedesktop.org/~airlied/linux:
  drm/radeon: Fix vram_size/visible values in DRM_RADEON_GEM_INFO ioctl
  drm/amdgpu/si: fix crash on headless asics
  drm/i915: Track pinned vma in intel_plane_state
  drm/atomic: Unconditionally call prepare_fb.
  drm/atomic: Fix double free in drm_atomic_state_default_clear
  drm/nouveau/kms/nv50: request vblank events for commits that send completion events
  drm/nouveau/nv1a,nv1f/disp: fix memory clock rate retrieval
  drm/nouveau/disp/gt215: Fix HDA ELD handling (thus, HDMI audio) on gt215
  drm/nouveau/nouveau/led: prevent compiling the led-code if nouveau=y and leds=m
  drm/nouveau/disp/mcp7x: disable dptmds workaround
  drm/nouveau: prevent userspace from deleting client object
  drm/nouveau/fence/g84-: protect against concurrent access to semaphore buffers
  drm: Don't race connector registration
  drm: prevent double-(un)registration for connectors
parents 57480b98 f63cf464
...@@ -254,6 +254,9 @@ static void gmc_v6_0_mc_program(struct amdgpu_device *adev) ...@@ -254,6 +254,9 @@ static void gmc_v6_0_mc_program(struct amdgpu_device *adev)
} }
WREG32(mmHDP_REG_COHERENCY_FLUSH_CNTL, 0); WREG32(mmHDP_REG_COHERENCY_FLUSH_CNTL, 0);
if (adev->mode_info.num_crtc)
amdgpu_display_set_vga_render_state(adev, false);
gmc_v6_0_mc_stop(adev, &save); gmc_v6_0_mc_stop(adev, &save);
if (gmc_v6_0_wait_for_idle((void *)adev)) { if (gmc_v6_0_wait_for_idle((void *)adev)) {
...@@ -283,7 +286,6 @@ static void gmc_v6_0_mc_program(struct amdgpu_device *adev) ...@@ -283,7 +286,6 @@ static void gmc_v6_0_mc_program(struct amdgpu_device *adev)
dev_warn(adev->dev, "Wait for MC idle timedout !\n"); dev_warn(adev->dev, "Wait for MC idle timedout !\n");
} }
gmc_v6_0_mc_resume(adev, &save); gmc_v6_0_mc_resume(adev, &save);
amdgpu_display_set_vga_render_state(adev, false);
} }
static int gmc_v6_0_mc_init(struct amdgpu_device *adev) static int gmc_v6_0_mc_init(struct amdgpu_device *adev)
......
...@@ -2032,13 +2032,16 @@ static void complete_crtc_signaling(struct drm_device *dev, ...@@ -2032,13 +2032,16 @@ static void complete_crtc_signaling(struct drm_device *dev,
} }
for_each_crtc_in_state(state, crtc, crtc_state, i) { for_each_crtc_in_state(state, crtc, crtc_state, i) {
struct drm_pending_vblank_event *event = crtc_state->event;
/* /*
* TEST_ONLY and PAGE_FLIP_EVENT are mutually * Free the allocated event. drm_atomic_helper_setup_commit
* exclusive, if they weren't, this code should be * can allocate an event too, so only free it if it's ours
* called on success for TEST_ONLY too. * to prevent a double free in drm_atomic_state_clear.
*/ */
if (crtc_state->event) if (event && (event->base.fence || event->base.file_priv)) {
drm_event_cancel_free(dev, &crtc_state->event->base); drm_event_cancel_free(dev, &event->base);
crtc_state->event = NULL;
}
} }
if (!fence_state) if (!fence_state)
......
...@@ -1666,9 +1666,6 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev, ...@@ -1666,9 +1666,6 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
funcs = plane->helper_private; funcs = plane->helper_private;
if (!drm_atomic_helper_framebuffer_changed(dev, state, plane_state->crtc))
continue;
if (funcs->prepare_fb) { if (funcs->prepare_fb) {
ret = funcs->prepare_fb(plane, plane_state); ret = funcs->prepare_fb(plane, plane_state);
if (ret) if (ret)
...@@ -1685,9 +1682,6 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev, ...@@ -1685,9 +1682,6 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
if (j >= i) if (j >= i)
continue; continue;
if (!drm_atomic_helper_framebuffer_changed(dev, state, plane_state->crtc))
continue;
funcs = plane->helper_private; funcs = plane->helper_private;
if (funcs->cleanup_fb) if (funcs->cleanup_fb)
...@@ -1954,9 +1948,6 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev, ...@@ -1954,9 +1948,6 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
for_each_plane_in_state(old_state, plane, plane_state, i) { for_each_plane_in_state(old_state, plane, plane_state, i) {
const struct drm_plane_helper_funcs *funcs; const struct drm_plane_helper_funcs *funcs;
if (!drm_atomic_helper_framebuffer_changed(dev, old_state, plane_state->crtc))
continue;
funcs = plane->helper_private; funcs = plane->helper_private;
if (funcs->cleanup_fb) if (funcs->cleanup_fb)
......
...@@ -225,6 +225,7 @@ int drm_connector_init(struct drm_device *dev, ...@@ -225,6 +225,7 @@ int drm_connector_init(struct drm_device *dev,
INIT_LIST_HEAD(&connector->probed_modes); INIT_LIST_HEAD(&connector->probed_modes);
INIT_LIST_HEAD(&connector->modes); INIT_LIST_HEAD(&connector->modes);
mutex_init(&connector->mutex);
connector->edid_blob_ptr = NULL; connector->edid_blob_ptr = NULL;
connector->status = connector_status_unknown; connector->status = connector_status_unknown;
...@@ -359,6 +360,8 @@ void drm_connector_cleanup(struct drm_connector *connector) ...@@ -359,6 +360,8 @@ void drm_connector_cleanup(struct drm_connector *connector)
connector->funcs->atomic_destroy_state(connector, connector->funcs->atomic_destroy_state(connector,
connector->state); connector->state);
mutex_destroy(&connector->mutex);
memset(connector, 0, sizeof(*connector)); memset(connector, 0, sizeof(*connector));
} }
EXPORT_SYMBOL(drm_connector_cleanup); EXPORT_SYMBOL(drm_connector_cleanup);
...@@ -374,14 +377,18 @@ EXPORT_SYMBOL(drm_connector_cleanup); ...@@ -374,14 +377,18 @@ EXPORT_SYMBOL(drm_connector_cleanup);
*/ */
int drm_connector_register(struct drm_connector *connector) int drm_connector_register(struct drm_connector *connector)
{ {
int ret; int ret = 0;
if (connector->registered) if (!connector->dev->registered)
return 0; return 0;
mutex_lock(&connector->mutex);
if (connector->registered)
goto unlock;
ret = drm_sysfs_connector_add(connector); ret = drm_sysfs_connector_add(connector);
if (ret) if (ret)
return ret; goto unlock;
ret = drm_debugfs_connector_add(connector); ret = drm_debugfs_connector_add(connector);
if (ret) { if (ret) {
...@@ -397,12 +404,14 @@ int drm_connector_register(struct drm_connector *connector) ...@@ -397,12 +404,14 @@ int drm_connector_register(struct drm_connector *connector)
drm_mode_object_register(connector->dev, &connector->base); drm_mode_object_register(connector->dev, &connector->base);
connector->registered = true; connector->registered = true;
return 0; goto unlock;
err_debugfs: err_debugfs:
drm_debugfs_connector_remove(connector); drm_debugfs_connector_remove(connector);
err_sysfs: err_sysfs:
drm_sysfs_connector_remove(connector); drm_sysfs_connector_remove(connector);
unlock:
mutex_unlock(&connector->mutex);
return ret; return ret;
} }
EXPORT_SYMBOL(drm_connector_register); EXPORT_SYMBOL(drm_connector_register);
...@@ -415,8 +424,11 @@ EXPORT_SYMBOL(drm_connector_register); ...@@ -415,8 +424,11 @@ EXPORT_SYMBOL(drm_connector_register);
*/ */
void drm_connector_unregister(struct drm_connector *connector) void drm_connector_unregister(struct drm_connector *connector)
{ {
if (!connector->registered) mutex_lock(&connector->mutex);
if (!connector->registered) {
mutex_unlock(&connector->mutex);
return; return;
}
if (connector->funcs->early_unregister) if (connector->funcs->early_unregister)
connector->funcs->early_unregister(connector); connector->funcs->early_unregister(connector);
...@@ -425,6 +437,7 @@ void drm_connector_unregister(struct drm_connector *connector) ...@@ -425,6 +437,7 @@ void drm_connector_unregister(struct drm_connector *connector)
drm_debugfs_connector_remove(connector); drm_debugfs_connector_remove(connector);
connector->registered = false; connector->registered = false;
mutex_unlock(&connector->mutex);
} }
EXPORT_SYMBOL(drm_connector_unregister); EXPORT_SYMBOL(drm_connector_unregister);
......
...@@ -745,6 +745,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) ...@@ -745,6 +745,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
if (ret) if (ret)
goto err_minors; goto err_minors;
dev->registered = true;
if (dev->driver->load) { if (dev->driver->load) {
ret = dev->driver->load(dev, flags); ret = dev->driver->load(dev, flags);
if (ret) if (ret)
...@@ -785,6 +787,8 @@ void drm_dev_unregister(struct drm_device *dev) ...@@ -785,6 +787,8 @@ void drm_dev_unregister(struct drm_device *dev)
drm_lastclose(dev); drm_lastclose(dev);
dev->registered = false;
if (drm_core_check_feature(dev, DRIVER_MODESET)) if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_modeset_unregister_all(dev); drm_modeset_unregister_all(dev);
......
...@@ -1012,6 +1012,8 @@ struct intel_fbc { ...@@ -1012,6 +1012,8 @@ struct intel_fbc {
struct work_struct underrun_work; struct work_struct underrun_work;
struct intel_fbc_state_cache { struct intel_fbc_state_cache {
struct i915_vma *vma;
struct { struct {
unsigned int mode_flags; unsigned int mode_flags;
uint32_t hsw_bdw_pixel_rate; uint32_t hsw_bdw_pixel_rate;
...@@ -1025,15 +1027,14 @@ struct intel_fbc { ...@@ -1025,15 +1027,14 @@ struct intel_fbc {
} plane; } plane;
struct { struct {
u64 ilk_ggtt_offset;
uint32_t pixel_format; uint32_t pixel_format;
unsigned int stride; unsigned int stride;
int fence_reg;
unsigned int tiling_mode;
} fb; } fb;
} state_cache; } state_cache;
struct intel_fbc_reg_params { struct intel_fbc_reg_params {
struct i915_vma *vma;
struct { struct {
enum pipe pipe; enum pipe pipe;
enum plane plane; enum plane plane;
...@@ -1041,10 +1042,8 @@ struct intel_fbc { ...@@ -1041,10 +1042,8 @@ struct intel_fbc {
} crtc; } crtc;
struct { struct {
u64 ggtt_offset;
uint32_t pixel_format; uint32_t pixel_format;
unsigned int stride; unsigned int stride;
int fence_reg;
} fb; } fb;
int cfb_size; int cfb_size;
...@@ -3168,13 +3167,6 @@ i915_gem_object_to_ggtt(struct drm_i915_gem_object *obj, ...@@ -3168,13 +3167,6 @@ i915_gem_object_to_ggtt(struct drm_i915_gem_object *obj,
return i915_gem_obj_to_vma(obj, &to_i915(obj->base.dev)->ggtt.base, view); return i915_gem_obj_to_vma(obj, &to_i915(obj->base.dev)->ggtt.base, view);
} }
static inline unsigned long
i915_gem_object_ggtt_offset(struct drm_i915_gem_object *o,
const struct i915_ggtt_view *view)
{
return i915_ggtt_offset(i915_gem_object_to_ggtt(o, view));
}
/* i915_gem_fence_reg.c */ /* i915_gem_fence_reg.c */
int __must_check i915_vma_get_fence(struct i915_vma *vma); int __must_check i915_vma_get_fence(struct i915_vma *vma);
int __must_check i915_vma_put_fence(struct i915_vma *vma); int __must_check i915_vma_put_fence(struct i915_vma *vma);
......
...@@ -85,6 +85,8 @@ intel_plane_duplicate_state(struct drm_plane *plane) ...@@ -85,6 +85,8 @@ intel_plane_duplicate_state(struct drm_plane *plane)
__drm_atomic_helper_plane_duplicate_state(plane, state); __drm_atomic_helper_plane_duplicate_state(plane, state);
intel_state->vma = NULL;
return state; return state;
} }
...@@ -100,6 +102,24 @@ void ...@@ -100,6 +102,24 @@ void
intel_plane_destroy_state(struct drm_plane *plane, intel_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state) struct drm_plane_state *state)
{ {
struct i915_vma *vma;
vma = fetch_and_zero(&to_intel_plane_state(state)->vma);
/*
* FIXME: Normally intel_cleanup_plane_fb handles destruction of vma.
* We currently don't clear all planes during driver unload, so we have
* to be able to unpin vma here for now.
*
* Normally this can only happen during unload when kmscon is disabled
* and userspace doesn't attempt to set a framebuffer at all.
*/
if (vma) {
mutex_lock(&plane->dev->struct_mutex);
intel_unpin_fb_vma(vma);
mutex_unlock(&plane->dev->struct_mutex);
}
drm_atomic_helper_plane_destroy_state(plane, state); drm_atomic_helper_plane_destroy_state(plane, state);
} }
......
...@@ -2235,27 +2235,22 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation) ...@@ -2235,27 +2235,22 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
i915_vma_pin_fence(vma); i915_vma_pin_fence(vma);
} }
i915_vma_get(vma);
err: err:
intel_runtime_pm_put(dev_priv); intel_runtime_pm_put(dev_priv);
return vma; return vma;
} }
void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation) void intel_unpin_fb_vma(struct i915_vma *vma)
{ {
struct drm_i915_gem_object *obj = intel_fb_obj(fb); lockdep_assert_held(&vma->vm->dev->struct_mutex);
struct i915_ggtt_view view;
struct i915_vma *vma;
WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
intel_fill_fb_ggtt_view(&view, fb, rotation);
vma = i915_gem_object_to_ggtt(obj, &view);
if (WARN_ON_ONCE(!vma)) if (WARN_ON_ONCE(!vma))
return; return;
i915_vma_unpin_fence(vma); i915_vma_unpin_fence(vma);
i915_gem_object_unpin_from_display_plane(vma); i915_gem_object_unpin_from_display_plane(vma);
i915_vma_put(vma);
} }
static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane, static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane,
...@@ -2750,7 +2745,6 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, ...@@ -2750,7 +2745,6 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
struct drm_device *dev = intel_crtc->base.dev; struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_crtc *c; struct drm_crtc *c;
struct intel_crtc *i;
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
struct drm_plane *primary = intel_crtc->base.primary; struct drm_plane *primary = intel_crtc->base.primary;
struct drm_plane_state *plane_state = primary->state; struct drm_plane_state *plane_state = primary->state;
...@@ -2775,20 +2769,20 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, ...@@ -2775,20 +2769,20 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
* an fb with another CRTC instead * an fb with another CRTC instead
*/ */
for_each_crtc(dev, c) { for_each_crtc(dev, c) {
i = to_intel_crtc(c); struct intel_plane_state *state;
if (c == &intel_crtc->base) if (c == &intel_crtc->base)
continue; continue;
if (!i->active) if (!to_intel_crtc(c)->active)
continue; continue;
fb = c->primary->fb; state = to_intel_plane_state(c->primary->state);
if (!fb) if (!state->vma)
continue; continue;
obj = intel_fb_obj(fb); if (intel_plane_ggtt_offset(state) == plane_config->base) {
if (i915_gem_object_ggtt_offset(obj, NULL) == plane_config->base) { fb = c->primary->fb;
drm_framebuffer_reference(fb); drm_framebuffer_reference(fb);
goto valid_fb; goto valid_fb;
} }
...@@ -2809,6 +2803,19 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, ...@@ -2809,6 +2803,19 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
return; return;
valid_fb: valid_fb:
mutex_lock(&dev->struct_mutex);
intel_state->vma =
intel_pin_and_fence_fb_obj(fb, primary->state->rotation);
mutex_unlock(&dev->struct_mutex);
if (IS_ERR(intel_state->vma)) {
DRM_ERROR("failed to pin boot fb on pipe %d: %li\n",
intel_crtc->pipe, PTR_ERR(intel_state->vma));
intel_state->vma = NULL;
drm_framebuffer_unreference(fb);
return;
}
plane_state->src_x = 0; plane_state->src_x = 0;
plane_state->src_y = 0; plane_state->src_y = 0;
plane_state->src_w = fb->width << 16; plane_state->src_w = fb->width << 16;
...@@ -3104,13 +3111,13 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, ...@@ -3104,13 +3111,13 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
if (INTEL_GEN(dev_priv) >= 4) { if (INTEL_GEN(dev_priv) >= 4) {
I915_WRITE(DSPSURF(plane), I915_WRITE(DSPSURF(plane),
intel_fb_gtt_offset(fb, rotation) + intel_plane_ggtt_offset(plane_state) +
intel_crtc->dspaddr_offset); intel_crtc->dspaddr_offset);
I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
I915_WRITE(DSPLINOFF(plane), linear_offset); I915_WRITE(DSPLINOFF(plane), linear_offset);
} else { } else {
I915_WRITE(DSPADDR(plane), I915_WRITE(DSPADDR(plane),
intel_fb_gtt_offset(fb, rotation) + intel_plane_ggtt_offset(plane_state) +
intel_crtc->dspaddr_offset); intel_crtc->dspaddr_offset);
} }
POSTING_READ(reg); POSTING_READ(reg);
...@@ -3207,7 +3214,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, ...@@ -3207,7 +3214,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
I915_WRITE(DSPSURF(plane), I915_WRITE(DSPSURF(plane),
intel_fb_gtt_offset(fb, rotation) + intel_plane_ggtt_offset(plane_state) +
intel_crtc->dspaddr_offset); intel_crtc->dspaddr_offset);
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
I915_WRITE(DSPOFFSET(plane), (y << 16) | x); I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
...@@ -3230,23 +3237,6 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv, ...@@ -3230,23 +3237,6 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
} }
} }
u32 intel_fb_gtt_offset(struct drm_framebuffer *fb,
unsigned int rotation)
{
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct i915_ggtt_view view;
struct i915_vma *vma;
intel_fill_fb_ggtt_view(&view, fb, rotation);
vma = i915_gem_object_to_ggtt(obj, &view);
if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
view.type))
return -1;
return i915_ggtt_offset(vma);
}
static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id) static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
{ {
struct drm_device *dev = intel_crtc->base.dev; struct drm_device *dev = intel_crtc->base.dev;
...@@ -3441,7 +3431,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane, ...@@ -3441,7 +3431,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
} }
I915_WRITE(PLANE_SURF(pipe, 0), I915_WRITE(PLANE_SURF(pipe, 0),
intel_fb_gtt_offset(fb, rotation) + surf_addr); intel_plane_ggtt_offset(plane_state) + surf_addr);
POSTING_READ(PLANE_SURF(pipe, 0)); POSTING_READ(PLANE_SURF(pipe, 0));
} }
...@@ -11536,7 +11526,7 @@ static void intel_unpin_work_fn(struct work_struct *__work) ...@@ -11536,7 +11526,7 @@ static void intel_unpin_work_fn(struct work_struct *__work)
flush_work(&work->mmio_work); flush_work(&work->mmio_work);
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
intel_unpin_fb_obj(work->old_fb, primary->state->rotation); intel_unpin_fb_vma(work->old_vma);
i915_gem_object_put(work->pending_flip_obj); i915_gem_object_put(work->pending_flip_obj);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
...@@ -12246,8 +12236,10 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, ...@@ -12246,8 +12236,10 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
goto cleanup_pending; goto cleanup_pending;
} }
work->gtt_offset = intel_fb_gtt_offset(fb, primary->state->rotation); work->old_vma = to_intel_plane_state(primary->state)->vma;
work->gtt_offset += intel_crtc->dspaddr_offset; to_intel_plane_state(primary->state)->vma = vma;
work->gtt_offset = i915_ggtt_offset(vma) + intel_crtc->dspaddr_offset;
work->rotation = crtc->primary->state->rotation; work->rotation = crtc->primary->state->rotation;
/* /*
...@@ -12301,7 +12293,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, ...@@ -12301,7 +12293,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
cleanup_request: cleanup_request:
i915_add_request_no_flush(request); i915_add_request_no_flush(request);
cleanup_unpin: cleanup_unpin:
intel_unpin_fb_obj(fb, crtc->primary->state->rotation); to_intel_plane_state(primary->state)->vma = work->old_vma;
intel_unpin_fb_vma(vma);
cleanup_pending: cleanup_pending:
atomic_dec(&intel_crtc->unpin_work_count); atomic_dec(&intel_crtc->unpin_work_count);
unlock: unlock:
...@@ -14794,6 +14787,8 @@ intel_prepare_plane_fb(struct drm_plane *plane, ...@@ -14794,6 +14787,8 @@ intel_prepare_plane_fb(struct drm_plane *plane,
DRM_DEBUG_KMS("failed to pin object\n"); DRM_DEBUG_KMS("failed to pin object\n");
return PTR_ERR(vma); return PTR_ERR(vma);
} }
to_intel_plane_state(new_state)->vma = vma;
} }
return 0; return 0;
...@@ -14812,19 +14807,12 @@ void ...@@ -14812,19 +14807,12 @@ void
intel_cleanup_plane_fb(struct drm_plane *plane, intel_cleanup_plane_fb(struct drm_plane *plane,
struct drm_plane_state *old_state) struct drm_plane_state *old_state)
{ {
struct drm_i915_private *dev_priv = to_i915(plane->dev); struct i915_vma *vma;
struct intel_plane_state *old_intel_state;
struct drm_i915_gem_object *old_obj = intel_fb_obj(old_state->fb);
struct drm_i915_gem_object *obj = intel_fb_obj(plane->state->fb);
old_intel_state = to_intel_plane_state(old_state);
if (!obj && !old_obj)
return;
if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR || /* Should only be called after a successful intel_prepare_plane_fb()! */
!INTEL_INFO(dev_priv)->cursor_needs_physical)) vma = fetch_and_zero(&to_intel_plane_state(old_state)->vma);
intel_unpin_fb_obj(old_state->fb, old_state->rotation); if (vma)
intel_unpin_fb_vma(vma);
} }
int int
...@@ -15166,7 +15154,7 @@ intel_update_cursor_plane(struct drm_plane *plane, ...@@ -15166,7 +15154,7 @@ intel_update_cursor_plane(struct drm_plane *plane,
if (!obj) if (!obj)
addr = 0; addr = 0;
else if (!INTEL_INFO(dev_priv)->cursor_needs_physical) else if (!INTEL_INFO(dev_priv)->cursor_needs_physical)
addr = i915_gem_object_ggtt_offset(obj, NULL); addr = intel_plane_ggtt_offset(state);
else else
addr = obj->phys_handle->busaddr; addr = obj->phys_handle->busaddr;
...@@ -17066,41 +17054,12 @@ void intel_display_resume(struct drm_device *dev) ...@@ -17066,41 +17054,12 @@ void intel_display_resume(struct drm_device *dev)
void intel_modeset_gem_init(struct drm_device *dev) void intel_modeset_gem_init(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_crtc *c;
struct drm_i915_gem_object *obj;
intel_init_gt_powersave(dev_priv); intel_init_gt_powersave(dev_priv);
intel_modeset_init_hw(dev); intel_modeset_init_hw(dev);
intel_setup_overlay(dev_priv); intel_setup_overlay(dev_priv);
/*
* Make sure any fbs we allocated at startup are properly
* pinned & fenced. When we do the allocation it's too early
* for this.
*/
for_each_crtc(dev, c) {
struct i915_vma *vma;
obj = intel_fb_obj(c->primary->fb);
if (obj == NULL)
continue;
mutex_lock(&dev->struct_mutex);
vma = intel_pin_and_fence_fb_obj(c->primary->fb,
c->primary->state->rotation);
mutex_unlock(&dev->struct_mutex);
if (IS_ERR(vma)) {
DRM_ERROR("failed to pin boot fb on pipe %d\n",
to_intel_crtc(c)->pipe);
drm_framebuffer_unreference(c->primary->fb);
c->primary->fb = NULL;
c->primary->crtc = c->primary->state->crtc = NULL;
update_state_fb(c->primary);
c->state->plane_mask &= ~(1 << drm_plane_index(c->primary));
}
}
} }
int intel_connector_register(struct drm_connector *connector) int intel_connector_register(struct drm_connector *connector)
......
...@@ -377,6 +377,7 @@ struct intel_atomic_state { ...@@ -377,6 +377,7 @@ struct intel_atomic_state {
struct intel_plane_state { struct intel_plane_state {
struct drm_plane_state base; struct drm_plane_state base;
struct drm_rect clip; struct drm_rect clip;
struct i915_vma *vma;
struct { struct {
u32 offset; u32 offset;
...@@ -1046,6 +1047,7 @@ struct intel_flip_work { ...@@ -1046,6 +1047,7 @@ struct intel_flip_work {
struct work_struct mmio_work; struct work_struct mmio_work;
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct i915_vma *old_vma;
struct drm_framebuffer *old_fb; struct drm_framebuffer *old_fb;
struct drm_i915_gem_object *pending_flip_obj; struct drm_i915_gem_object *pending_flip_obj;
struct drm_pending_vblank_event *event; struct drm_pending_vblank_event *event;
...@@ -1273,7 +1275,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, ...@@ -1273,7 +1275,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
struct drm_modeset_acquire_ctx *ctx); struct drm_modeset_acquire_ctx *ctx);
struct i915_vma * struct i915_vma *
intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation); intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation);
void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation); void intel_unpin_fb_vma(struct i915_vma *vma);
struct drm_framebuffer * struct drm_framebuffer *
__intel_framebuffer_create(struct drm_device *dev, __intel_framebuffer_create(struct drm_device *dev,
struct drm_mode_fb_cmd2 *mode_cmd, struct drm_mode_fb_cmd2 *mode_cmd,
...@@ -1362,7 +1364,10 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode, ...@@ -1362,7 +1364,10 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state); int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state); int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
u32 intel_fb_gtt_offset(struct drm_framebuffer *fb, unsigned int rotation); static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
{
return i915_ggtt_offset(state->vma);
}
u32 skl_plane_ctl_format(uint32_t pixel_format); u32 skl_plane_ctl_format(uint32_t pixel_format);
u32 skl_plane_ctl_tiling(uint64_t fb_modifier); u32 skl_plane_ctl_tiling(uint64_t fb_modifier);
......
...@@ -173,7 +173,7 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv) ...@@ -173,7 +173,7 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv)
if (IS_I945GM(dev_priv)) if (IS_I945GM(dev_priv))
fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */ fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
fbc_ctl |= params->fb.fence_reg; fbc_ctl |= params->vma->fence->id;
I915_WRITE(FBC_CONTROL, fbc_ctl); I915_WRITE(FBC_CONTROL, fbc_ctl);
} }
...@@ -193,8 +193,8 @@ static void g4x_fbc_activate(struct drm_i915_private *dev_priv) ...@@ -193,8 +193,8 @@ static void g4x_fbc_activate(struct drm_i915_private *dev_priv)
else else
dpfc_ctl |= DPFC_CTL_LIMIT_1X; dpfc_ctl |= DPFC_CTL_LIMIT_1X;
if (params->fb.fence_reg != I915_FENCE_REG_NONE) { if (params->vma->fence) {
dpfc_ctl |= DPFC_CTL_FENCE_EN | params->fb.fence_reg; dpfc_ctl |= DPFC_CTL_FENCE_EN | params->vma->fence->id;
I915_WRITE(DPFC_FENCE_YOFF, params->crtc.fence_y_offset); I915_WRITE(DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
} else { } else {
I915_WRITE(DPFC_FENCE_YOFF, 0); I915_WRITE(DPFC_FENCE_YOFF, 0);
...@@ -251,13 +251,14 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv) ...@@ -251,13 +251,14 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
break; break;
} }
if (params->fb.fence_reg != I915_FENCE_REG_NONE) { if (params->vma->fence) {
dpfc_ctl |= DPFC_CTL_FENCE_EN; dpfc_ctl |= DPFC_CTL_FENCE_EN;
if (IS_GEN5(dev_priv)) if (IS_GEN5(dev_priv))
dpfc_ctl |= params->fb.fence_reg; dpfc_ctl |= params->vma->fence->id;
if (IS_GEN6(dev_priv)) { if (IS_GEN6(dev_priv)) {
I915_WRITE(SNB_DPFC_CTL_SA, I915_WRITE(SNB_DPFC_CTL_SA,
SNB_CPU_FENCE_ENABLE | params->fb.fence_reg); SNB_CPU_FENCE_ENABLE |
params->vma->fence->id);
I915_WRITE(DPFC_CPU_FENCE_OFFSET, I915_WRITE(DPFC_CPU_FENCE_OFFSET,
params->crtc.fence_y_offset); params->crtc.fence_y_offset);
} }
...@@ -269,7 +270,8 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv) ...@@ -269,7 +270,8 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
} }
I915_WRITE(ILK_DPFC_FENCE_YOFF, params->crtc.fence_y_offset); I915_WRITE(ILK_DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
I915_WRITE(ILK_FBC_RT_BASE, params->fb.ggtt_offset | ILK_FBC_RT_VALID); I915_WRITE(ILK_FBC_RT_BASE,
i915_ggtt_offset(params->vma) | ILK_FBC_RT_VALID);
/* enable it... */ /* enable it... */
I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
...@@ -319,10 +321,11 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv) ...@@ -319,10 +321,11 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
break; break;
} }
if (params->fb.fence_reg != I915_FENCE_REG_NONE) { if (params->vma->fence) {
dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN; dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN;
I915_WRITE(SNB_DPFC_CTL_SA, I915_WRITE(SNB_DPFC_CTL_SA,
SNB_CPU_FENCE_ENABLE | params->fb.fence_reg); SNB_CPU_FENCE_ENABLE |
params->vma->fence->id);
I915_WRITE(DPFC_CPU_FENCE_OFFSET, params->crtc.fence_y_offset); I915_WRITE(DPFC_CPU_FENCE_OFFSET, params->crtc.fence_y_offset);
} else { } else {
I915_WRITE(SNB_DPFC_CTL_SA,0); I915_WRITE(SNB_DPFC_CTL_SA,0);
...@@ -727,14 +730,6 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc) ...@@ -727,14 +730,6 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
return effective_w <= max_w && effective_h <= max_h; return effective_w <= max_w && effective_h <= max_h;
} }
/* XXX replace me when we have VMA tracking for intel_plane_state */
static int get_fence_id(struct drm_framebuffer *fb)
{
struct i915_vma *vma = i915_gem_object_to_ggtt(intel_fb_obj(fb), NULL);
return vma && vma->fence ? vma->fence->id : I915_FENCE_REG_NONE;
}
static void intel_fbc_update_state_cache(struct intel_crtc *crtc, static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
struct intel_crtc_state *crtc_state, struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state) struct intel_plane_state *plane_state)
...@@ -743,7 +738,8 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, ...@@ -743,7 +738,8 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
struct intel_fbc *fbc = &dev_priv->fbc; struct intel_fbc *fbc = &dev_priv->fbc;
struct intel_fbc_state_cache *cache = &fbc->state_cache; struct intel_fbc_state_cache *cache = &fbc->state_cache;
struct drm_framebuffer *fb = plane_state->base.fb; struct drm_framebuffer *fb = plane_state->base.fb;
struct drm_i915_gem_object *obj;
cache->vma = NULL;
cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags; cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags;
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
...@@ -758,16 +754,10 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, ...@@ -758,16 +754,10 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
if (!cache->plane.visible) if (!cache->plane.visible)
return; return;
obj = intel_fb_obj(fb);
/* FIXME: We lack the proper locking here, so only run this on the
* platforms that need. */
if (IS_GEN(dev_priv, 5, 6))
cache->fb.ilk_ggtt_offset = i915_gem_object_ggtt_offset(obj, NULL);
cache->fb.pixel_format = fb->pixel_format; cache->fb.pixel_format = fb->pixel_format;
cache->fb.stride = fb->pitches[0]; cache->fb.stride = fb->pitches[0];
cache->fb.fence_reg = get_fence_id(fb);
cache->fb.tiling_mode = i915_gem_object_get_tiling(obj); cache->vma = plane_state->vma;
} }
static bool intel_fbc_can_activate(struct intel_crtc *crtc) static bool intel_fbc_can_activate(struct intel_crtc *crtc)
...@@ -784,7 +774,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) ...@@ -784,7 +774,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
return false; return false;
} }
if (!cache->plane.visible) { if (!cache->vma) {
fbc->no_fbc_reason = "primary plane not visible"; fbc->no_fbc_reason = "primary plane not visible";
return false; return false;
} }
...@@ -807,8 +797,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) ...@@ -807,8 +797,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
* so have no fence associated with it) due to aperture constaints * so have no fence associated with it) due to aperture constaints
* at the time of pinning. * at the time of pinning.
*/ */
if (cache->fb.tiling_mode != I915_TILING_X || if (!cache->vma->fence) {
cache->fb.fence_reg == I915_FENCE_REG_NONE) {
fbc->no_fbc_reason = "framebuffer not tiled or fenced"; fbc->no_fbc_reason = "framebuffer not tiled or fenced";
return false; return false;
} }
...@@ -888,17 +877,16 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, ...@@ -888,17 +877,16 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc,
* zero. */ * zero. */
memset(params, 0, sizeof(*params)); memset(params, 0, sizeof(*params));
params->vma = cache->vma;
params->crtc.pipe = crtc->pipe; params->crtc.pipe = crtc->pipe;
params->crtc.plane = crtc->plane; params->crtc.plane = crtc->plane;
params->crtc.fence_y_offset = get_crtc_fence_y_offset(crtc); params->crtc.fence_y_offset = get_crtc_fence_y_offset(crtc);
params->fb.pixel_format = cache->fb.pixel_format; params->fb.pixel_format = cache->fb.pixel_format;
params->fb.stride = cache->fb.stride; params->fb.stride = cache->fb.stride;
params->fb.fence_reg = cache->fb.fence_reg;
params->cfb_size = intel_fbc_calculate_cfb_size(dev_priv, cache); params->cfb_size = intel_fbc_calculate_cfb_size(dev_priv, cache);
params->fb.ggtt_offset = cache->fb.ilk_ggtt_offset;
} }
static bool intel_fbc_reg_params_equal(struct intel_fbc_reg_params *params1, static bool intel_fbc_reg_params_equal(struct intel_fbc_reg_params *params1,
......
...@@ -284,7 +284,7 @@ static int intelfb_create(struct drm_fb_helper *helper, ...@@ -284,7 +284,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
out_destroy_fbi: out_destroy_fbi:
drm_fb_helper_release_fbi(helper); drm_fb_helper_release_fbi(helper);
out_unpin: out_unpin:
intel_unpin_fb_obj(&ifbdev->fb->base, DRM_ROTATE_0); intel_unpin_fb_vma(vma);
out_unlock: out_unlock:
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return ret; return ret;
...@@ -549,7 +549,7 @@ static void intel_fbdev_destroy(struct intel_fbdev *ifbdev) ...@@ -549,7 +549,7 @@ static void intel_fbdev_destroy(struct intel_fbdev *ifbdev)
if (ifbdev->fb) { if (ifbdev->fb) {
mutex_lock(&ifbdev->helper.dev->struct_mutex); mutex_lock(&ifbdev->helper.dev->struct_mutex);
intel_unpin_fb_obj(&ifbdev->fb->base, DRM_ROTATE_0); intel_unpin_fb_vma(ifbdev->vma);
mutex_unlock(&ifbdev->helper.dev->struct_mutex); mutex_unlock(&ifbdev->helper.dev->struct_mutex);
drm_framebuffer_remove(&ifbdev->fb->base); drm_framebuffer_remove(&ifbdev->fb->base);
......
...@@ -273,7 +273,7 @@ skl_update_plane(struct drm_plane *drm_plane, ...@@ -273,7 +273,7 @@ skl_update_plane(struct drm_plane *drm_plane,
I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl); I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
I915_WRITE(PLANE_SURF(pipe, plane), I915_WRITE(PLANE_SURF(pipe, plane),
intel_fb_gtt_offset(fb, rotation) + surf_addr); intel_plane_ggtt_offset(plane_state) + surf_addr);
POSTING_READ(PLANE_SURF(pipe, plane)); POSTING_READ(PLANE_SURF(pipe, plane));
} }
...@@ -458,7 +458,7 @@ vlv_update_plane(struct drm_plane *dplane, ...@@ -458,7 +458,7 @@ vlv_update_plane(struct drm_plane *dplane,
I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w); I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
I915_WRITE(SPCNTR(pipe, plane), sprctl); I915_WRITE(SPCNTR(pipe, plane), sprctl);
I915_WRITE(SPSURF(pipe, plane), I915_WRITE(SPSURF(pipe, plane),
intel_fb_gtt_offset(fb, rotation) + sprsurf_offset); intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
POSTING_READ(SPSURF(pipe, plane)); POSTING_READ(SPSURF(pipe, plane));
} }
...@@ -594,7 +594,7 @@ ivb_update_plane(struct drm_plane *plane, ...@@ -594,7 +594,7 @@ ivb_update_plane(struct drm_plane *plane,
I915_WRITE(SPRSCALE(pipe), sprscale); I915_WRITE(SPRSCALE(pipe), sprscale);
I915_WRITE(SPRCTL(pipe), sprctl); I915_WRITE(SPRCTL(pipe), sprctl);
I915_WRITE(SPRSURF(pipe), I915_WRITE(SPRSURF(pipe),
intel_fb_gtt_offset(fb, rotation) + sprsurf_offset); intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
POSTING_READ(SPRSURF(pipe)); POSTING_READ(SPRSURF(pipe));
} }
...@@ -721,7 +721,7 @@ ilk_update_plane(struct drm_plane *plane, ...@@ -721,7 +721,7 @@ ilk_update_plane(struct drm_plane *plane,
I915_WRITE(DVSSCALE(pipe), dvsscale); I915_WRITE(DVSSCALE(pipe), dvsscale);
I915_WRITE(DVSCNTR(pipe), dvscntr); I915_WRITE(DVSCNTR(pipe), dvscntr);
I915_WRITE(DVSSURF(pipe), I915_WRITE(DVSSURF(pipe),
intel_fb_gtt_offset(fb, rotation) + dvssurf_offset); intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
POSTING_READ(DVSSURF(pipe)); POSTING_READ(DVSSURF(pipe));
} }
......
...@@ -222,6 +222,7 @@ nouveau_hw_get_clock(struct drm_device *dev, enum nvbios_pll_type plltype) ...@@ -222,6 +222,7 @@ nouveau_hw_get_clock(struct drm_device *dev, enum nvbios_pll_type plltype)
uint32_t mpllP; uint32_t mpllP;
pci_read_config_dword(pci_get_bus_and_slot(0, 3), 0x6c, &mpllP); pci_read_config_dword(pci_get_bus_and_slot(0, 3), 0x6c, &mpllP);
mpllP = (mpllP >> 8) & 0xf;
if (!mpllP) if (!mpllP)
mpllP = 4; mpllP = 4;
...@@ -232,7 +233,7 @@ nouveau_hw_get_clock(struct drm_device *dev, enum nvbios_pll_type plltype) ...@@ -232,7 +233,7 @@ nouveau_hw_get_clock(struct drm_device *dev, enum nvbios_pll_type plltype)
uint32_t clock; uint32_t clock;
pci_read_config_dword(pci_get_bus_and_slot(0, 5), 0x4c, &clock); pci_read_config_dword(pci_get_bus_and_slot(0, 5), 0x4c, &clock);
return clock; return clock / 1000;
} }
ret = nouveau_hw_get_pllvals(dev, plltype, &pllvals); ret = nouveau_hw_get_pllvals(dev, plltype, &pllvals);
......
...@@ -99,6 +99,7 @@ struct nv84_fence_priv { ...@@ -99,6 +99,7 @@ struct nv84_fence_priv {
struct nouveau_bo *bo; struct nouveau_bo *bo;
struct nouveau_bo *bo_gart; struct nouveau_bo *bo_gart;
u32 *suspend; u32 *suspend;
struct mutex mutex;
}; };
int nv84_fence_context_new(struct nouveau_channel *); int nv84_fence_context_new(struct nouveau_channel *);
......
...@@ -42,7 +42,7 @@ nouveau_led(struct drm_device *dev) ...@@ -42,7 +42,7 @@ nouveau_led(struct drm_device *dev)
} }
/* nouveau_led.c */ /* nouveau_led.c */
#if IS_ENABLED(CONFIG_LEDS_CLASS) #if IS_REACHABLE(CONFIG_LEDS_CLASS)
int nouveau_led_init(struct drm_device *dev); int nouveau_led_init(struct drm_device *dev);
void nouveau_led_suspend(struct drm_device *dev); void nouveau_led_suspend(struct drm_device *dev);
void nouveau_led_resume(struct drm_device *dev); void nouveau_led_resume(struct drm_device *dev);
......
...@@ -313,7 +313,8 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc) ...@@ -313,7 +313,8 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
if (!(ret = nvif_unpack(-ENOSYS, &data, &size, argv->v0, 0, 0, true))) { if (!(ret = nvif_unpack(-ENOSYS, &data, &size, argv->v0, 0, 0, true))) {
/* block access to objects not created via this interface */ /* block access to objects not created via this interface */
owner = argv->v0.owner; owner = argv->v0.owner;
if (argv->v0.object == 0ULL) if (argv->v0.object == 0ULL &&
argv->v0.type != NVIF_IOCTL_V0_DEL)
argv->v0.owner = NVDRM_OBJECT_ANY; /* except client */ argv->v0.owner = NVDRM_OBJECT_ANY; /* except client */
else else
argv->v0.owner = NVDRM_OBJECT_USIF; argv->v0.owner = NVDRM_OBJECT_USIF;
......
...@@ -4052,6 +4052,11 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -4052,6 +4052,11 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
} }
} }
for_each_crtc_in_state(state, crtc, crtc_state, i) {
if (crtc->state->event)
drm_crtc_vblank_get(crtc);
}
/* Update plane(s). */ /* Update plane(s). */
for_each_plane_in_state(state, plane, plane_state, i) { for_each_plane_in_state(state, plane, plane_state, i) {
struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane->state); struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane->state);
...@@ -4101,6 +4106,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -4101,6 +4106,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
drm_crtc_send_vblank_event(crtc, crtc->state->event); drm_crtc_send_vblank_event(crtc, crtc->state->event);
spin_unlock_irqrestore(&crtc->dev->event_lock, flags); spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
crtc->state->event = NULL; crtc->state->event = NULL;
drm_crtc_vblank_put(crtc);
} }
} }
......
...@@ -107,8 +107,10 @@ nv84_fence_context_del(struct nouveau_channel *chan) ...@@ -107,8 +107,10 @@ nv84_fence_context_del(struct nouveau_channel *chan)
struct nv84_fence_chan *fctx = chan->fence; struct nv84_fence_chan *fctx = chan->fence;
nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence); nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence);
mutex_lock(&priv->mutex);
nouveau_bo_vma_del(priv->bo, &fctx->vma_gart); nouveau_bo_vma_del(priv->bo, &fctx->vma_gart);
nouveau_bo_vma_del(priv->bo, &fctx->vma); nouveau_bo_vma_del(priv->bo, &fctx->vma);
mutex_unlock(&priv->mutex);
nouveau_fence_context_del(&fctx->base); nouveau_fence_context_del(&fctx->base);
chan->fence = NULL; chan->fence = NULL;
nouveau_fence_context_free(&fctx->base); nouveau_fence_context_free(&fctx->base);
...@@ -134,11 +136,13 @@ nv84_fence_context_new(struct nouveau_channel *chan) ...@@ -134,11 +136,13 @@ nv84_fence_context_new(struct nouveau_channel *chan)
fctx->base.sync32 = nv84_fence_sync32; fctx->base.sync32 = nv84_fence_sync32;
fctx->base.sequence = nv84_fence_read(chan); fctx->base.sequence = nv84_fence_read(chan);
mutex_lock(&priv->mutex);
ret = nouveau_bo_vma_add(priv->bo, cli->vm, &fctx->vma); ret = nouveau_bo_vma_add(priv->bo, cli->vm, &fctx->vma);
if (ret == 0) { if (ret == 0) {
ret = nouveau_bo_vma_add(priv->bo_gart, cli->vm, ret = nouveau_bo_vma_add(priv->bo_gart, cli->vm,
&fctx->vma_gart); &fctx->vma_gart);
} }
mutex_unlock(&priv->mutex);
if (ret) if (ret)
nv84_fence_context_del(chan); nv84_fence_context_del(chan);
...@@ -212,6 +216,8 @@ nv84_fence_create(struct nouveau_drm *drm) ...@@ -212,6 +216,8 @@ nv84_fence_create(struct nouveau_drm *drm)
priv->base.context_base = dma_fence_context_alloc(priv->base.contexts); priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
priv->base.uevent = true; priv->base.uevent = true;
mutex_init(&priv->mutex);
/* Use VRAM if there is any ; otherwise fallback to system memory */ /* Use VRAM if there is any ; otherwise fallback to system memory */
domain = drm->device.info.ram_size != 0 ? TTM_PL_FLAG_VRAM : domain = drm->device.info.ram_size != 0 ? TTM_PL_FLAG_VRAM :
/* /*
......
...@@ -59,7 +59,7 @@ gt215_hda_eld(NV50_DISP_MTHD_V1) ...@@ -59,7 +59,7 @@ gt215_hda_eld(NV50_DISP_MTHD_V1)
); );
} }
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
nvkm_wr32(device, 0x61c440 + soff, (i << 8) | args->v0.data[0]); nvkm_wr32(device, 0x61c440 + soff, (i << 8) | args->v0.data[i]);
for (; i < 0x60; i++) for (; i < 0x60; i++)
nvkm_wr32(device, 0x61c440 + soff, (i << 8)); nvkm_wr32(device, 0x61c440 + soff, (i << 8));
nvkm_mask(device, 0x61c448 + soff, 0x80000003, 0x80000003); nvkm_mask(device, 0x61c448 + soff, 0x80000003, 0x80000003);
......
...@@ -433,8 +433,6 @@ nv50_disp_dptmds_war(struct nvkm_device *device) ...@@ -433,8 +433,6 @@ nv50_disp_dptmds_war(struct nvkm_device *device)
case 0x94: case 0x94:
case 0x96: case 0x96:
case 0x98: case 0x98:
case 0xaa:
case 0xac:
return true; return true;
default: default:
break; break;
......
...@@ -97,9 +97,10 @@ ...@@ -97,9 +97,10 @@
* 2.46.0 - Add PFP_SYNC_ME support on evergreen * 2.46.0 - Add PFP_SYNC_ME support on evergreen
* 2.47.0 - Add UVD_NO_OP register support * 2.47.0 - Add UVD_NO_OP register support
* 2.48.0 - TA_CS_BC_BASE_ADDR allowed on SI * 2.48.0 - TA_CS_BC_BASE_ADDR allowed on SI
* 2.49.0 - DRM_RADEON_GEM_INFO ioctl returns correct vram_size/visible values
*/ */
#define KMS_DRIVER_MAJOR 2 #define KMS_DRIVER_MAJOR 2
#define KMS_DRIVER_MINOR 48 #define KMS_DRIVER_MINOR 49
#define KMS_DRIVER_PATCHLEVEL 0 #define KMS_DRIVER_PATCHLEVEL 0
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
int radeon_driver_unload_kms(struct drm_device *dev); int radeon_driver_unload_kms(struct drm_device *dev);
......
...@@ -220,8 +220,8 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data, ...@@ -220,8 +220,8 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data,
man = &rdev->mman.bdev.man[TTM_PL_VRAM]; man = &rdev->mman.bdev.man[TTM_PL_VRAM];
args->vram_size = rdev->mc.real_vram_size; args->vram_size = (u64)man->size << PAGE_SHIFT;
args->vram_visible = (u64)man->size << PAGE_SHIFT; args->vram_visible = rdev->mc.visible_vram_size;
args->vram_visible -= rdev->vram_pin_size; args->vram_visible -= rdev->vram_pin_size;
args->gart_size = rdev->mc.gtt_size; args->gart_size = rdev->mc.gtt_size;
args->gart_size -= rdev->gart_pin_size; args->gart_size -= rdev->gart_pin_size;
......
...@@ -517,6 +517,7 @@ struct drm_device { ...@@ -517,6 +517,7 @@ struct drm_device {
struct drm_minor *control; /**< Control node */ struct drm_minor *control; /**< Control node */
struct drm_minor *primary; /**< Primary node */ struct drm_minor *primary; /**< Primary node */
struct drm_minor *render; /**< Render node */ struct drm_minor *render; /**< Render node */
bool registered;
/* currently active master for this device. Protected by master_mutex */ /* currently active master for this device. Protected by master_mutex */
struct drm_master *master; struct drm_master *master;
......
...@@ -381,6 +381,8 @@ struct drm_connector_funcs { ...@@ -381,6 +381,8 @@ struct drm_connector_funcs {
* core drm connector interfaces. Everything added from this callback * core drm connector interfaces. Everything added from this callback
* should be unregistered in the early_unregister callback. * should be unregistered in the early_unregister callback.
* *
* This is called while holding drm_connector->mutex.
*
* Returns: * Returns:
* *
* 0 on success, or a negative error code on failure. * 0 on success, or a negative error code on failure.
...@@ -395,6 +397,8 @@ struct drm_connector_funcs { ...@@ -395,6 +397,8 @@ struct drm_connector_funcs {
* late_register(). It is called from drm_connector_unregister(), * late_register(). It is called from drm_connector_unregister(),
* early in the driver unload sequence to disable userspace access * early in the driver unload sequence to disable userspace access
* before data structures are torndown. * before data structures are torndown.
*
* This is called while holding drm_connector->mutex.
*/ */
void (*early_unregister)(struct drm_connector *connector); void (*early_unregister)(struct drm_connector *connector);
...@@ -559,7 +563,6 @@ struct drm_cmdline_mode { ...@@ -559,7 +563,6 @@ struct drm_cmdline_mode {
* @interlace_allowed: can this connector handle interlaced modes? * @interlace_allowed: can this connector handle interlaced modes?
* @doublescan_allowed: can this connector handle doublescan? * @doublescan_allowed: can this connector handle doublescan?
* @stereo_allowed: can this connector handle stereo modes? * @stereo_allowed: can this connector handle stereo modes?
* @registered: is this connector exposed (registered) with userspace?
* @modes: modes available on this connector (from fill_modes() + user) * @modes: modes available on this connector (from fill_modes() + user)
* @status: one of the drm_connector_status enums (connected, not, or unknown) * @status: one of the drm_connector_status enums (connected, not, or unknown)
* @probed_modes: list of modes derived directly from the display * @probed_modes: list of modes derived directly from the display
...@@ -607,6 +610,13 @@ struct drm_connector { ...@@ -607,6 +610,13 @@ struct drm_connector {
char *name; char *name;
/**
* @mutex: Lock for general connector state, but currently only protects
* @registered. Most of the connector state is still protected by the
* mutex in &drm_mode_config.
*/
struct mutex mutex;
/** /**
* @index: Compacted connector index, which matches the position inside * @index: Compacted connector index, which matches the position inside
* the mode_config.list for drivers not supporting hot-add/removing. Can * the mode_config.list for drivers not supporting hot-add/removing. Can
...@@ -620,6 +630,10 @@ struct drm_connector { ...@@ -620,6 +630,10 @@ struct drm_connector {
bool interlace_allowed; bool interlace_allowed;
bool doublescan_allowed; bool doublescan_allowed;
bool stereo_allowed; bool stereo_allowed;
/**
* @registered: Is this connector exposed (registered) with userspace?
* Protected by @mutex.
*/
bool registered; bool registered;
struct list_head modes; /* list of modes on this connector */ struct list_head modes; /* list of modes on this connector */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment