]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge tag 'drm-intel-next-2014-09-01' of git://anongit.freedesktop.org/drm-intel...
authorDave Airlie <airlied@redhat.com>
Tue, 2 Sep 2014 22:30:48 +0000 (08:30 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 2 Sep 2014 22:30:48 +0000 (08:30 +1000)
drm-intel-next-2014-08-22:
- basic code for execlist, which is the fancy new cmd submission on gen8. Still
  disabled by default (Ben, Oscar Mateo, Thomas Daniel et al)
- remove the useless usage of console_lock for I915_FBDEV=n (Chris)
- clean up relations between ctx and ppgtt
- clean up ppgtt lifetime handling (Michel Thierry)
- various cursor code improvements from Ville
- execbuffer code cleanups and secure batch fixes (Chris)
- prep work for dev -> dev_priv transition (Chris)
- some of the prep patches for the seqno -> request object transition (Chris)
- various small improvements all over

* tag 'drm-intel-next-2014-09-01' of git://anongit.freedesktop.org/drm-intel: (86 commits)
  drm/i915: fix suspend/resume for GENs w/o runtime PM support
  drm/i915: Update DRIVER_DATE to 20140822
  drm: fix plane rotation when restoring fbdev configuration
  drm/i915/bdw: Disable execlists by default
  drm/i915/bdw: Enable Logical Ring Contexts (hence, Execlists)
  drm/i915/bdw: Document Logical Rings, LR contexts and Execlists
  drm/i915/bdw: Print context state in debugfs
  drm/i915/bdw: Display context backing obj & ringbuffer info in debugfs
  drm/i915/bdw: Display execlists info in debugfs
  drm/i915/bdw: Disable semaphores for Execlists
  drm/i915/bdw: Make sure gpu reset still works with Execlists
  drm/i915/bdw: Don't write PDP in the legacy way when using LRCs
  drm/i915: Track cursor changes as frontbuffer tracking flushes
  drm/i915/bdw: Help out the ctx switch interrupt handler
  drm/i915/bdw: Avoid non-lite-restore preemptions
  drm/i915/bdw: Handle context switch events
  drm/i915/bdw: Two-stage execlist submit process
  drm/i915/bdw: Write the tail pointer, LRC style
  drm/i915/bdw: Implement context switching (somewhat)
  drm/i915/bdw: Emission of requests with logical rings
  ...

Conflicts:
drivers/gpu/drm/i915/i915_drv.c

13 files changed:
1  2 
Documentation/DocBook/drm.tmpl
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_params.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_pm.c
include/drm/drm_crtc.h

index 5c299fa4e01676a00025d8492903bbce12cb0275,689e3e38b9c3ea4ab7a143d18e68ae72d74138c5..58ab4d32c86fe0b30a99f30ce3f37d4d2646f3d9
@@@ -315,7 -315,7 +315,7 @@@ char *date;</synopsis
          <function>drm_dev_unregister()</function> followed by a call to
          <function>drm_dev_unref()</function>.
        </para>
 -!Edrivers/gpu/drm/drm_stub.c
 +!Edrivers/gpu/drm/drm_drv.c
      </sect2>
      <sect2>
        <title>Driver Load</title>
@@@ -3919,6 -3919,11 +3919,11 @@@ int num_ioctls;</synopsis
  !Pdrivers/gpu/drm/i915/i915_cmd_parser.c batch buffer command parser
  !Idrivers/gpu/drm/i915/i915_cmd_parser.c
        </sect2>
+       <sect2>
+         <title>Logical Rings, Logical Ring Contexts and Execlists</title>
+ !Pdrivers/gpu/drm/i915/intel_lrc.c Logical Rings, Logical Ring Contexts and Execlists
+ !Idrivers/gpu/drm/i915/intel_lrc.c
+       </sect2>
      </sect1>
    </chapter>
  </part>
index f09b75212081ae7256e00d9845c31eabc3dfc2c5,d7e4c0e2e7964f5321675cff0000fb3c8f8fcc65..7d7c1fd15443f233cc8c75f4dd729abe32c4ff8b
@@@ -45,6 -45,101 +45,6 @@@ static struct drm_framebuffer *add_fram
                                                        struct drm_mode_fb_cmd2 *r,
                                                        struct drm_file *file_priv);
  
 -/**
 - * drm_modeset_lock_all - take all modeset locks
 - * @dev: drm device
 - *
 - * This function takes all modeset locks, suitable where a more fine-grained
 - * scheme isn't (yet) implemented. Locks must be dropped with
 - * drm_modeset_unlock_all.
 - */
 -void drm_modeset_lock_all(struct drm_device *dev)
 -{
 -      struct drm_mode_config *config = &dev->mode_config;
 -      struct drm_modeset_acquire_ctx *ctx;
 -      int ret;
 -
 -      ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 -      if (WARN_ON(!ctx))
 -              return;
 -
 -      mutex_lock(&config->mutex);
 -
 -      drm_modeset_acquire_init(ctx, 0);
 -
 -retry:
 -      ret = drm_modeset_lock(&config->connection_mutex, ctx);
 -      if (ret)
 -              goto fail;
 -      ret = drm_modeset_lock_all_crtcs(dev, ctx);
 -      if (ret)
 -              goto fail;
 -
 -      WARN_ON(config->acquire_ctx);
 -
 -      /* now we hold the locks, so now that it is safe, stash the
 -       * ctx for drm_modeset_unlock_all():
 -       */
 -      config->acquire_ctx = ctx;
 -
 -      drm_warn_on_modeset_not_all_locked(dev);
 -
 -      return;
 -
 -fail:
 -      if (ret == -EDEADLK) {
 -              drm_modeset_backoff(ctx);
 -              goto retry;
 -      }
 -}
 -EXPORT_SYMBOL(drm_modeset_lock_all);
 -
 -/**
 - * drm_modeset_unlock_all - drop all modeset locks
 - * @dev: device
 - *
 - * This function drop all modeset locks taken by drm_modeset_lock_all.
 - */
 -void drm_modeset_unlock_all(struct drm_device *dev)
 -{
 -      struct drm_mode_config *config = &dev->mode_config;
 -      struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx;
 -
 -      if (WARN_ON(!ctx))
 -              return;
 -
 -      config->acquire_ctx = NULL;
 -      drm_modeset_drop_locks(ctx);
 -      drm_modeset_acquire_fini(ctx);
 -
 -      kfree(ctx);
 -
 -      mutex_unlock(&dev->mode_config.mutex);
 -}
 -EXPORT_SYMBOL(drm_modeset_unlock_all);
 -
 -/**
 - * drm_warn_on_modeset_not_all_locked - check that all modeset locks are locked
 - * @dev: device
 - *
 - * Useful as a debug assert.
 - */
 -void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)
 -{
 -      struct drm_crtc *crtc;
 -
 -      /* Locking is currently fubar in the panic handler. */
 -      if (oops_in_progress)
 -              return;
 -
 -      list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
 -              WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
 -
 -      WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
 -      WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
 -}
 -EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
 -
  /* Avoid boilerplate.  I'm tired of typing. */
  #define DRM_ENUM_NAME_FN(fnname, list)                                \
        const char *fnname(int val)                             \
@@@ -351,12 -446,8 +351,12 @@@ static struct drm_mode_object *_object_
  
        mutex_lock(&dev->mode_config.idr_mutex);
        obj = idr_find(&dev->mode_config.crtc_idr, id);
 -      if (!obj || (type != DRM_MODE_OBJECT_ANY && obj->type != type) ||
 -          (obj->id != id))
 +      if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type)
 +              obj = NULL;
 +      if (obj && obj->id != id)
 +              obj = NULL;
 +      /* don't leak out unref'd fb's */
 +      if (obj && (obj->type == DRM_MODE_OBJECT_FB))
                obj = NULL;
        mutex_unlock(&dev->mode_config.idr_mutex);
  
@@@ -383,6 -474,9 +383,6 @@@ struct drm_mode_object *drm_mode_object
         * function.*/
        WARN_ON(type == DRM_MODE_OBJECT_FB);
        obj = _object_find(dev, id, type);
 -      /* don't leak out unref'd fb's */
 -      if (obj && (obj->type == DRM_MODE_OBJECT_FB))
 -              obj = NULL;
        return obj;
  }
  EXPORT_SYMBOL(drm_mode_object_find);
@@@ -420,6 -514,9 +420,6 @@@ int drm_framebuffer_init(struct drm_dev
        if (ret)
                goto out;
  
 -      /* Grab the idr reference. */
 -      drm_framebuffer_reference(fb);
 -
        dev->mode_config.num_fb++;
        list_add(&fb->head, &dev->mode_config.fb_list);
  out:
  }
  EXPORT_SYMBOL(drm_framebuffer_init);
  
 +/* dev->mode_config.fb_lock must be held! */
 +static void __drm_framebuffer_unregister(struct drm_device *dev,
 +                                       struct drm_framebuffer *fb)
 +{
 +      mutex_lock(&dev->mode_config.idr_mutex);
 +      idr_remove(&dev->mode_config.crtc_idr, fb->base.id);
 +      mutex_unlock(&dev->mode_config.idr_mutex);
 +
 +      fb->base.id = 0;
 +}
 +
  static void drm_framebuffer_free(struct kref *kref)
  {
        struct drm_framebuffer *fb =
                        container_of(kref, struct drm_framebuffer, refcount);
 +      struct drm_device *dev = fb->dev;
 +
 +      /*
 +       * The lookup idr holds a weak reference, which has not necessarily been
 +       * removed at this point. Check for that.
 +       */
 +      mutex_lock(&dev->mode_config.fb_lock);
 +      if (fb->base.id) {
 +              /* Mark fb as reaped and drop idr ref. */
 +              __drm_framebuffer_unregister(dev, fb);
 +      }
 +      mutex_unlock(&dev->mode_config.fb_lock);
 +
        fb->funcs->destroy(fb);
  }
  
@@@ -493,10 -566,8 +493,10 @@@ struct drm_framebuffer *drm_framebuffer
  
        mutex_lock(&dev->mode_config.fb_lock);
        fb = __drm_framebuffer_lookup(dev, id);
 -      if (fb)
 -              drm_framebuffer_reference(fb);
 +      if (fb) {
 +              if (!kref_get_unless_zero(&fb->refcount))
 +                      fb = NULL;
 +      }
        mutex_unlock(&dev->mode_config.fb_lock);
  
        return fb;
@@@ -540,6 -611,19 +540,6 @@@ static void __drm_framebuffer_unreferen
        kref_put(&fb->refcount, drm_framebuffer_free_bug);
  }
  
 -/* dev->mode_config.fb_lock must be held! */
 -static void __drm_framebuffer_unregister(struct drm_device *dev,
 -                                       struct drm_framebuffer *fb)
 -{
 -      mutex_lock(&dev->mode_config.idr_mutex);
 -      idr_remove(&dev->mode_config.crtc_idr, fb->base.id);
 -      mutex_unlock(&dev->mode_config.idr_mutex);
 -
 -      fb->base.id = 0;
 -
 -      __drm_framebuffer_unreference(fb);
 -}
 -
  /**
   * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
   * @fb: fb to unregister
@@@ -767,59 -851,6 +767,59 @@@ static void drm_mode_remove(struct drm_
        drm_mode_destroy(connector->dev, mode);
  }
  
 +/**
 + * drm_connector_get_cmdline_mode - reads the user's cmdline mode
 + * @connector: connector to quwery
 + * @mode: returned mode
 + *
 + * The kernel supports per-connector configration of its consoles through
 + * use of the video= parameter. This function parses that option and
 + * extracts the user's specified mode (or enable/disable status) for a
 + * particular connector. This is typically only used during the early fbdev
 + * setup.
 + */
 +static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
 +{
 +      struct drm_cmdline_mode *mode = &connector->cmdline_mode;
 +      char *option = NULL;
 +
 +      if (fb_get_options(connector->name, &option))
 +              return;
 +
 +      if (!drm_mode_parse_command_line_for_connector(option,
 +                                                     connector,
 +                                                     mode))
 +              return;
 +
 +      if (mode->force) {
 +              const char *s;
 +
 +              switch (mode->force) {
 +              case DRM_FORCE_OFF:
 +                      s = "OFF";
 +                      break;
 +              case DRM_FORCE_ON_DIGITAL:
 +                      s = "ON - dig";
 +                      break;
 +              default:
 +              case DRM_FORCE_ON:
 +                      s = "ON";
 +                      break;
 +              }
 +
 +              DRM_INFO("forcing %s connector %s\n", connector->name, s);
 +              connector->force = mode->force;
 +      }
 +
 +      DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
 +                    connector->name,
 +                    mode->xres, mode->yres,
 +                    mode->refresh_specified ? mode->refresh : 60,
 +                    mode->rb ? " reduced blanking" : "",
 +                    mode->margins ? " with margins" : "",
 +                    mode->interlace ?  " interlaced" : "");
 +}
 +
  /**
   * drm_connector_init - Init a preallocated connector
   * @dev: DRM device
@@@ -872,8 -903,6 +872,8 @@@ int drm_connector_init(struct drm_devic
        connector->edid_blob_ptr = NULL;
        connector->status = connector_status_unknown;
  
 +      drm_connector_get_cmdline_mode(connector);
 +
        list_add_tail(&connector->head, &dev->mode_config.connector_list);
        dev->mode_config.num_connector++;
  
@@@ -926,29 -955,6 +926,29 @@@ void drm_connector_cleanup(struct drm_c
  }
  EXPORT_SYMBOL(drm_connector_cleanup);
  
 +/**
 + * drm_connector_index - find the index of a registered connector
 + * @connector: connector to find index for
 + *
 + * Given a registered connector, return the index of that connector within a DRM
 + * device's list of connectors.
 + */
 +unsigned int drm_connector_index(struct drm_connector *connector)
 +{
 +      unsigned int index = 0;
 +      struct drm_connector *tmp;
 +
 +      list_for_each_entry(tmp, &connector->dev->mode_config.connector_list, head) {
 +              if (tmp == connector)
 +                      return index;
 +
 +              index++;
 +      }
 +
 +      BUG();
 +}
 +EXPORT_SYMBOL(drm_connector_index);
 +
  /**
   * drm_connector_register - register a connector
   * @connector: the connector to register
@@@ -1253,29 -1259,6 +1253,29 @@@ void drm_plane_cleanup(struct drm_plan
  }
  EXPORT_SYMBOL(drm_plane_cleanup);
  
 +/**
 + * drm_plane_index - find the index of a registered plane
 + * @plane: plane to find index for
 + *
 + * Given a registered plane, return the index of that CRTC within a DRM
 + * device's list of planes.
 + */
 +unsigned int drm_plane_index(struct drm_plane *plane)
 +{
 +      unsigned int index = 0;
 +      struct drm_plane *tmp;
 +
 +      list_for_each_entry(tmp, &plane->dev->mode_config.plane_list, head) {
 +              if (tmp == plane)
 +                      return index;
 +
 +              index++;
 +      }
 +
 +      BUG();
 +}
 +EXPORT_SYMBOL(drm_plane_index);
 +
  /**
   * drm_plane_force_disable - Forcibly disable a plane
   * @plane: plane to disable
   */
  void drm_plane_force_disable(struct drm_plane *plane)
  {
 -      struct drm_framebuffer *old_fb = plane->fb;
        int ret;
  
 -      if (!old_fb)
 +      if (!plane->fb)
                return;
  
 +      plane->old_fb = plane->fb;
        ret = plane->funcs->disable_plane(plane);
        if (ret) {
                DRM_ERROR("failed to disable plane with busy fb\n");
 +              plane->old_fb = NULL;
                return;
        }
        /* disconnect the plane from the fb and crtc: */
 -      __drm_framebuffer_unreference(old_fb);
 +      __drm_framebuffer_unreference(plane->old_fb);
 +      plane->old_fb = NULL;
        plane->fb = NULL;
        plane->crtc = NULL;
  }
@@@ -2277,21 -2258,23 +2277,21 @@@ static int setplane_internal(struct drm
                             uint32_t src_w, uint32_t src_h)
  {
        struct drm_device *dev = plane->dev;
 -      struct drm_framebuffer *old_fb = NULL;
        int ret = 0;
        unsigned int fb_width, fb_height;
        int i;
  
 +      drm_modeset_lock_all(dev);
        /* No fb means shut it down */
        if (!fb) {
 -              drm_modeset_lock_all(dev);
 -              old_fb = plane->fb;
 +              plane->old_fb = plane->fb;
                ret = plane->funcs->disable_plane(plane);
                if (!ret) {
                        plane->crtc = NULL;
                        plane->fb = NULL;
                } else {
 -                      old_fb = NULL;
 +                      plane->old_fb = NULL;
                }
 -              drm_modeset_unlock_all(dev);
                goto out;
        }
  
                goto out;
        }
  
 -      drm_modeset_lock_all(dev);
 -      old_fb = plane->fb;
 +      plane->old_fb = plane->fb;
        ret = plane->funcs->update_plane(plane, crtc, fb,
                                         crtc_x, crtc_y, crtc_w, crtc_h,
                                         src_x, src_y, src_w, src_h);
                plane->fb = fb;
                fb = NULL;
        } else {
 -              old_fb = NULL;
 +              plane->old_fb = NULL;
        }
 -      drm_modeset_unlock_all(dev);
  
  out:
        if (fb)
                drm_framebuffer_unreference(fb);
 -      if (old_fb)
 -              drm_framebuffer_unreference(old_fb);
 +      if (plane->old_fb)
 +              drm_framebuffer_unreference(plane->old_fb);
 +      plane->old_fb = NULL;
 +      drm_modeset_unlock_all(dev);
  
        return ret;
  
@@@ -2456,7 -2439,7 +2456,7 @@@ int drm_mode_set_config_internal(struc
         * crtcs. Atomic modeset will have saner semantics ...
         */
        list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
 -              tmp->old_fb = tmp->primary->fb;
 +              tmp->primary->old_fb = tmp->primary->fb;
  
        fb = set->fb;
  
        list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
                if (tmp->primary->fb)
                        drm_framebuffer_reference(tmp->primary->fb);
 -              if (tmp->old_fb)
 -                      drm_framebuffer_unreference(tmp->old_fb);
 +              if (tmp->primary->old_fb)
 +                      drm_framebuffer_unreference(tmp->primary->old_fb);
 +              tmp->primary->old_fb = NULL;
        }
  
        return ret;
@@@ -2802,7 -2784,7 +2802,7 @@@ static int drm_mode_cursor_common(struc
        if (crtc->cursor)
                return drm_mode_cursor_universal(crtc, req, file_priv);
  
 -      drm_modeset_lock(&crtc->mutex, NULL);
 +      drm_modeset_lock_crtc(crtc);
        if (req->flags & DRM_MODE_CURSOR_BO) {
                if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
                        ret = -ENXIO;
                }
        }
  out:
 -      drm_modeset_unlock(&crtc->mutex);
 +      drm_modeset_unlock_crtc(crtc);
  
        return ret;
  
@@@ -3512,10 -3494,9 +3512,10 @@@ EXPORT_SYMBOL(drm_property_create_enum)
   * @flags: flags specifying the property type
   * @name: name of the property
   * @props: enumeration lists with property bitflags
 - * @num_values: number of pre-defined values
 + * @num_props: size of the @props array
 + * @supported_bits: bitmask of all supported enumeration values
   *
 - * This creates a new generic drm property which can then be attached to a drm
 + * This creates a new bitmask drm property which can then be attached to a drm
   * object with drm_object_attach_property. The returned property object must be
   * freed with drm_property_destroy.
   *
@@@ -4175,12 -4156,25 +4175,25 @@@ static int drm_mode_crtc_set_obj_prop(s
        return ret;
  }
  
- static int drm_mode_plane_set_obj_prop(struct drm_mode_object *obj,
-                                     struct drm_property *property,
-                                     uint64_t value)
+ /**
+  * drm_mode_plane_set_obj_prop - set the value of a property
+  * @plane: drm plane object to set property value for
+  * @property: property to set
+  * @value: value the property should be set to
+  *
+  * This functions sets a given property on a given plane object. This function
+  * calls the driver's ->set_property callback and changes the software state of
+  * the property if the callback succeeds.
+  *
+  * Returns:
+  * Zero on success, error code on failure.
+  */
+ int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
+                               struct drm_property *property,
+                               uint64_t value)
  {
        int ret = -EINVAL;
-       struct drm_plane *plane = obj_to_plane(obj);
+       struct drm_mode_object *obj = &plane->base;
  
        if (plane->funcs->set_property)
                ret = plane->funcs->set_property(plane, property, value);
  
        return ret;
  }
+ EXPORT_SYMBOL(drm_mode_plane_set_obj_prop);
  
  /**
   * drm_mode_getproperty_ioctl - get the current value of a object's property
@@@ -4327,7 -4322,8 +4341,8 @@@ int drm_mode_obj_set_property_ioctl(str
                ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value);
                break;
        case DRM_MODE_OBJECT_PLANE:
-               ret = drm_mode_plane_set_obj_prop(arg_obj, property, arg->value);
+               ret = drm_mode_plane_set_obj_prop(obj_to_plane(arg_obj),
+                                                 property, arg->value);
                break;
        }
  
@@@ -4547,7 -4543,7 +4562,7 @@@ int drm_mode_page_flip_ioctl(struct drm
  {
        struct drm_mode_crtc_page_flip *page_flip = data;
        struct drm_crtc *crtc;
 -      struct drm_framebuffer *fb = NULL, *old_fb = NULL;
 +      struct drm_framebuffer *fb = NULL;
        struct drm_pending_vblank_event *e = NULL;
        unsigned long flags;
        int ret = -EINVAL;
        if (!crtc)
                return -ENOENT;
  
 -      drm_modeset_lock(&crtc->mutex, NULL);
 +      drm_modeset_lock_crtc(crtc);
        if (crtc->primary->fb == NULL) {
                /* The framebuffer is currently unbound, presumably
                 * due to a hotplug event, that userspace has not
                        (void (*) (struct drm_pending_event *)) kfree;
        }
  
 -      old_fb = crtc->primary->fb;
 +      crtc->primary->old_fb = crtc->primary->fb;
        ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
        if (ret) {
                if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
                        kfree(e);
                }
                /* Keep the old fb, don't unref it. */
 -              old_fb = NULL;
 +              crtc->primary->old_fb = NULL;
        } else {
                /*
                 * Warn if the driver hasn't properly updated the crtc->fb
  out:
        if (fb)
                drm_framebuffer_unreference(fb);
 -      if (old_fb)
 -              drm_framebuffer_unreference(old_fb);
 -      drm_modeset_unlock(&crtc->mutex);
 +      if (crtc->primary->old_fb)
 +              drm_framebuffer_unreference(crtc->primary->old_fb);
 +      crtc->primary->old_fb = NULL;
 +      drm_modeset_unlock_crtc(crtc);
  
        return ret;
  }
  void drm_mode_config_reset(struct drm_device *dev)
  {
        struct drm_crtc *crtc;
 +      struct drm_plane *plane;
        struct drm_encoder *encoder;
        struct drm_connector *connector;
  
 +      list_for_each_entry(plane, &dev->mode_config.plane_list, head)
 +              if (plane->funcs->reset)
 +                      plane->funcs->reset(plane);
 +
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
                if (crtc->funcs->reset)
                        crtc->funcs->reset(crtc);
index 63d7b8eb6c1746654c36005f5674d51fcd50306c,99569ee5adee30fb372731dcaf7833eb057a62f1..0c0c39bac23da21a368ef94681da10b173994660
@@@ -126,7 -126,7 +126,7 @@@ int drm_fb_helper_add_one_connector(str
  
        WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
        if (fb_helper->connector_count + 1 > fb_helper->connector_info_alloc_count) {
 -              temp = krealloc(fb_helper->connector_info, sizeof(struct drm_fb_helper_connector) * (fb_helper->connector_count + 1), GFP_KERNEL);
 +              temp = krealloc(fb_helper->connector_info, sizeof(struct drm_fb_helper_connector *) * (fb_helper->connector_count + 1), GFP_KERNEL);
                if (!temp)
                        return -ENOMEM;
  
@@@ -171,6 -171,60 +171,6 @@@ int drm_fb_helper_remove_one_connector(
  }
  EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);
  
 -static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
 -{
 -      struct drm_fb_helper_connector *fb_helper_conn;
 -      int i;
 -
 -      for (i = 0; i < fb_helper->connector_count; i++) {
 -              struct drm_cmdline_mode *mode;
 -              struct drm_connector *connector;
 -              char *option = NULL;
 -
 -              fb_helper_conn = fb_helper->connector_info[i];
 -              connector = fb_helper_conn->connector;
 -              mode = &fb_helper_conn->cmdline_mode;
 -
 -              /* do something on return - turn off connector maybe */
 -              if (fb_get_options(connector->name, &option))
 -                      continue;
 -
 -              if (drm_mode_parse_command_line_for_connector(option,
 -                                                            connector,
 -                                                            mode)) {
 -                      if (mode->force) {
 -                              const char *s;
 -                              switch (mode->force) {
 -                              case DRM_FORCE_OFF:
 -                                      s = "OFF";
 -                                      break;
 -                              case DRM_FORCE_ON_DIGITAL:
 -                                      s = "ON - dig";
 -                                      break;
 -                              default:
 -                              case DRM_FORCE_ON:
 -                                      s = "ON";
 -                                      break;
 -                              }
 -
 -                              DRM_INFO("forcing %s connector %s\n",
 -                                       connector->name, s);
 -                              connector->force = mode->force;
 -                      }
 -
 -                      DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
 -                                    connector->name,
 -                                    mode->xres, mode->yres,
 -                                    mode->refresh_specified ? mode->refresh : 60,
 -                                    mode->rb ? " reduced blanking" : "",
 -                                    mode->margins ? " with margins" : "",
 -                                    mode->interlace ?  " interlaced" : "");
 -              }
 -
 -      }
 -      return 0;
 -}
 -
  static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper)
  {
        uint16_t *r_base, *g_base, *b_base;
@@@ -296,9 -350,9 +296,9 @@@ static bool restore_fbdev_mode(struct d
                        drm_plane_force_disable(plane);
  
                if (dev->mode_config.rotation_property) {
-                       drm_object_property_set_value(&plane->base,
-                                       dev->mode_config.rotation_property,
-                                       BIT(DRM_ROTATE_0));
+                       drm_mode_plane_set_obj_prop(plane,
+                                                   dev->mode_config.rotation_property,
+                                                   BIT(DRM_ROTATE_0));
                }
        }
  
@@@ -372,11 -426,11 +372,11 @@@ static bool drm_fb_helper_force_kernel_
                if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
                        continue;
  
 -              /* NOTE: we use lockless flag below to avoid grabbing other
 -               * modeset locks.  So just trylock the underlying mutex
 -               * directly:
 +              /*
 +               * NOTE: Use trylock mode to avoid deadlocks and sleeping in
 +               * panic context.
                 */
 -              if (!mutex_trylock(&dev->mode_config.mutex)) {
 +              if (__drm_modeset_lock_all(dev, true) != 0) {
                        error = true;
                        continue;
                }
                if (ret)
                        error = true;
  
 -              mutex_unlock(&dev->mode_config.mutex);
 +              drm_modeset_unlock_all(dev);
        }
        return error;
  }
@@@ -966,7 -1020,7 +966,7 @@@ static int drm_fb_helper_single_fb_prob
                struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
                struct drm_cmdline_mode *cmdline_mode;
  
 -              cmdline_mode = &fb_helper_conn->cmdline_mode;
 +              cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
  
                if (cmdline_mode->bpp_specified) {
                        switch (cmdline_mode->bpp) {
@@@ -1213,7 -1267,9 +1213,7 @@@ EXPORT_SYMBOL(drm_has_preferred_mode)
  
  static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
  {
 -      struct drm_cmdline_mode *cmdline_mode;
 -      cmdline_mode = &fb_connector->cmdline_mode;
 -      return cmdline_mode->specified;
 +      return fb_connector->connector->cmdline_mode.specified;
  }
  
  struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
        struct drm_display_mode *mode = NULL;
        bool prefer_non_interlace;
  
 -      cmdline_mode = &fb_helper_conn->cmdline_mode;
 +      cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
        if (cmdline_mode->specified == false)
                return mode;
  
@@@ -1608,6 -1664,8 +1608,6 @@@ bool drm_fb_helper_initial_config(struc
        struct drm_device *dev = fb_helper->dev;
        int count = 0;
  
 -      drm_fb_helper_parse_command_line(fb_helper);
 -
        mutex_lock(&dev->mode_config.mutex);
        count = drm_fb_helper_probe_connector_modes(fb_helper,
                                                    dev->mode_config.max_width,
index e27cdbe9d524a79dbd4168febc15de0660e82d9f,0f7a522682a56a7f9daba834008c05edd7ce8bdb..ff4db249cc7210f16169cc9d6a4c4413e9f70104
@@@ -481,6 -481,10 +481,10 @@@ bool i915_semaphore_is_enabled(struct d
        if (i915.semaphores >= 0)
                return i915.semaphores;
  
+       /* TODO: make semaphores and Execlists play nicely together */
+       if (i915.enable_execlists)
+               return false;
        /* Until we get further testing... */
        if (IS_GEN8(dev))
                return false;
        return true;
  }
  
 +void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
 +{
 +      spin_lock_irq(&dev_priv->irq_lock);
 +
 +      dev_priv->long_hpd_port_mask = 0;
 +      dev_priv->short_hpd_port_mask = 0;
 +      dev_priv->hpd_event_bits = 0;
 +
 +      spin_unlock_irq(&dev_priv->irq_lock);
 +
 +      cancel_work_sync(&dev_priv->dig_port_work);
 +      cancel_work_sync(&dev_priv->hotplug_work);
 +      cancel_delayed_work_sync(&dev_priv->hotplug_reenable_work);
 +}
 +
 +static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
 +{
 +      struct drm_device *dev = dev_priv->dev;
 +      struct drm_encoder *encoder;
 +
 +      drm_modeset_lock_all(dev);
 +      list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 +              struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
 +
 +              if (intel_encoder->suspend)
 +                      intel_encoder->suspend(intel_encoder);
 +      }
 +      drm_modeset_unlock_all(dev);
 +}
  
+ static int intel_suspend_complete(struct drm_i915_private *dev_priv);
+ static int intel_resume_prepare(struct drm_i915_private *dev_priv,
+                               bool rpm_resume);
  static int i915_drm_freeze(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
                flush_delayed_work(&dev_priv->rps.delayed_resume_work);
  
                intel_runtime_pm_disable_interrupts(dev);
 +              intel_hpd_cancel_work(dev_priv);
 +
 +              intel_suspend_encoders(dev_priv);
  
                intel_suspend_gt_powersave(dev);
  
        intel_uncore_forcewake_reset(dev, false);
        intel_opregion_fini(dev);
  
-       console_lock();
-       intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED);
-       console_unlock();
+       intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED, true);
  
        dev_priv->suspend_count++;
  
@@@ -632,30 -606,20 +638,20 @@@ int i915_suspend(struct drm_device *dev
        return 0;
  }
  
- void intel_console_resume(struct work_struct *work)
- {
-       struct drm_i915_private *dev_priv =
-               container_of(work, struct drm_i915_private,
-                            console_resume_work);
-       struct drm_device *dev = dev_priv->dev;
-       console_lock();
-       intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING);
-       console_unlock();
- }
  static int i915_drm_thaw_early(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret;
  
-       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-               hsw_disable_pc8(dev_priv);
+       ret = intel_resume_prepare(dev_priv, false);
+       if (ret)
+               DRM_ERROR("Resume prepare failed: %d,Continuing resume\n", ret);
  
        intel_uncore_early_sanitize(dev, true);
        intel_uncore_sanitize(dev);
        intel_power_domains_init_hw(dev_priv);
  
-       return 0;
+       return ret;
  }
  
  static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
  
        intel_opregion_init(dev);
  
-       /*
-        * The console lock can be pretty contented on resume due
-        * to all the printk activity.  Try to keep it out of the hot
-        * path of resume if possible.
-        */
-       if (console_trylock()) {
-               intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING);
-               console_unlock();
-       } else {
-               schedule_work(&dev_priv->console_resume_work);
-       }
+       intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING, false);
  
        mutex_lock(&dev_priv->modeset_restore_lock);
        dev_priv->modeset_restore = MODESET_DONE;
@@@ -941,6 -895,7 +927,7 @@@ static int i915_pm_suspend_late(struct 
        struct pci_dev *pdev = to_pci_dev(dev);
        struct drm_device *drm_dev = pci_get_drvdata(pdev);
        struct drm_i915_private *dev_priv = drm_dev->dev_private;
+       int ret;
  
        /*
         * We have a suspedn ordering issue with the snd-hda driver also
        if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
                return 0;
  
-       if (IS_HASWELL(drm_dev) || IS_BROADWELL(drm_dev))
-               hsw_enable_pc8(dev_priv);
+       ret = intel_suspend_complete(dev_priv);
  
-       pci_disable_device(pdev);
-       pci_set_power_state(pdev, PCI_D3hot);
+       if (ret)
+               DRM_ERROR("Suspend complete failed: %d\n", ret);
+       else {
+               pci_disable_device(pdev);
+               pci_set_power_state(pdev, PCI_D3hot);
+       }
  
-       return 0;
+       return ret;
  }
  
  static int i915_pm_resume_early(struct device *dev)
@@@ -1016,23 -974,26 +1006,26 @@@ static int i915_pm_poweroff(struct devi
        return i915_drm_freeze(drm_dev);
  }
  
- static int hsw_runtime_suspend(struct drm_i915_private *dev_priv)
+ static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
  {
        hsw_enable_pc8(dev_priv);
  
        return 0;
  }
  
- static int snb_runtime_resume(struct drm_i915_private *dev_priv)
+ static int snb_resume_prepare(struct drm_i915_private *dev_priv,
+                               bool rpm_resume)
  {
        struct drm_device *dev = dev_priv->dev;
  
-       intel_init_pch_refclk(dev);
+       if (rpm_resume)
+               intel_init_pch_refclk(dev);
  
        return 0;
  }
  
- static int hsw_runtime_resume(struct drm_i915_private *dev_priv)
+ static int hsw_resume_prepare(struct drm_i915_private *dev_priv,
+                               bool rpm_resume)
  {
        hsw_disable_pc8(dev_priv);
  
@@@ -1328,7 -1289,7 +1321,7 @@@ static void vlv_check_no_gt_access(stru
        I915_WRITE(VLV_GTLC_PW_STATUS, VLV_GTLC_ALLOWWAKEERR);
  }
  
- static int vlv_runtime_suspend(struct drm_i915_private *dev_priv)
+ static int vlv_suspend_complete(struct drm_i915_private *dev_priv)
  {
        u32 mask;
        int err;
@@@ -1368,7 -1329,8 +1361,8 @@@ err1
        return err;
  }
  
- static int vlv_runtime_resume(struct drm_i915_private *dev_priv)
+ static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
+                               bool rpm_resume)
  {
        struct drm_device *dev = dev_priv->dev;
        int err;
  
        vlv_check_no_gt_access(dev_priv);
  
-       intel_init_clock_gating(dev);
-       i915_gem_restore_fences(dev);
+       if (rpm_resume) {
+               intel_init_clock_gating(dev);
+               i915_gem_restore_fences(dev);
+       }
  
        return ret;
  }
@@@ -1409,7 -1373,9 +1405,9 @@@ static int intel_runtime_suspend(struc
        if (WARN_ON_ONCE(!(dev_priv->rps.enabled && intel_enable_rc6(dev))))
                return -ENODEV;
  
-       WARN_ON(!HAS_RUNTIME_PM(dev));
+       if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev)))
+               return -ENODEV;
        assert_force_wake_inactive(dev_priv);
  
        DRM_DEBUG_KMS("Suspending device\n");
        cancel_work_sync(&dev_priv->rps.work);
        intel_runtime_pm_disable_interrupts(dev);
  
-       if (IS_GEN6(dev)) {
-               ret = 0;
-       } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
-               ret = hsw_runtime_suspend(dev_priv);
-       } else if (IS_VALLEYVIEW(dev)) {
-               ret = vlv_runtime_suspend(dev_priv);
-       } else {
-               ret = -ENODEV;
-               WARN_ON(1);
-       }
+       ret = intel_suspend_complete(dev_priv);
        if (ret) {
                DRM_ERROR("Runtime suspend failed, disabling it (%d)\n", ret);
                intel_runtime_pm_restore_interrupts(dev);
@@@ -1487,24 -1443,15 +1475,15 @@@ static int intel_runtime_resume(struct 
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
  
-       WARN_ON(!HAS_RUNTIME_PM(dev));
+       if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev)))
+               return -ENODEV;
  
        DRM_DEBUG_KMS("Resuming device\n");
  
        intel_opregion_notify_adapter(dev, PCI_D0);
        dev_priv->pm.suspended = false;
  
-       if (IS_GEN6(dev)) {
-               ret = snb_runtime_resume(dev_priv);
-       } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
-               ret = hsw_runtime_resume(dev_priv);
-       } else if (IS_VALLEYVIEW(dev)) {
-               ret = vlv_runtime_resume(dev_priv);
-       } else {
-               WARN_ON(1);
-               ret = -ENODEV;
-       }
+       ret = intel_resume_prepare(dev_priv, true);
        /*
         * No point of rolling back things in case of an error, as the best
         * we can do is to hope that things will still work (and disable RPM).
        return ret;
  }
  
+ /*
+  * This function implements common functionality of runtime and system
+  * suspend sequence.
+  */
+ static int intel_suspend_complete(struct drm_i915_private *dev_priv)
+ {
+       struct drm_device *dev = dev_priv->dev;
+       int ret;
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+               ret = hsw_suspend_complete(dev_priv);
+       else if (IS_VALLEYVIEW(dev))
+               ret = vlv_suspend_complete(dev_priv);
+       else
+               ret = 0;
+       return ret;
+ }
+ /*
+  * This function implements common functionality of runtime and system
+  * resume sequence. Variable rpm_resume used for implementing different
+  * code paths.
+  */
+ static int intel_resume_prepare(struct drm_i915_private *dev_priv,
+                               bool rpm_resume)
+ {
+       struct drm_device *dev = dev_priv->dev;
+       int ret;
+       if (IS_GEN6(dev))
+               ret = snb_resume_prepare(dev_priv, rpm_resume);
+       else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+               ret = hsw_resume_prepare(dev_priv, rpm_resume);
+       else if (IS_VALLEYVIEW(dev))
+               ret = vlv_resume_prepare(dev_priv, rpm_resume);
+       else
+               ret = 0;
+       return ret;
+ }
  static const struct dev_pm_ops i915_pm_ops = {
        .suspend = i915_pm_suspend,
        .suspend_late = i915_pm_suspend_late,
index 0730af32afe6783e8fac7984e20c9454316777a7,d309725a7d7bcacbfb551930db9e6dc7b5f45973..bcf8783dbc2e79176dc82045e9222e395ef71490
@@@ -35,6 -35,7 +35,7 @@@
  #include "i915_reg.h"
  #include "intel_bios.h"
  #include "intel_ringbuffer.h"
+ #include "intel_lrc.h"
  #include "i915_gem_gtt.h"
  #include <linux/io-mapping.h>
  #include <linux/i2c.h>
@@@ -53,7 -54,7 +54,7 @@@
  
  #define DRIVER_NAME           "i915"
  #define DRIVER_DESC           "Intel Graphics"
- #define DRIVER_DATE           "20140808"
+ #define DRIVER_DATE           "20140822"
  
  enum pipe {
        INVALID_PIPE = -1,
@@@ -395,6 -396,7 +396,7 @@@ struct drm_i915_error_state 
                pid_t pid;
                char comm[TASK_COMM_LEN];
        } ring[I915_NUM_RINGS];
        struct drm_i915_error_buffer {
                u32 size;
                u32 name;
        } **active_bo, **pinned_bo;
  
        u32 *active_bo_count, *pinned_bo_count;
+       u32 vm_count;
  };
  
  struct intel_connector;
@@@ -558,6 -561,7 +561,7 @@@ struct intel_uncore 
  
  struct intel_device_info {
        u32 display_mmio_offset;
+       u16 device_id;
        u8 num_pipes:3;
        u8 num_sprites[I915_MAX_PIPES];
        u8 gen;
@@@ -622,13 -626,20 +626,20 @@@ struct intel_context 
        uint8_t remap_slice;
        struct drm_i915_file_private *file_priv;
        struct i915_ctx_hang_stats hang_stats;
-       struct i915_address_space *vm;
+       struct i915_hw_ppgtt *ppgtt;
  
+       /* Legacy ring buffer submission */
        struct {
                struct drm_i915_gem_object *rcs_state;
                bool initialized;
        } legacy_hw_ctx;
  
+       /* Execlists */
+       struct {
+               struct drm_i915_gem_object *state;
+               struct intel_ringbuffer *ringbuf;
+       } engine[I915_NUM_RINGS];
        struct list_head link;
  };
  
@@@ -983,7 -994,7 +994,7 @@@ struct intel_ilk_power_mgmt 
        unsigned long last_time1;
        unsigned long chipset_power;
        u64 last_count2;
 -      struct timespec last_time2;
 +      u64 last_time2;
        unsigned long gfx_power;
        u8 corr;
  
@@@ -1474,7 -1485,7 +1485,7 @@@ struct drm_i915_private 
                } hpd_mark;
        } hpd_stats[HPD_NUM_PINS];
        u32 hpd_event_bits;
 -      struct timer_list hotplug_reenable_timer;
 +      struct delayed_work hotplug_reenable_work;
  
        struct i915_fbc fbc;
        struct i915_drrs drrs;
  #ifdef CONFIG_DRM_I915_FBDEV
        /* list of fbdev register on this device */
        struct intel_fbdev *fbdev;
+       struct work_struct fbdev_suspend_work;
  #endif
  
-       /*
-        * The console may be contended at resume, but we don't
-        * want it to block on it.
-        */
-       struct work_struct console_resume_work;
        struct drm_property *broadcast_rgb_property;
        struct drm_property *force_audio_property;
  
        /* Old ums support infrastructure, same warning applies. */
        struct i915_ums_state ums;
  
+       /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */
+       struct {
+               int (*do_execbuf)(struct drm_device *dev, struct drm_file *file,
+                                 struct intel_engine_cs *ring,
+                                 struct intel_context *ctx,
+                                 struct drm_i915_gem_execbuffer2 *args,
+                                 struct list_head *vmas,
+                                 struct drm_i915_gem_object *batch_obj,
+                                 u64 exec_start, u32 flags);
+               int (*init_rings)(struct drm_device *dev);
+               void (*cleanup_ring)(struct intel_engine_cs *ring);
+               void (*stop_ring)(struct intel_engine_cs *ring);
+       } gt;
        /*
         * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
         * will be rejected. Instead look for a better place.
@@@ -1777,13 -1797,6 +1797,6 @@@ struct drm_i915_gem_object 
         * Only honoured if hardware has relevant pte bit
         */
        unsigned long gt_ro:1;
-       /*
-        * Is the GPU currently using a fence to access this buffer,
-        */
-       unsigned int pending_fenced_gpu_access:1;
-       unsigned int fenced_gpu_access:1;
        unsigned int cache_level:3;
  
        unsigned int has_aliasing_ppgtt_mapping:1;
@@@ -1987,51 -2000,63 +2000,63 @@@ struct drm_i915_cmd_table 
        int count;
  };
  
- #define INTEL_INFO(dev)       (&to_i915(dev)->info)
- #define IS_I830(dev)          ((dev)->pdev->device == 0x3577)
- #define IS_845G(dev)          ((dev)->pdev->device == 0x2562)
+ /* Note that the (struct drm_i915_private *) cast is just to shut up gcc. */
+ #define __I915__(p) ({ \
+       struct drm_i915_private *__p; \
+       if (__builtin_types_compatible_p(typeof(*p), struct drm_i915_private)) \
+               __p = (struct drm_i915_private *)p; \
+       else if (__builtin_types_compatible_p(typeof(*p), struct drm_device)) \
+               __p = to_i915((struct drm_device *)p); \
+       else \
+               BUILD_BUG(); \
+       __p; \
+ })
+ #define INTEL_INFO(p)         (&__I915__(p)->info)
+ #define INTEL_DEVID(p)        (INTEL_INFO(p)->device_id)
+ #define IS_I830(dev)          (INTEL_DEVID(dev) == 0x3577)
+ #define IS_845G(dev)          (INTEL_DEVID(dev) == 0x2562)
  #define IS_I85X(dev)          (INTEL_INFO(dev)->is_i85x)
- #define IS_I865G(dev)         ((dev)->pdev->device == 0x2572)
+ #define IS_I865G(dev)         (INTEL_DEVID(dev) == 0x2572)
  #define IS_I915G(dev)         (INTEL_INFO(dev)->is_i915g)
- #define IS_I915GM(dev)                ((dev)->pdev->device == 0x2592)
- #define IS_I945G(dev)         ((dev)->pdev->device == 0x2772)
+ #define IS_I915GM(dev)                (INTEL_DEVID(dev) == 0x2592)
+ #define IS_I945G(dev)         (INTEL_DEVID(dev) == 0x2772)
  #define IS_I945GM(dev)                (INTEL_INFO(dev)->is_i945gm)
  #define IS_BROADWATER(dev)    (INTEL_INFO(dev)->is_broadwater)
  #define IS_CRESTLINE(dev)     (INTEL_INFO(dev)->is_crestline)
- #define IS_GM45(dev)          ((dev)->pdev->device == 0x2A42)
+ #define IS_GM45(dev)          (INTEL_DEVID(dev) == 0x2A42)
  #define IS_G4X(dev)           (INTEL_INFO(dev)->is_g4x)
- #define IS_PINEVIEW_G(dev)    ((dev)->pdev->device == 0xa001)
- #define IS_PINEVIEW_M(dev)    ((dev)->pdev->device == 0xa011)
+ #define IS_PINEVIEW_G(dev)    (INTEL_DEVID(dev) == 0xa001)
+ #define IS_PINEVIEW_M(dev)    (INTEL_DEVID(dev) == 0xa011)
  #define IS_PINEVIEW(dev)      (INTEL_INFO(dev)->is_pineview)
  #define IS_G33(dev)           (INTEL_INFO(dev)->is_g33)
- #define IS_IRONLAKE_M(dev)    ((dev)->pdev->device == 0x0046)
+ #define IS_IRONLAKE_M(dev)    (INTEL_DEVID(dev) == 0x0046)
  #define IS_IVYBRIDGE(dev)     (INTEL_INFO(dev)->is_ivybridge)
- #define IS_IVB_GT1(dev)               ((dev)->pdev->device == 0x0156 || \
-                                (dev)->pdev->device == 0x0152 || \
-                                (dev)->pdev->device == 0x015a)
- #define IS_SNB_GT1(dev)               ((dev)->pdev->device == 0x0102 || \
-                                (dev)->pdev->device == 0x0106 || \
-                                (dev)->pdev->device == 0x010A)
+ #define IS_IVB_GT1(dev)               (INTEL_DEVID(dev) == 0x0156 || \
+                                INTEL_DEVID(dev) == 0x0152 || \
+                                INTEL_DEVID(dev) == 0x015a)
+ #define IS_SNB_GT1(dev)               (INTEL_DEVID(dev) == 0x0102 || \
+                                INTEL_DEVID(dev) == 0x0106 || \
+                                INTEL_DEVID(dev) == 0x010A)
  #define IS_VALLEYVIEW(dev)    (INTEL_INFO(dev)->is_valleyview)
  #define IS_CHERRYVIEW(dev)    (INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev))
  #define IS_HASWELL(dev)       (INTEL_INFO(dev)->is_haswell)
  #define IS_BROADWELL(dev)     (!INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev))
  #define IS_MOBILE(dev)                (INTEL_INFO(dev)->is_mobile)
  #define IS_HSW_EARLY_SDV(dev) (IS_HASWELL(dev) && \
-                                ((dev)->pdev->device & 0xFF00) == 0x0C00)
+                                (INTEL_DEVID(dev) & 0xFF00) == 0x0C00)
  #define IS_BDW_ULT(dev)               (IS_BROADWELL(dev) && \
-                                (((dev)->pdev->device & 0xf) == 0x2  || \
-                                ((dev)->pdev->device & 0xf) == 0x6 || \
-                                ((dev)->pdev->device & 0xf) == 0xe))
+                                ((INTEL_DEVID(dev) & 0xf) == 0x2  || \
+                                (INTEL_DEVID(dev) & 0xf) == 0x6 || \
+                                (INTEL_DEVID(dev) & 0xf) == 0xe))
  #define IS_HSW_ULT(dev)               (IS_HASWELL(dev) && \
-                                ((dev)->pdev->device & 0xFF00) == 0x0A00)
+                                (INTEL_DEVID(dev) & 0xFF00) == 0x0A00)
  #define IS_ULT(dev)           (IS_HSW_ULT(dev) || IS_BDW_ULT(dev))
  #define IS_HSW_GT3(dev)               (IS_HASWELL(dev) && \
-                                ((dev)->pdev->device & 0x00F0) == 0x0020)
+                                (INTEL_DEVID(dev) & 0x00F0) == 0x0020)
  /* ULX machines are also considered ULT. */
- #define IS_HSW_ULX(dev)               ((dev)->pdev->device == 0x0A0E || \
-                                (dev)->pdev->device == 0x0A1E)
+ #define IS_HSW_ULX(dev)               (INTEL_DEVID(dev) == 0x0A0E || \
+                                INTEL_DEVID(dev) == 0x0A1E)
  #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary)
  
  /*
  #define I915_NEED_GFX_HWS(dev)        (INTEL_INFO(dev)->need_gfx_hws)
  
  #define HAS_HW_CONTEXTS(dev)  (INTEL_INFO(dev)->gen >= 6)
+ #define HAS_LOGICAL_RING_CONTEXTS(dev)        (INTEL_INFO(dev)->gen >= 8)
  #define HAS_ALIASING_PPGTT(dev)       (INTEL_INFO(dev)->gen >= 6)
  #define HAS_PPGTT(dev)                (INTEL_INFO(dev)->gen >= 7 && !IS_GEN8(dev))
  #define USES_PPGTT(dev)               (i915.enable_ppgtt)
@@@ -2150,6 -2176,7 +2176,7 @@@ struct i915_params 
        int enable_rc6;
        int enable_fbc;
        int enable_ppgtt;
+       int enable_execlists;
        int enable_psr;
        unsigned int preliminary_hw_support;
        int disable_power_well;
@@@ -2194,10 -2221,7 +2221,8 @@@ extern unsigned long i915_mch_val(struc
  extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
  extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
  int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
 +void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
  
- extern void intel_console_resume(struct work_struct *work);
  /* i915_irq.c */
  void i915_queue_hangcheck(struct drm_device *dev);
  __printf(3, 4)
@@@ -2245,6 -2269,20 +2270,20 @@@ int i915_gem_set_domain_ioctl(struct dr
                              struct drm_file *file_priv);
  int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
                             struct drm_file *file_priv);
+ void i915_gem_execbuffer_move_to_active(struct list_head *vmas,
+                                       struct intel_engine_cs *ring);
+ void i915_gem_execbuffer_retire_commands(struct drm_device *dev,
+                                        struct drm_file *file,
+                                        struct intel_engine_cs *ring,
+                                        struct drm_i915_gem_object *obj);
+ int i915_gem_ringbuffer_submission(struct drm_device *dev,
+                                  struct drm_file *file,
+                                  struct intel_engine_cs *ring,
+                                  struct intel_context *ctx,
+                                  struct drm_i915_gem_execbuffer2 *args,
+                                  struct list_head *vmas,
+                                  struct drm_i915_gem_object *batch_obj,
+                                  u64 exec_start, u32 flags);
  int i915_gem_execbuffer(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
  int i915_gem_execbuffer2(struct drm_device *dev, void *data,
@@@ -2397,6 -2435,7 +2436,7 @@@ void i915_gem_reset(struct drm_device *
  bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force);
  int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj);
  int __must_check i915_gem_init(struct drm_device *dev);
+ int i915_gem_init_rings(struct drm_device *dev);
  int __must_check i915_gem_init_hw(struct drm_device *dev);
  int i915_gem_l3_remap(struct intel_engine_cs *ring, int slice);
  void i915_gem_init_swizzling(struct drm_device *dev);
@@@ -2467,7 -2506,7 +2507,7 @@@ static inline bool i915_gem_obj_is_pinn
  }
  
  /* Some GGTT VM helpers */
- #define obj_to_ggtt(obj) \
+ #define i915_obj_to_ggtt(obj) \
        (&((struct drm_i915_private *)(obj)->base.dev->dev_private)->gtt.base)
  static inline bool i915_is_ggtt(struct i915_address_space *vm)
  {
        return vm == ggtt;
  }
  
+ static inline struct i915_hw_ppgtt *
+ i915_vm_to_ppgtt(struct i915_address_space *vm)
+ {
+       WARN_ON(i915_is_ggtt(vm));
+       return container_of(vm, struct i915_hw_ppgtt, base);
+ }
  static inline bool i915_gem_obj_ggtt_bound(struct drm_i915_gem_object *obj)
  {
-       return i915_gem_obj_bound(obj, obj_to_ggtt(obj));
+       return i915_gem_obj_bound(obj, i915_obj_to_ggtt(obj));
  }
  
  static inline unsigned long
  i915_gem_obj_ggtt_offset(struct drm_i915_gem_object *obj)
  {
-       return i915_gem_obj_offset(obj, obj_to_ggtt(obj));
+       return i915_gem_obj_offset(obj, i915_obj_to_ggtt(obj));
  }
  
  static inline unsigned long
  i915_gem_obj_ggtt_size(struct drm_i915_gem_object *obj)
  {
-       return i915_gem_obj_size(obj, obj_to_ggtt(obj));
+       return i915_gem_obj_size(obj, i915_obj_to_ggtt(obj));
  }
  
  static inline int __must_check
@@@ -2498,7 -2546,8 +2547,8 @@@ i915_gem_obj_ggtt_pin(struct drm_i915_g
                      uint32_t alignment,
                      unsigned flags)
  {
-       return i915_gem_object_pin(obj, obj_to_ggtt(obj), alignment, flags | PIN_GLOBAL);
+       return i915_gem_object_pin(obj, i915_obj_to_ggtt(obj),
+                                  alignment, flags | PIN_GLOBAL);
  }
  
  static inline int
@@@ -2510,7 -2559,6 +2560,6 @@@ i915_gem_object_ggtt_unbind(struct drm_
  void i915_gem_object_ggtt_unpin(struct drm_i915_gem_object *obj);
  
  /* i915_gem_context.c */
- #define ctx_to_ppgtt(ctx) container_of((ctx)->vm, struct i915_hw_ppgtt, base)
  int __must_check i915_gem_context_init(struct drm_device *dev);
  void i915_gem_context_fini(struct drm_device *dev);
  void i915_gem_context_reset(struct drm_device *dev);
@@@ -2522,6 -2570,8 +2571,8 @@@ int i915_switch_context(struct intel_en
  struct intel_context *
  i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id);
  void i915_gem_context_free(struct kref *ctx_ref);
+ struct drm_i915_gem_object *
+ i915_gem_alloc_context_obj(struct drm_device *dev, size_t size);
  static inline void i915_gem_context_reference(struct intel_context *ctx)
  {
        kref_get(&ctx->ref);
index ba7f5c6bb50d1f7e5b886ea20e74ed58a9ae5247,aa4103bdd35239b049304c903433fadabe5aa75d..f1bb69377a356db36c105fdf84b615fdbe03dd23
@@@ -1149,16 -1149,16 +1149,16 @@@ static bool can_wait_boost(struct drm_i
  static int __wait_seqno(struct intel_engine_cs *ring, u32 seqno,
                        unsigned reset_counter,
                        bool interruptible,
 -                      struct timespec *timeout,
 +                      s64 *timeout,
                        struct drm_i915_file_private *file_priv)
  {
        struct drm_device *dev = ring->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        const bool irq_test_in_progress =
                ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring);
 -      struct timespec before, now;
        DEFINE_WAIT(wait);
        unsigned long timeout_expire;
 +      s64 before, now;
        int ret;
  
        WARN(!intel_irqs_enabled(dev_priv), "IRQs disabled");
        if (i915_seqno_passed(ring->get_seqno(ring, true), seqno))
                return 0;
  
 -      timeout_expire = timeout ? jiffies + timespec_to_jiffies_timeout(timeout) : 0;
 +      timeout_expire = timeout ? jiffies + nsecs_to_jiffies((u64)*timeout) : 0;
  
        if (INTEL_INFO(dev)->gen >= 6 && ring->id == RCS && can_wait_boost(file_priv)) {
                gen6_rps_boost(dev_priv);
  
        /* Record current time in case interrupted by signal, or wedged */
        trace_i915_gem_request_wait_begin(ring, seqno);
 -      getrawmonotonic(&before);
 +      before = ktime_get_raw_ns();
        for (;;) {
                struct timer_list timer;
  
                        destroy_timer_on_stack(&timer);
                }
        }
 -      getrawmonotonic(&now);
 +      now = ktime_get_raw_ns();
        trace_i915_gem_request_wait_end(ring, seqno);
  
        if (!irq_test_in_progress)
        finish_wait(&ring->irq_queue, &wait);
  
        if (timeout) {
 -              struct timespec sleep_time = timespec_sub(now, before);
 -              *timeout = timespec_sub(*timeout, sleep_time);
 -              if (!timespec_valid(timeout)) /* i.e. negative time remains */
 -                      set_normalized_timespec(timeout, 0, 0);
 +              s64 tres = *timeout - (now - before);
 +
 +              *timeout = tres < 0 ? 0 : tres;
        }
  
        return ret;
@@@ -2160,8 -2161,6 +2160,6 @@@ static voi
  i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
                               struct intel_engine_cs *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);
        list_move_tail(&obj->ring_list, &ring->active_list);
  
        obj->last_read_seqno = seqno;
-       if (obj->fenced_gpu_access) {
-               obj->last_fenced_seqno = seqno;
-               /* Bump MRU to take account of the delayed flush */
-               if (obj->fence_reg != I915_FENCE_REG_NONE) {
-                       struct drm_i915_fence_reg *reg;
-                       reg = &dev_priv->fence_regs[obj->fence_reg];
-                       list_move_tail(&reg->lru_list,
-                                      &dev_priv->mm.fence_list);
-               }
-       }
  }
  
  void i915_vma_move_to_active(struct i915_vma *vma,
@@@ -2228,7 -2214,6 +2213,6 @@@ i915_gem_object_move_to_inactive(struc
        obj->base.write_domain = 0;
  
        obj->last_fenced_seqno = 0;
-       obj->fenced_gpu_access = false;
  
        obj->active = 0;
        drm_gem_object_unreference(&obj->base);
@@@ -2326,10 -2311,21 +2310,21 @@@ int __i915_add_request(struct intel_eng
  {
        struct drm_i915_private *dev_priv = ring->dev->dev_private;
        struct drm_i915_gem_request *request;
+       struct intel_ringbuffer *ringbuf;
        u32 request_ring_position, request_start;
        int ret;
  
-       request_start = intel_ring_get_tail(ring->buffer);
+       request = ring->preallocated_lazy_request;
+       if (WARN_ON(request == NULL))
+               return -ENOMEM;
+       if (i915.enable_execlists) {
+               struct intel_context *ctx = request->ctx;
+               ringbuf = ctx->engine[ring->id].ringbuf;
+       } else
+               ringbuf = ring->buffer;
+       request_start = intel_ring_get_tail(ringbuf);
        /*
         * Emit any outstanding flushes - execbuf can fail to emit the flush
         * after having emitted the batchbuffer command. Hence we need to fix
         * is that the flush _must_ happen before the next request, no matter
         * what.
         */
-       ret = intel_ring_flush_all_caches(ring);
-       if (ret)
-               return ret;
-       request = ring->preallocated_lazy_request;
-       if (WARN_ON(request == NULL))
-               return -ENOMEM;
+       if (i915.enable_execlists) {
+               ret = logical_ring_flush_all_caches(ringbuf);
+               if (ret)
+                       return ret;
+       } else {
+               ret = intel_ring_flush_all_caches(ring);
+               if (ret)
+                       return ret;
+       }
  
        /* Record the position of the start of the request so that
         * should we detect the updated seqno part-way through the
         * GPU processing the request, we never over-estimate the
         * position of the head.
         */
-       request_ring_position = intel_ring_get_tail(ring->buffer);
+       request_ring_position = intel_ring_get_tail(ringbuf);
  
-       ret = ring->add_request(ring);
-       if (ret)
-               return ret;
+       if (i915.enable_execlists) {
+               ret = ring->emit_request(ringbuf);
+               if (ret)
+                       return ret;
+       } else {
+               ret = ring->add_request(ring);
+               if (ret)
+                       return ret;
+       }
  
        request->seqno = intel_ring_get_seqno(ring);
        request->ring = ring;
         */
        request->batch_obj = obj;
  
-       /* Hold a reference to the current context so that we can inspect
-        * it later in case a hangcheck error event fires.
-        */
-       request->ctx = ring->last_context;
-       if (request->ctx)
-               i915_gem_context_reference(request->ctx);
+       if (!i915.enable_execlists) {
+               /* Hold a reference to the current context so that we can inspect
+                * it later in case a hangcheck error event fires.
+                */
+               request->ctx = ring->last_context;
+               if (request->ctx)
+                       i915_gem_context_reference(request->ctx);
+       }
  
        request->emitted_jiffies = jiffies;
        list_add_tail(&request->list, &ring->request_list);
@@@ -2545,6 -2551,18 +2550,18 @@@ static void i915_gem_reset_ring_cleanup
                i915_gem_free_request(request);
        }
  
+       while (!list_empty(&ring->execlist_queue)) {
+               struct intel_ctx_submit_request *submit_req;
+               submit_req = list_first_entry(&ring->execlist_queue,
+                               struct intel_ctx_submit_request,
+                               execlist_link);
+               list_del(&submit_req->execlist_link);
+               intel_runtime_pm_put(dev_priv);
+               i915_gem_context_unreference(submit_req->ctx);
+               kfree(submit_req);
+       }
        /* These may not have been flush before the reset, do so now */
        kfree(ring->preallocated_lazy_request);
        ring->preallocated_lazy_request = NULL;
@@@ -2629,6 -2647,7 +2646,7 @@@ i915_gem_retire_requests_ring(struct in
  
        while (!list_empty(&ring->request_list)) {
                struct drm_i915_gem_request *request;
+               struct intel_ringbuffer *ringbuf;
  
                request = list_first_entry(&ring->request_list,
                                           struct drm_i915_gem_request,
                        break;
  
                trace_i915_gem_request_retire(ring, request->seqno);
+               /* This is one of the few common intersection points
+                * between legacy ringbuffer submission and execlists:
+                * we need to tell them apart in order to find the correct
+                * ringbuffer to which the request belongs to.
+                */
+               if (i915.enable_execlists) {
+                       struct intel_context *ctx = request->ctx;
+                       ringbuf = ctx->engine[ring->id].ringbuf;
+               } else
+                       ringbuf = ring->buffer;
                /* We know the GPU must have read the request to have
                 * sent us the seqno + interrupt, so use the position
                 * of tail of the request to update the last known position
                 * of the GPU head.
                 */
-               ring->buffer->last_retired_head = request->tail;
+               ringbuf->last_retired_head = request->tail;
  
                i915_gem_free_request(request);
        }
@@@ -2756,10 -2787,16 +2786,10 @@@ i915_gem_wait_ioctl(struct drm_device *
        struct drm_i915_gem_wait *args = data;
        struct drm_i915_gem_object *obj;
        struct intel_engine_cs *ring = NULL;
 -      struct timespec timeout_stack, *timeout = NULL;
        unsigned reset_counter;
        u32 seqno = 0;
        int ret = 0;
  
 -      if (args->timeout_ns >= 0) {
 -              timeout_stack = ns_to_timespec(args->timeout_ns);
 -              timeout = &timeout_stack;
 -      }
 -
        ret = i915_mutex_lock_interruptible(dev);
        if (ret)
                return ret;
                 goto out;
  
        /* Do this after OLR check to make sure we make forward progress polling
 -       * on this IOCTL with a 0 timeout (like busy ioctl)
 +       * on this IOCTL with a timeout <=0 (like busy ioctl)
         */
 -      if (!args->timeout_ns) {
 +      if (args->timeout_ns <= 0) {
                ret = -ETIME;
                goto out;
        }
        reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
        mutex_unlock(&dev->struct_mutex);
  
 -      ret = __wait_seqno(ring, seqno, reset_counter, true, timeout, file->driver_priv);
 -      if (timeout)
 -              args->timeout_ns = timespec_to_ns(timeout);
 -      return ret;
 +      return __wait_seqno(ring, seqno, reset_counter, true, &args->timeout_ns,
 +                          file->driver_priv);
  
  out:
        drm_gem_object_unreference(&obj->base);
@@@ -2919,9 -2958,8 +2949,8 @@@ int i915_vma_unbind(struct i915_vma *vm
        vma->unbind_vma(vma);
  
        list_del_init(&vma->mm_list);
-       /* Avoid an unnecessary call to unbind on rebind. */
        if (i915_is_ggtt(vma->vm))
-               obj->map_and_fenceable = true;
+               obj->map_and_fenceable = false;
  
        drm_mm_remove_node(&vma->node);
        i915_gem_vma_destroy(vma);
@@@ -3166,7 -3204,6 +3195,6 @@@ i915_gem_object_wait_fence(struct drm_i
                obj->last_fenced_seqno = 0;
        }
  
-       obj->fenced_gpu_access = false;
        return 0;
  }
  
@@@ -3273,6 -3310,9 +3301,9 @@@ i915_gem_object_get_fence(struct drm_i9
                        return 0;
                }
        } else if (enable) {
+               if (WARN_ON(!obj->map_and_fenceable))
+                       return -EINVAL;
                reg = i915_find_fence_reg(dev);
                if (IS_ERR(reg))
                        return PTR_ERR(reg);
  i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
  {
        struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+       struct i915_vma *vma = i915_gem_obj_to_ggtt(obj);
        uint32_t old_write_domain, old_read_domains;
        int ret;
  
        /* Not valid to be called on unbound objects. */
-       if (!i915_gem_obj_bound_any(obj))
+       if (vma == NULL)
                return -EINVAL;
  
        if (obj->base.write_domain == I915_GEM_DOMAIN_GTT)
                                            old_write_domain);
  
        /* And bump the LRU for this access */
-       if (i915_gem_object_is_inactive(obj)) {
-               struct i915_vma *vma = i915_gem_obj_to_ggtt(obj);
-               if (vma)
-                       list_move_tail(&vma->mm_list,
-                                      &dev_priv->gtt.base.inactive_list);
-       }
+       if (i915_gem_object_is_inactive(obj))
+               list_move_tail(&vma->mm_list,
+                              &dev_priv->gtt.base.inactive_list);
  
        return 0;
  }
@@@ -3799,9 -3836,6 +3827,6 @@@ static bool is_pin_display(struct drm_i
  {
        struct i915_vma *vma;
  
-       if (list_empty(&obj->vma_list))
-               return false;
        vma = i915_gem_obj_to_ggtt(obj);
        if (!vma)
                return false;
@@@ -4328,8 -4362,6 +4353,6 @@@ void i915_gem_object_init(struct drm_i9
  
        obj->fence_reg = I915_FENCE_REG_NONE;
        obj->madv = I915_MADV_WILLNEED;
-       /* Avoid an unnecessary call to unbind on the first bind. */
-       obj->map_and_fenceable = true;
  
        i915_gem_info_add_obj(obj->base.dev->dev_private, obj->base.size);
  }
@@@ -4490,12 -4522,18 +4513,18 @@@ struct i915_vma *i915_gem_obj_to_vma(st
  
  void i915_gem_vma_destroy(struct i915_vma *vma)
  {
+       struct i915_address_space *vm = NULL;
        WARN_ON(vma->node.allocated);
  
        /* Keep the vma as a placeholder in the execbuffer reservation lists */
        if (!list_empty(&vma->exec_list))
                return;
  
+       vm = vma->vm;
+       if (!i915_is_ggtt(vm))
+               i915_ppgtt_put(i915_vm_to_ppgtt(vm));
        list_del(&vma->vma_link);
  
        kfree(vma);
@@@ -4509,7 -4547,7 +4538,7 @@@ i915_gem_stop_ringbuffers(struct drm_de
        int i;
  
        for_each_ring(ring, dev_priv, i)
-               intel_stop_ring_buffer(ring);
+               dev_priv->gt.stop_ring(ring);
  }
  
  int
@@@ -4626,7 -4664,7 +4655,7 @@@ intel_enable_blt(struct drm_device *dev
        return true;
  }
  
static int i915_gem_init_rings(struct drm_device *dev)
+ int i915_gem_init_rings(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
@@@ -4709,7 -4747,7 +4738,7 @@@ i915_gem_init_hw(struct drm_device *dev
  
        i915_gem_init_swizzling(dev);
  
-       ret = i915_gem_init_rings(dev);
+       ret = dev_priv->gt.init_rings(dev);
        if (ret)
                return ret;
  
        if (ret && ret != -EIO) {
                DRM_ERROR("Context enable failed %d\n", ret);
                i915_gem_cleanup_ringbuffer(dev);
+               return ret;
+       }
+       ret = i915_ppgtt_init_hw(dev);
+       if (ret && ret != -EIO) {
+               DRM_ERROR("PPGTT enable failed %d\n", ret);
+               i915_gem_cleanup_ringbuffer(dev);
        }
  
        return ret;
@@@ -4737,6 -4783,9 +4774,9 @@@ int i915_gem_init(struct drm_device *de
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
  
+       i915.enable_execlists = intel_sanitize_enable_execlists(dev,
+                       i915.enable_execlists);
        mutex_lock(&dev->struct_mutex);
  
        if (IS_VALLEYVIEW(dev)) {
                        DRM_DEBUG_DRIVER("allow wake ack timed out\n");
        }
  
-       i915_gem_init_userptr(dev);
+       if (!i915.enable_execlists) {
+               dev_priv->gt.do_execbuf = i915_gem_ringbuffer_submission;
+               dev_priv->gt.init_rings = i915_gem_init_rings;
+               dev_priv->gt.cleanup_ring = intel_cleanup_ring_buffer;
+               dev_priv->gt.stop_ring = intel_stop_ring_buffer;
+       } else {
+               dev_priv->gt.do_execbuf = intel_execlists_submission;
+               dev_priv->gt.init_rings = intel_logical_rings_init;
+               dev_priv->gt.cleanup_ring = intel_logical_ring_cleanup;
+               dev_priv->gt.stop_ring = intel_logical_ring_stop;
+       }
+       ret = i915_gem_init_userptr(dev);
+       if (ret) {
+               mutex_unlock(&dev->struct_mutex);
+               return ret;
+       }
        i915_gem_init_global_gtt(dev);
  
        ret = i915_gem_context_init(dev);
@@@ -4782,7 -4848,7 +4839,7 @@@ i915_gem_cleanup_ringbuffer(struct drm_
        int i;
  
        for_each_ring(ring, dev_priv, i)
-               intel_cleanup_ring_buffer(ring);
+               dev_priv->gt.cleanup_ring(ring);
  }
  
  int
@@@ -5094,9 -5160,7 +5151,7 @@@ unsigned long i915_gem_obj_offset(struc
        struct drm_i915_private *dev_priv = o->base.dev->dev_private;
        struct i915_vma *vma;
  
-       if (!dev_priv->mm.aliasing_ppgtt ||
-           vm == &dev_priv->mm.aliasing_ppgtt->base)
-               vm = &dev_priv->gtt.base;
+       WARN_ON(vm == &dev_priv->mm.aliasing_ppgtt->base);
  
        list_for_each_entry(vma, &o->vma_list, vma_link) {
                if (vma->vm == vm)
@@@ -5137,9 -5201,7 +5192,7 @@@ unsigned long i915_gem_obj_size(struct 
        struct drm_i915_private *dev_priv = o->base.dev->dev_private;
        struct i915_vma *vma;
  
-       if (!dev_priv->mm.aliasing_ppgtt ||
-           vm == &dev_priv->mm.aliasing_ppgtt->base)
-               vm = &dev_priv->gtt.base;
+       WARN_ON(vm == &dev_priv->mm.aliasing_ppgtt->base);
  
        BUG_ON(list_empty(&o->vma_list));
  
@@@ -5244,14 -5306,8 +5297,8 @@@ struct i915_vma *i915_gem_obj_to_ggtt(s
  {
        struct i915_vma *vma;
  
-       /* This WARN has probably outlived its usefulness (callers already
-        * WARN if they don't find the GGTT vma they expect). When removing,
-        * remember to remove the pre-check in is_pin_display() as well */
-       if (WARN_ON(list_empty(&obj->vma_list)))
-               return NULL;
        vma = list_first_entry(&obj->vma_list, typeof(*vma), vma_link);
-       if (vma->vm != obj_to_ggtt(obj))
+       if (vma->vm != i915_obj_to_ggtt(obj))
                return NULL;
  
        return vma;
index 7ccc900eaf6ba249ab713150b598b4b13b0180e6,f5d6795887d2d99c650b4774ab547aba90e50778..8b158f02bd0fecea53a72ef45eb119cad1a256c2
@@@ -1189,8 -1189,8 +1189,8 @@@ static void i915_hotplug_work_func(stru
          * some connectors */
        if (hpd_disabled) {
                drm_kms_helper_poll_enable(dev);
 -              mod_timer(&dev_priv->hotplug_reenable_timer,
 -                        jiffies + msecs_to_jiffies(I915_REENABLE_HOTPLUG_DELAY));
 +              mod_delayed_work(system_wq, &dev_priv->hotplug_reenable_work,
 +                               msecs_to_jiffies(I915_REENABLE_HOTPLUG_DELAY));
        }
  
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
                drm_kms_helper_hotplug_event(dev);
  }
  
 -static void intel_hpd_irq_uninstall(struct drm_i915_private *dev_priv)
 -{
 -      del_timer_sync(&dev_priv->hotplug_reenable_timer);
 -}
 -
  static void ironlake_rps_change_irq_handler(struct drm_device *dev)
  {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@@ -1322,10 -1327,10 +1322,10 @@@ static u32 vlv_c0_residency(struct drm_
   * @dev_priv: DRM device private
   *
   */
- static u32 vlv_calc_delay_from_C0_counters(struct drm_i915_private *dev_priv)
+ static int vlv_calc_delay_from_C0_counters(struct drm_i915_private *dev_priv)
  {
        u32 residency_C0_up = 0, residency_C0_down = 0;
-       u8 new_delay, adj;
+       int new_delay, adj;
  
        dev_priv->rps.ei_interrupt_count++;
  
@@@ -1627,6 -1632,7 +1627,7 @@@ static irqreturn_t gen8_gt_irq_handler(
                                       struct drm_i915_private *dev_priv,
                                       u32 master_ctl)
  {
+       struct intel_engine_cs *ring;
        u32 rcs, bcs, vcs;
        uint32_t tmp = 0;
        irqreturn_t ret = IRQ_NONE;
                if (tmp) {
                        I915_WRITE(GEN8_GT_IIR(0), tmp);
                        ret = IRQ_HANDLED;
                        rcs = tmp >> GEN8_RCS_IRQ_SHIFT;
-                       bcs = tmp >> GEN8_BCS_IRQ_SHIFT;
+                       ring = &dev_priv->ring[RCS];
                        if (rcs & GT_RENDER_USER_INTERRUPT)
-                               notify_ring(dev, &dev_priv->ring[RCS]);
+                               notify_ring(dev, ring);
+                       if (rcs & GT_CONTEXT_SWITCH_INTERRUPT)
+                               intel_execlists_handle_ctx_events(ring);
+                       bcs = tmp >> GEN8_BCS_IRQ_SHIFT;
+                       ring = &dev_priv->ring[BCS];
                        if (bcs & GT_RENDER_USER_INTERRUPT)
-                               notify_ring(dev, &dev_priv->ring[BCS]);
+                               notify_ring(dev, ring);
+                       if (bcs & GT_CONTEXT_SWITCH_INTERRUPT)
+                               intel_execlists_handle_ctx_events(ring);
                } else
                        DRM_ERROR("The master control interrupt lied (GT0)!\n");
        }
                if (tmp) {
                        I915_WRITE(GEN8_GT_IIR(1), tmp);
                        ret = IRQ_HANDLED;
                        vcs = tmp >> GEN8_VCS1_IRQ_SHIFT;
+                       ring = &dev_priv->ring[VCS];
                        if (vcs & GT_RENDER_USER_INTERRUPT)
-                               notify_ring(dev, &dev_priv->ring[VCS]);
+                               notify_ring(dev, ring);
+                       if (vcs & GT_CONTEXT_SWITCH_INTERRUPT)
+                               intel_execlists_handle_ctx_events(ring);
                        vcs = tmp >> GEN8_VCS2_IRQ_SHIFT;
+                       ring = &dev_priv->ring[VCS2];
                        if (vcs & GT_RENDER_USER_INTERRUPT)
-                               notify_ring(dev, &dev_priv->ring[VCS2]);
+                               notify_ring(dev, ring);
+                       if (vcs & GT_CONTEXT_SWITCH_INTERRUPT)
+                               intel_execlists_handle_ctx_events(ring);
                } else
                        DRM_ERROR("The master control interrupt lied (GT1)!\n");
        }
                if (tmp) {
                        I915_WRITE(GEN8_GT_IIR(3), tmp);
                        ret = IRQ_HANDLED;
                        vcs = tmp >> GEN8_VECS_IRQ_SHIFT;
+                       ring = &dev_priv->ring[VECS];
                        if (vcs & GT_RENDER_USER_INTERRUPT)
-                               notify_ring(dev, &dev_priv->ring[VECS]);
+                               notify_ring(dev, ring);
+                       if (vcs & GT_CONTEXT_SWITCH_INTERRUPT)
+                               intel_execlists_handle_ctx_events(ring);
                } else
                        DRM_ERROR("The master control interrupt lied (GT3)!\n");
        }
@@@ -1772,7 -1798,9 +1793,9 @@@ static inline void intel_hpd_irq_handle
                                long_hpd = (dig_hotplug_reg >> dig_shift) & PORTB_HOTPLUG_LONG_DETECT;
                        }
  
-                       DRM_DEBUG_DRIVER("digital hpd port %d %d\n", port, long_hpd);
+                       DRM_DEBUG_DRIVER("digital hpd port %c - %s\n",
+                                        port_name(port),
+                                        long_hpd ? "long" : "short");
                        /* for long HPD pulses we want to have the digital queue happen,
                           but we still want HPD storm detection to function. */
                        if (long_hpd) {
@@@ -3781,12 -3809,17 +3804,17 @@@ static void gen8_gt_irq_postinstall(str
        /* These are interrupts we'll toggle with the ring mask register */
        uint32_t gt_interrupts[] = {
                GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
+                       GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
                        GT_RENDER_L3_PARITY_ERROR_INTERRUPT |
-                       GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT,
+                       GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT |
+                       GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT,
                GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT |
-                       GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT,
+                       GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT |
+                       GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT |
+                       GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS2_IRQ_SHIFT,
                0,
-               GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT
+               GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT |
+                       GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT
                };
  
        for (i = 0; i < ARRAY_SIZE(gt_interrupts); i++)
@@@ -3881,6 -3914,8 +3909,6 @@@ static void gen8_irq_uninstall(struct d
        if (!dev_priv)
                return;
  
 -      intel_hpd_irq_uninstall(dev_priv);
 -
        gen8_irq_reset(dev);
  }
  
@@@ -3895,6 -3930,8 +3923,6 @@@ static void valleyview_irq_uninstall(st
  
        I915_WRITE(VLV_MASTER_IER, 0);
  
 -      intel_hpd_irq_uninstall(dev_priv);
 -
        for_each_pipe(pipe)
                I915_WRITE(PIPESTAT(pipe), 0xffff);
  
@@@ -3973,6 -4010,8 +4001,6 @@@ static void ironlake_irq_uninstall(stru
        if (!dev_priv)
                return;
  
 -      intel_hpd_irq_uninstall(dev_priv);
 -
        ironlake_irq_reset(dev);
  }
  
@@@ -4343,6 -4382,8 +4371,6 @@@ static void i915_irq_uninstall(struct d
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe;
  
 -      intel_hpd_irq_uninstall(dev_priv);
 -
        if (I915_HAS_HOTPLUG(dev)) {
                I915_WRITE(PORT_HOTPLUG_EN, 0);
                I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
@@@ -4578,6 -4619,8 +4606,6 @@@ static void i965_irq_uninstall(struct d
        if (!dev_priv)
                return;
  
 -      intel_hpd_irq_uninstall(dev_priv);
 -
        I915_WRITE(PORT_HOTPLUG_EN, 0);
        I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
  
        I915_WRITE(IIR, I915_READ(IIR));
  }
  
 -static void intel_hpd_irq_reenable(unsigned long data)
 +static void intel_hpd_irq_reenable(struct work_struct *work)
  {
 -      struct drm_i915_private *dev_priv = (struct drm_i915_private *)data;
 +      struct drm_i915_private *dev_priv =
 +              container_of(work, typeof(*dev_priv),
 +                           hotplug_reenable_work.work);
        struct drm_device *dev = dev_priv->dev;
        struct drm_mode_config *mode_config = &dev->mode_config;
        unsigned long irqflags;
        int i;
  
 +      intel_runtime_pm_get(dev_priv);
 +
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
        for (i = (HPD_NONE + 1); i < HPD_NUM_PINS; i++) {
                struct drm_connector *connector;
        if (dev_priv->display.hpd_irq_setup)
                dev_priv->display.hpd_irq_setup(dev);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 +
 +      intel_runtime_pm_put(dev_priv);
  }
  
  void intel_irq_init(struct drm_device *dev)
        setup_timer(&dev_priv->gpu_error.hangcheck_timer,
                    i915_hangcheck_elapsed,
                    (unsigned long) dev);
 -      setup_timer(&dev_priv->hotplug_reenable_timer, intel_hpd_irq_reenable,
 -                  (unsigned long) dev_priv);
 +      INIT_DELAYED_WORK(&dev_priv->hotplug_reenable_work,
 +                        intel_hpd_irq_reenable);
  
        pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
  
index 7f84dd263ee8966d414341a4d6471d52ca0578c3,1dcb1bed5ef8cce143a492be9774d6d90eced581..139f490d464df8ae5ac1c400c877d3cb67b23988
@@@ -35,9 -35,10 +35,10 @@@ struct i915_params i915 __read_mostly 
        .vbt_sdvo_panel_type = -1,
        .enable_rc6 = -1,
        .enable_fbc = -1,
+       .enable_execlists = 0,
        .enable_hangcheck = true,
        .enable_ppgtt = -1,
 -      .enable_psr = 1,
 +      .enable_psr = 0,
        .preliminary_hw_support = IS_ENABLED(CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT),
        .disable_power_well = 1,
        .enable_ips = 1,
@@@ -118,8 -119,13 +119,13 @@@ MODULE_PARM_DESC(enable_ppgtt
        "Override PPGTT usage. "
        "(-1=auto [default], 0=disabled, 1=aliasing, 2=full)");
  
+ module_param_named(enable_execlists, i915.enable_execlists, int, 0400);
+ MODULE_PARM_DESC(enable_execlists,
+       "Override execlists usage. "
+       "(-1=auto, 0=disabled [default], 1=enabled)");
  module_param_named(enable_psr, i915.enable_psr, int, 0600);
 -MODULE_PARM_DESC(enable_psr, "Enable PSR (default: true)");
 +MODULE_PARM_DESC(enable_psr, "Enable PSR (default: false)");
  
  module_param_named(preliminary_hw_support, i915.preliminary_hw_support, int, 0600);
  MODULE_PARM_DESC(preliminary_hw_support,
index eab182d960f3c552839ebcfb0267f387b460f11e,b2e4eac7b70b1c87f67b9ad946c12426c4094afd..ca8592e73644e48073c91dea03fee08e5b03419a
@@@ -1797,7 -1797,7 +1797,7 @@@ static void intel_enable_shared_dpll(st
        pll->on = true;
  }
  
- void intel_disable_shared_dpll(struct intel_crtc *crtc)
static void intel_disable_shared_dpll(struct intel_crtc *crtc)
  {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@@ -2082,35 -2082,28 +2082,28 @@@ void intel_flush_primary_plane(struct d
  
  /**
   * intel_enable_primary_hw_plane - enable the primary plane on a given pipe
-  * @dev_priv: i915 private structure
-  * @plane: plane to enable
-  * @pipe: pipe being fed
+  * @plane:  plane to be enabled
+  * @crtc: crtc for the plane
   *
-  * Enable @plane on @pipe, making sure that @pipe is running first.
+  * Enable @plane on @crtc, making sure that the pipe is running first.
   */
- static void intel_enable_primary_hw_plane(struct drm_i915_private *dev_priv,
-                                         enum plane plane, enum pipe pipe)
+ static void intel_enable_primary_hw_plane(struct drm_plane *plane,
+                                         struct drm_crtc *crtc)
  {
-       struct drm_device *dev = dev_priv->dev;
-       struct intel_crtc *intel_crtc =
-               to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
-       int reg;
-       u32 val;
+       struct drm_device *dev = plane->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  
        /* If the pipe isn't enabled, we can't pump pixels and may hang */
-       assert_pipe_enabled(dev_priv, pipe);
+       assert_pipe_enabled(dev_priv, intel_crtc->pipe);
  
        if (intel_crtc->primary_enabled)
                return;
  
        intel_crtc->primary_enabled = true;
  
-       reg = DSPCNTR(plane);
-       val = I915_READ(reg);
-       WARN_ON(val & DISPLAY_PLANE_ENABLE);
-       I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE);
-       intel_flush_primary_plane(dev_priv, plane);
+       dev_priv->display.update_primary_plane(crtc, plane->fb,
+                                              crtc->x, crtc->y);
  
        /*
         * BDW signals flip done immediately if the plane
  
  /**
   * intel_disable_primary_hw_plane - disable the primary hardware plane
-  * @dev_priv: i915 private structure
-  * @plane: plane to disable
-  * @pipe: pipe consuming the data
+  * @plane: plane to be disabled
+  * @crtc: crtc for the plane
   *
-  * Disable @plane; should be an independent operation.
+  * Disable @plane on @crtc, making sure that the pipe is running first.
   */
- static void intel_disable_primary_hw_plane(struct drm_i915_private *dev_priv,
-                                          enum plane plane, enum pipe pipe)
+ static void intel_disable_primary_hw_plane(struct drm_plane *plane,
+                                          struct drm_crtc *crtc)
  {
-       struct intel_crtc *intel_crtc =
-               to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
-       int reg;
-       u32 val;
+       struct drm_device *dev = plane->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       assert_pipe_enabled(dev_priv, intel_crtc->pipe);
  
        if (!intel_crtc->primary_enabled)
                return;
  
        intel_crtc->primary_enabled = false;
  
-       reg = DSPCNTR(plane);
-       val = I915_READ(reg);
-       WARN_ON((val & DISPLAY_PLANE_ENABLE) == 0);
-       I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
-       intel_flush_primary_plane(dev_priv, plane);
+       dev_priv->display.update_primary_plane(crtc, plane->fb,
+                                              crtc->x, crtc->y);
  }
  
  static bool need_vtd_wa(struct drm_device *dev)
@@@ -2388,12 -2377,35 +2377,35 @@@ static void i9xx_update_primary_plane(s
        int plane = intel_crtc->plane;
        unsigned long linear_offset;
        u32 dspcntr;
-       u32 reg;
+       u32 reg = DSPCNTR(plane);
+       if (!intel_crtc->primary_enabled) {
+               I915_WRITE(reg, 0);
+               if (INTEL_INFO(dev)->gen >= 4)
+                       I915_WRITE(DSPSURF(plane), 0);
+               else
+                       I915_WRITE(DSPADDR(plane), 0);
+               POSTING_READ(reg);
+               return;
+       }
+       dspcntr = DISPPLANE_GAMMA_ENABLE;
+       dspcntr |= DISPLAY_PLANE_ENABLE;
+       if (INTEL_INFO(dev)->gen < 4) {
+               if (intel_crtc->pipe == PIPE_B)
+                       dspcntr |= DISPPLANE_SEL_PIPE_B;
+               /* pipesrc and dspsize control the size that is scaled from,
+                * which should always be the user's requested size.
+                */
+               I915_WRITE(DSPSIZE(plane),
+                          ((intel_crtc->config.pipe_src_h - 1) << 16) |
+                          (intel_crtc->config.pipe_src_w - 1));
+               I915_WRITE(DSPPOS(plane), 0);
+       }
  
-       reg = DSPCNTR(plane);
-       dspcntr = I915_READ(reg);
-       /* Mask out pixel format bits in case we change it */
-       dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
        switch (fb->pixel_format) {
        case DRM_FORMAT_C8:
                dspcntr |= DISPPLANE_8BPP;
                BUG();
        }
  
-       if (INTEL_INFO(dev)->gen >= 4) {
-               if (obj->tiling_mode != I915_TILING_NONE)
-                       dspcntr |= DISPPLANE_TILED;
-               else
-                       dspcntr &= ~DISPPLANE_TILED;
-       }
+       if (INTEL_INFO(dev)->gen >= 4 &&
+           obj->tiling_mode != I915_TILING_NONE)
+               dspcntr |= DISPPLANE_TILED;
  
        if (IS_G4X(dev))
                dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
@@@ -2474,12 -2483,22 +2483,22 @@@ static void ironlake_update_primary_pla
        int plane = intel_crtc->plane;
        unsigned long linear_offset;
        u32 dspcntr;
-       u32 reg;
+       u32 reg = DSPCNTR(plane);
+       if (!intel_crtc->primary_enabled) {
+               I915_WRITE(reg, 0);
+               I915_WRITE(DSPSURF(plane), 0);
+               POSTING_READ(reg);
+               return;
+       }
+       dspcntr = DISPPLANE_GAMMA_ENABLE;
+       dspcntr |= DISPLAY_PLANE_ENABLE;
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+               dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
  
-       reg = DSPCNTR(plane);
-       dspcntr = I915_READ(reg);
-       /* Mask out pixel format bits in case we change it */
-       dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
        switch (fb->pixel_format) {
        case DRM_FORMAT_C8:
                dspcntr |= DISPPLANE_8BPP;
  
        if (obj->tiling_mode != I915_TILING_NONE)
                dspcntr |= DISPPLANE_TILED;
-       else
-               dspcntr &= ~DISPPLANE_TILED;
  
-       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-               dspcntr &= ~DISPPLANE_TRICKLE_FEED_DISABLE;
-       else
+       if (!IS_HASWELL(dev) && !IS_BROADWELL(dev))
                dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
  
        I915_WRITE(reg, dspcntr);
@@@ -3873,14 -3888,12 +3888,12 @@@ static void intel_crtc_dpms_overlay(str
  static void intel_crtc_enable_planes(struct drm_crtc *crtc)
  {
        struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       int plane = intel_crtc->plane;
  
        drm_vblank_on(dev, pipe);
  
-       intel_enable_primary_hw_plane(dev_priv, plane, pipe);
+       intel_enable_primary_hw_plane(crtc->primary, crtc);
        intel_enable_planes(crtc);
        intel_crtc_update_cursor(crtc, true);
        intel_crtc_dpms_overlay(intel_crtc, true);
@@@ -3917,7 -3930,7 +3930,7 @@@ static void intel_crtc_disable_planes(s
        intel_crtc_dpms_overlay(intel_crtc, false);
        intel_crtc_update_cursor(crtc, false);
        intel_disable_planes(crtc);
-       intel_disable_primary_hw_plane(dev_priv, plane, pipe);
+       intel_disable_primary_hw_plane(crtc->primary, crtc);
  
        /*
         * FIXME: Once we grow proper nuclear flip support out of this we need
@@@ -3936,7 -3949,6 +3949,6 @@@ static void ironlake_crtc_enable(struc
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_encoder *encoder;
        int pipe = intel_crtc->pipe;
-       enum plane plane = intel_crtc->plane;
  
        WARN_ON(!crtc->enabled);
  
  
        ironlake_set_pipeconf(crtc);
  
-       /* Set up the display plane register */
-       I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE);
-       POSTING_READ(DSPCNTR(plane));
-       dev_priv->display.update_primary_plane(crtc, crtc->primary->fb,
-                                              crtc->x, crtc->y);
        intel_crtc->active = true;
  
        intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
@@@ -4049,7 -4054,6 +4054,6 @@@ static void haswell_crtc_enable(struct 
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_encoder *encoder;
        int pipe = intel_crtc->pipe;
-       enum plane plane = intel_crtc->plane;
  
        WARN_ON(!crtc->enabled);
  
  
        intel_set_pipe_csc(crtc);
  
-       /* Set up the display plane register */
-       I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE | DISPPLANE_PIPE_CSC_ENABLE);
-       POSTING_READ(DSPCNTR(plane));
-       dev_priv->display.update_primary_plane(crtc, crtc->primary->fb,
-                                              crtc->x, crtc->y);
        intel_crtc->active = true;
  
        intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
@@@ -4628,13 -4625,10 +4625,10 @@@ static void valleyview_modeset_global_r
  static void valleyview_crtc_enable(struct drm_crtc *crtc)
  {
        struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_encoder *encoder;
        int pipe = intel_crtc->pipe;
-       int plane = intel_crtc->plane;
        bool is_dsi;
-       u32 dspcntr;
  
        WARN_ON(!crtc->enabled);
  
                        vlv_prepare_pll(intel_crtc);
        }
  
-       /* Set up the display plane register */
-       dspcntr = DISPPLANE_GAMMA_ENABLE;
        if (intel_crtc->config.has_dp_encoder)
                intel_dp_set_m_n(intel_crtc);
  
        intel_set_pipe_timings(intel_crtc);
  
-       /* pipesrc and dspsize control the size that is scaled from,
-        * which should always be the user's requested size.
-        */
-       I915_WRITE(DSPSIZE(plane),
-                  ((intel_crtc->config.pipe_src_h - 1) << 16) |
-                  (intel_crtc->config.pipe_src_w - 1));
-       I915_WRITE(DSPPOS(plane), 0);
        i9xx_set_pipeconf(intel_crtc);
  
-       I915_WRITE(DSPCNTR(plane), dspcntr);
-       POSTING_READ(DSPCNTR(plane));
-       dev_priv->display.update_primary_plane(crtc, crtc->primary->fb,
-                                              crtc->x, crtc->y);
        intel_crtc->active = true;
  
        intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
@@@ -4721,12 -4698,9 +4698,9 @@@ static void i9xx_set_pll_dividers(struc
  static void i9xx_crtc_enable(struct drm_crtc *crtc)
  {
        struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_encoder *encoder;
        int pipe = intel_crtc->pipe;
-       int plane = intel_crtc->plane;
-       u32 dspcntr;
  
        WARN_ON(!crtc->enabled);
  
  
        i9xx_set_pll_dividers(intel_crtc);
  
-       /* Set up the display plane register */
-       dspcntr = DISPPLANE_GAMMA_ENABLE;
-       if (pipe == 0)
-               dspcntr &= ~DISPPLANE_SEL_PIPE_MASK;
-       else
-               dspcntr |= DISPPLANE_SEL_PIPE_B;
        if (intel_crtc->config.has_dp_encoder)
                intel_dp_set_m_n(intel_crtc);
  
        intel_set_pipe_timings(intel_crtc);
  
-       /* pipesrc and dspsize control the size that is scaled from,
-        * which should always be the user's requested size.
-        */
-       I915_WRITE(DSPSIZE(plane),
-                  ((intel_crtc->config.pipe_src_h - 1) << 16) |
-                  (intel_crtc->config.pipe_src_w - 1));
-       I915_WRITE(DSPPOS(plane), 0);
        i9xx_set_pipeconf(intel_crtc);
  
-       I915_WRITE(DSPCNTR(plane), dspcntr);
-       POSTING_READ(DSPCNTR(plane));
-       dev_priv->display.update_primary_plane(crtc, crtc->primary->fb,
-                                              crtc->x, crtc->y);
        intel_crtc->active = true;
  
        if (!IS_GEN2(dev))
@@@ -8095,74 -8047,62 +8047,62 @@@ static void i845_update_cursor(struct d
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       uint32_t cntl;
+       uint32_t cntl = 0, size = 0;
  
-       if (base != intel_crtc->cursor_base) {
-               /* On these chipsets we can only modify the base whilst
-                * the cursor is disabled.
-                */
-               if (intel_crtc->cursor_cntl) {
-                       I915_WRITE(_CURACNTR, 0);
-                       POSTING_READ(_CURACNTR);
-                       intel_crtc->cursor_cntl = 0;
+       if (base) {
+               unsigned int width = intel_crtc->cursor_width;
+               unsigned int height = intel_crtc->cursor_height;
+               unsigned int stride = roundup_pow_of_two(width) * 4;
+               switch (stride) {
+               default:
+                       WARN_ONCE(1, "Invalid cursor width/stride, width=%u, stride=%u\n",
+                                 width, stride);
+                       stride = 256;
+                       /* fallthrough */
+               case 256:
+               case 512:
+               case 1024:
+               case 2048:
+                       break;
                }
  
-               I915_WRITE(_CURABASE, base);
-               POSTING_READ(_CURABASE);
+               cntl |= CURSOR_ENABLE |
+                       CURSOR_GAMMA_ENABLE |
+                       CURSOR_FORMAT_ARGB |
+                       CURSOR_STRIDE(stride);
+               size = (height << 12) | width;
        }
  
-       /* XXX width must be 64, stride 256 => 0x00 << 28 */
-       cntl = 0;
-       if (base)
-               cntl = (CURSOR_ENABLE |
-                       CURSOR_GAMMA_ENABLE |
-                       CURSOR_FORMAT_ARGB);
-       if (intel_crtc->cursor_cntl != cntl) {
-               I915_WRITE(_CURACNTR, cntl);
+       if (intel_crtc->cursor_cntl != 0 &&
+           (intel_crtc->cursor_base != base ||
+            intel_crtc->cursor_size != size ||
+            intel_crtc->cursor_cntl != cntl)) {
+               /* On these chipsets we can only modify the base/size/stride
+                * whilst the cursor is disabled.
+                */
+               I915_WRITE(_CURACNTR, 0);
                POSTING_READ(_CURACNTR);
-               intel_crtc->cursor_cntl = cntl;
+               intel_crtc->cursor_cntl = 0;
        }
- }
  
- static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
- {
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
-       uint32_t cntl;
+       if (intel_crtc->cursor_base != base)
+               I915_WRITE(_CURABASE, base);
  
-       cntl = 0;
-       if (base) {
-               cntl = MCURSOR_GAMMA_ENABLE;
-               switch (intel_crtc->cursor_width) {
-                       case 64:
-                               cntl |= CURSOR_MODE_64_ARGB_AX;
-                               break;
-                       case 128:
-                               cntl |= CURSOR_MODE_128_ARGB_AX;
-                               break;
-                       case 256:
-                               cntl |= CURSOR_MODE_256_ARGB_AX;
-                               break;
-                       default:
-                               WARN_ON(1);
-                               return;
-               }
-               cntl |= pipe << 28; /* Connect to correct pipe */
+       if (intel_crtc->cursor_size != size) {
+               I915_WRITE(CURSIZE, size);
+               intel_crtc->cursor_size = size;
        }
        if (intel_crtc->cursor_cntl != cntl) {
-               I915_WRITE(CURCNTR(pipe), cntl);
-               POSTING_READ(CURCNTR(pipe));
+               I915_WRITE(_CURACNTR, cntl);
+               POSTING_READ(_CURACNTR);
                intel_crtc->cursor_cntl = cntl;
        }
-       /* and commit changes on next vblank */
-       I915_WRITE(CURBASE(pipe), base);
-       POSTING_READ(CURBASE(pipe));
  }
  
- static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
+ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
  {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
                                WARN_ON(1);
                                return;
                }
+               cntl |= pipe << 28; /* Connect to correct pipe */
        }
        if (IS_HASWELL(dev) || IS_BROADWELL(dev))
                cntl |= CURSOR_PIPE_CSC_ENABLE;
@@@ -8246,15 -8187,50 +8187,50 @@@ static void intel_crtc_update_cursor(st
  
        I915_WRITE(CURPOS(pipe), pos);
  
-       if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev))
-               ivb_update_cursor(crtc, base);
-       else if (IS_845G(dev) || IS_I865G(dev))
+       if (IS_845G(dev) || IS_I865G(dev))
                i845_update_cursor(crtc, base);
        else
                i9xx_update_cursor(crtc, base);
        intel_crtc->cursor_base = base;
  }
  
+ static bool cursor_size_ok(struct drm_device *dev,
+                          uint32_t width, uint32_t height)
+ {
+       if (width == 0 || height == 0)
+               return false;
+       /*
+        * 845g/865g are special in that they are only limited by
+        * the width of their cursors, the height is arbitrary up to
+        * the precision of the register. Everything else requires
+        * square cursors, limited to a few power-of-two sizes.
+        */
+       if (IS_845G(dev) || IS_I865G(dev)) {
+               if ((width & 63) != 0)
+                       return false;
+               if (width > (IS_845G(dev) ? 64 : 512))
+                       return false;
+               if (height > 1023)
+                       return false;
+       } else {
+               switch (width | height) {
+               case 256:
+               case 128:
+                       if (IS_GEN2(dev))
+                               return false;
+               case 64:
+                       break;
+               default:
+                       return false;
+               }
+       }
+       return true;
+ }
  /*
   * intel_crtc_cursor_set_obj - Set cursor to specified GEM object
   *
@@@ -8267,10 -8243,9 +8243,9 @@@ static int intel_crtc_cursor_set_obj(st
                                     uint32_t width, uint32_t height)
  {
        struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        enum pipe pipe = intel_crtc->pipe;
-       unsigned old_width;
+       unsigned old_width, stride;
        uint32_t addr;
        int ret;
  
        }
  
        /* Check for which cursor types we support */
-       if (!((width == 64 && height == 64) ||
-                       (width == 128 && height == 128 && !IS_GEN2(dev)) ||
-                       (width == 256 && height == 256 && !IS_GEN2(dev)))) {
+       if (!cursor_size_ok(dev, width, height)) {
                DRM_DEBUG("Cursor dimension not supported\n");
                return -EINVAL;
        }
  
-       if (obj->base.size < width * height * 4) {
+       stride = roundup_pow_of_two(width) * 4;
+       if (obj->base.size < stride * height) {
                DRM_DEBUG_KMS("buffer is too small\n");
                ret = -ENOMEM;
                goto fail;
                addr = obj->phys_handle->busaddr;
        }
  
-       if (IS_GEN2(dev))
-               I915_WRITE(CURSIZE, (height << 12) | width);
   finish:
        if (intel_crtc->cursor_bo) {
                if (!INTEL_INFO(dev)->cursor_needs_physical)
@@@ -8530,6 -8501,8 +8501,6 @@@ bool intel_get_load_detect_pipe(struct 
                      connector->base.id, connector->name,
                      encoder->base.id, encoder->name);
  
 -      drm_modeset_acquire_init(ctx, 0);
 -
  retry:
        ret = drm_modeset_lock(&config->connection_mutex, ctx);
        if (ret)
                i++;
                if (!(encoder->possible_crtcs & (1 << i)))
                        continue;
 -              if (!possible_crtc->enabled) {
 -                      crtc = possible_crtc;
 -                      break;
 -              }
 +              if (possible_crtc->enabled)
 +                      continue;
 +              /* This can occur when applying the pipe A quirk on resume. */
 +              if (to_intel_crtc(possible_crtc)->new_enabled)
 +                      continue;
 +
 +              crtc = possible_crtc;
 +              break;
        }
  
        /*
@@@ -8644,11 -8613,15 +8615,11 @@@ fail_unlock
                goto retry;
        }
  
 -      drm_modeset_drop_locks(ctx);
 -      drm_modeset_acquire_fini(ctx);
 -
        return false;
  }
  
  void intel_release_load_detect_pipe(struct drm_connector *connector,
 -                                  struct intel_load_detect_pipe *old,
 -                                  struct drm_modeset_acquire_ctx *ctx)
 +                                  struct intel_load_detect_pipe *old)
  {
        struct intel_encoder *intel_encoder =
                intel_attached_encoder(connector);
                        drm_framebuffer_unreference(old->release_fb);
                }
  
 -              goto unlock;
                return;
        }
  
        /* Switch crtc and encoder back off if necessary */
        if (old->dpms_mode != DRM_MODE_DPMS_ON)
                connector->funcs->dpms(connector, old->dpms_mode);
 -
 -unlock:
 -      drm_modeset_drop_locks(ctx);
 -      drm_modeset_acquire_fini(ctx);
  }
  
  static int i9xx_pll_refclk(struct drm_device *dev,
@@@ -9577,6 -9555,8 +9548,8 @@@ static bool use_mmio_flip(struct intel_
                return false;
        else if (i915.use_mmio_flip > 0)
                return true;
+       else if (i915.enable_execlists)
+               return true;
        else
                return ring != obj->ring;
  }
@@@ -11380,7 -11360,6 +11353,6 @@@ static int intel_crtc_set_config(struc
                ret = intel_set_mode(set->crtc, set->mode,
                                     set->x, set->y, set->fb);
        } else if (config->fb_changed) {
-               struct drm_i915_private *dev_priv = dev->dev_private;
                struct intel_crtc *intel_crtc = to_intel_crtc(set->crtc);
  
                intel_crtc_wait_for_pending_flips(set->crtc);
                 */
                if (!intel_crtc->primary_enabled && ret == 0) {
                        WARN_ON(!intel_crtc->active);
-                       intel_enable_primary_hw_plane(dev_priv, intel_crtc->plane,
-                                                     intel_crtc->pipe);
+                       intel_enable_primary_hw_plane(set->crtc->primary, set->crtc);
                }
  
                /*
@@@ -11548,8 -11526,6 +11519,6 @@@ static in
  intel_primary_plane_disable(struct drm_plane *plane)
  {
        struct drm_device *dev = plane->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_plane *intel_plane = to_intel_plane(plane);
        struct intel_crtc *intel_crtc;
  
        if (!plane->fb)
                goto disable_unpin;
  
        intel_crtc_wait_for_pending_flips(plane->crtc);
-       intel_disable_primary_hw_plane(dev_priv, intel_plane->plane,
-                                      intel_plane->pipe);
+       intel_disable_primary_hw_plane(plane, plane->crtc);
  disable_unpin:
        mutex_lock(&dev->struct_mutex);
        i915_gem_track_fb(intel_fb_obj(plane->fb), NULL,
@@@ -11593,9 -11569,7 +11562,7 @@@ intel_primary_plane_setplane(struct drm
                             uint32_t src_w, uint32_t src_h)
  {
        struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct intel_plane *intel_plane = to_intel_plane(plane);
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
        struct drm_rect dest = {
                                  INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe));
  
                if (intel_crtc->primary_enabled)
-                       intel_disable_primary_hw_plane(dev_priv,
-                                                      intel_plane->plane,
-                                                      intel_plane->pipe);
+                       intel_disable_primary_hw_plane(plane, crtc);
  
  
                if (plane->fb != fb)
                return ret;
  
        if (!intel_crtc->primary_enabled)
-               intel_enable_primary_hw_plane(dev_priv, intel_crtc->plane,
-                                             intel_crtc->pipe);
+               intel_enable_primary_hw_plane(plane, crtc);
  
        return 0;
  }
@@@ -11811,6 -11782,10 +11775,10 @@@ intel_cursor_plane_update(struct drm_pl
                return intel_crtc_cursor_set_obj(crtc, obj, crtc_w, crtc_h);
        } else {
                intel_crtc_update_cursor(crtc, visible);
+               intel_frontbuffer_flip(crtc->dev,
+                                      INTEL_FRONTBUFFER_CURSOR(intel_crtc->pipe));
                return 0;
        }
  }
@@@ -11887,6 -11862,7 +11855,7 @@@ static void intel_crtc_init(struct drm_
  
        intel_crtc->cursor_base = ~0;
        intel_crtc->cursor_cntl = ~0;
+       intel_crtc->cursor_size = ~0;
  
        BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
               dev_priv->plane_to_crtc_mapping[intel_crtc->plane] != NULL);
@@@ -12404,29 -12380,27 +12373,27 @@@ static void intel_init_display(struct d
                dev_priv->display.get_display_clock_speed =
                        i830_get_display_clock_speed;
  
-       if (HAS_PCH_SPLIT(dev)) {
-               if (IS_GEN5(dev)) {
-                       dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
-                       dev_priv->display.write_eld = ironlake_write_eld;
-               } else if (IS_GEN6(dev)) {
-                       dev_priv->display.fdi_link_train = gen6_fdi_link_train;
-                       dev_priv->display.write_eld = ironlake_write_eld;
-                       dev_priv->display.modeset_global_resources =
-                               snb_modeset_global_resources;
-               } else if (IS_IVYBRIDGE(dev)) {
-                       /* FIXME: detect B0+ stepping and use auto training */
-                       dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
-                       dev_priv->display.write_eld = ironlake_write_eld;
-                       dev_priv->display.modeset_global_resources =
-                               ivb_modeset_global_resources;
-               } else if (IS_HASWELL(dev) || IS_GEN8(dev)) {
-                       dev_priv->display.fdi_link_train = hsw_fdi_link_train;
-                       dev_priv->display.write_eld = haswell_write_eld;
-                       dev_priv->display.modeset_global_resources =
-                               haswell_modeset_global_resources;
-               }
-       } else if (IS_G4X(dev)) {
+       if (IS_G4X(dev)) {
                dev_priv->display.write_eld = g4x_write_eld;
+       } else if (IS_GEN5(dev)) {
+               dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
+               dev_priv->display.write_eld = ironlake_write_eld;
+       } else if (IS_GEN6(dev)) {
+               dev_priv->display.fdi_link_train = gen6_fdi_link_train;
+               dev_priv->display.write_eld = ironlake_write_eld;
+               dev_priv->display.modeset_global_resources =
+                       snb_modeset_global_resources;
+       } else if (IS_IVYBRIDGE(dev)) {
+               /* FIXME: detect B0+ stepping and use auto training */
+               dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
+               dev_priv->display.write_eld = ironlake_write_eld;
+               dev_priv->display.modeset_global_resources =
+                       ivb_modeset_global_resources;
+       } else if (IS_HASWELL(dev) || IS_GEN8(dev)) {
+               dev_priv->display.fdi_link_train = hsw_fdi_link_train;
+               dev_priv->display.write_eld = haswell_write_eld;
+               dev_priv->display.modeset_global_resources =
+                       haswell_modeset_global_resources;
        } else if (IS_VALLEYVIEW(dev)) {
                dev_priv->display.modeset_global_resources =
                        valleyview_modeset_global_resources;
@@@ -12677,7 -12651,10 +12644,10 @@@ void intel_modeset_init(struct drm_devi
                dev->mode_config.max_height = 8192;
        }
  
-       if (IS_GEN2(dev)) {
+       if (IS_845G(dev) || IS_I865G(dev)) {
+               dev->mode_config.cursor_width = IS_845G(dev) ? 64 : 512;
+               dev->mode_config.cursor_height = 1023;
+       } else if (IS_GEN2(dev)) {
                dev->mode_config.cursor_width = GEN2_CURSOR_WIDTH;
                dev->mode_config.cursor_height = GEN2_CURSOR_HEIGHT;
        } else {
@@@ -12744,7 -12721,7 +12714,7 @@@ static void intel_enable_pipe_a(struct 
        struct intel_connector *connector;
        struct drm_connector *crt = NULL;
        struct intel_load_detect_pipe load_detect_temp;
 -      struct drm_modeset_acquire_ctx ctx;
 +      struct drm_modeset_acquire_ctx *ctx = dev->mode_config.acquire_ctx;
  
        /* We can't just switch on the pipe A, we need to set things up with a
         * proper mode and output configuration. As a gross hack, enable pipe A
        if (!crt)
                return;
  
 -      if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, &ctx))
 -              intel_release_load_detect_pipe(crt, &load_detect_temp, &ctx);
 -
 -
 +      if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, ctx))
 +              intel_release_load_detect_pipe(crt, &load_detect_temp);
  }
  
  static bool
@@@ -13193,7 -13172,7 +13163,7 @@@ void intel_modeset_cleanup(struct drm_d
         * experience fancy races otherwise.
         */
        drm_irq_uninstall(dev);
 -      cancel_work_sync(&dev_priv->hotplug_work);
 +      intel_hpd_cancel_work(dev_priv);
        dev_priv->pm._irqs_disabled = true;
  
        /*
index 6db84bf0a92a2ca1d8b84f6adfae00ed30d38f3b,def55cdfef2547066b4e1c2a46ae79c9564cf453..6a2256cf1f2a294aa9e42e0fd8ac66af222e0f16
@@@ -3540,22 -3540,17 +3540,22 @@@ go_again
  void
  intel_dp_check_link_status(struct intel_dp *intel_dp)
  {
 +      struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
        u8 sink_irq_vector;
        u8 link_status[DP_LINK_STATUS_SIZE];
  
 -      /* FIXME: This access isn't protected by any locks. */
 +      WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
 +
        if (!intel_encoder->connectors_active)
                return;
  
        if (WARN_ON(!intel_encoder->base.crtc))
                return;
  
 +      if (!to_intel_crtc(intel_encoder->base.crtc)->active)
 +              return;
 +
        /* Try to read receiver status if the link appears to be up */
        if (!intel_dp_get_link_status(intel_dp, link_status)) {
                return;
@@@ -4006,16 -4001,6 +4006,16 @@@ void intel_dp_encoder_destroy(struct dr
        kfree(intel_dig_port);
  }
  
 +static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
 +{
 +      struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
 +
 +      if (!is_edp(intel_dp))
 +              return;
 +
 +      edp_panel_vdd_off_sync(intel_dp);
 +}
 +
  static void intel_dp_encoder_reset(struct drm_encoder *encoder)
  {
        intel_edp_panel_vdd_sanitize(to_intel_encoder(encoder));
  intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
  {
        struct intel_dp *intel_dp = &intel_dig_port->dp;
 +      struct intel_encoder *intel_encoder = &intel_dig_port->base;
        struct drm_device *dev = intel_dig_port->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 -      int ret;
 +      enum intel_display_power_domain power_domain;
 +      bool ret = true;
 +
        if (intel_dig_port->base.type != INTEL_OUTPUT_EDP)
                intel_dig_port->base.type = INTEL_OUTPUT_DISPLAYPORT;
  
-       DRM_DEBUG_KMS("got hpd irq on port %d - %s\n", intel_dig_port->port,
+       DRM_DEBUG_KMS("got hpd irq on port %c - %s\n",
+                     port_name(intel_dig_port->port),
                      long_hpd ? "long" : "short");
  
 +      power_domain = intel_display_port_power_domain(intel_encoder);
 +      intel_display_power_get(dev_priv, power_domain);
 +
        if (long_hpd) {
                if (!ibx_digital_port_connected(dev_priv, intel_dig_port))
                        goto mst_fail;
  
        } else {
                if (intel_dp->is_mst) {
 -                      ret = intel_dp_check_mst_status(intel_dp);
 -                      if (ret == -EINVAL)
 +                      if (intel_dp_check_mst_status(intel_dp) == -EINVAL)
                                goto mst_fail;
                }
  
                         * we'll check the link status via the normal hot plug path later -
                         * but for short hpds we should check it now
                         */
 +                      drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
                        intel_dp_check_link_status(intel_dp);
 +                      drm_modeset_unlock(&dev->mode_config.connection_mutex);
                }
        }
 -      return false;
 +      ret = false;
 +      goto put_power;
  mst_fail:
        /* if we were in MST mode, and device is not there get out of MST mode */
        if (intel_dp->is_mst) {
                intel_dp->is_mst = false;
                drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
        }
 -      return true;
 +put_power:
 +      intel_display_power_put(dev_priv, power_domain);
 +
 +      return ret;
  }
  
  /* Return which DP Port should be selected for Transcoder DP control */
@@@ -4744,7 -4719,6 +4745,7 @@@ intel_dp_init(struct drm_device *dev, i
        intel_encoder->disable = intel_disable_dp;
        intel_encoder->get_hw_state = intel_dp_get_hw_state;
        intel_encoder->get_config = intel_dp_get_config;
 +      intel_encoder->suspend = intel_dp_encoder_suspend;
        if (IS_CHERRYVIEW(dev)) {
                intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable;
                intel_encoder->pre_enable = chv_pre_enable_dp;
index 70cddaf29ae36636e583dbf2ec5df20d080a74b5,4ab0d928b819cbdd91f03a9cd95d2e1290006fc9..d683a2090249d2be5a91a0c61ae1289be5fe229b
@@@ -153,12 -153,6 +153,12 @@@ struct intel_encoder 
         * be set correctly before calling this function. */
        void (*get_config)(struct intel_encoder *,
                           struct intel_crtc_config *pipe_config);
 +      /*
 +       * Called during system suspend after all pending requests for the
 +       * encoder are flushed (for example for DP AUX transactions) and
 +       * device interrupts are disabled.
 +       */
 +      void (*suspend)(struct intel_encoder *);
        int crtc_mask;
        enum hpd_pin hpd_pin;
  };
@@@ -411,6 -405,7 +411,7 @@@ struct intel_crtc 
        uint32_t cursor_addr;
        int16_t cursor_width, cursor_height;
        uint32_t cursor_cntl;
+       uint32_t cursor_size;
        uint32_t cursor_base;
  
        struct intel_plane_config plane_config;
@@@ -836,7 -831,8 +837,7 @@@ bool intel_get_load_detect_pipe(struct 
                                struct intel_load_detect_pipe *old,
                                struct drm_modeset_acquire_ctx *ctx);
  void intel_release_load_detect_pipe(struct drm_connector *connector,
 -                                  struct intel_load_detect_pipe *old,
 -                                  struct drm_modeset_acquire_ctx *ctx);
 +                                  struct intel_load_detect_pipe *old);
  int intel_pin_and_fence_fb_obj(struct drm_device *dev,
                               struct drm_i915_gem_object *obj,
                               struct intel_engine_cs *pipelined);
@@@ -952,7 -948,7 +953,7 @@@ void intel_dvo_init(struct drm_device *
  extern int intel_fbdev_init(struct drm_device *dev);
  extern void intel_fbdev_initial_config(struct drm_device *dev);
  extern void intel_fbdev_fini(struct drm_device *dev);
- extern void intel_fbdev_set_suspend(struct drm_device *dev, int state);
+ extern void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous);
  extern void intel_fbdev_output_poll_changed(struct drm_device *dev);
  extern void intel_fbdev_restore_mode(struct drm_device *dev);
  #else
@@@ -969,7 -965,7 +970,7 @@@ static inline void intel_fbdev_fini(str
  {
  }
  
- static inline void intel_fbdev_set_suspend(struct drm_device *dev, int state)
+ static inline void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
  {
  }
  
index 020e9ab567ed93d7caa261b2dc6bac3e0af52dcd,12f4e143328ce071c75ee512942bfec2c847b3e4..c8f744c418f0082ef0c7eeea12c3323e83e03e60
@@@ -3154,7 -3154,7 +3154,7 @@@ static void ironlake_enable_drps(struc
                I915_READ(0x112e0);
        dev_priv->ips.last_time1 = jiffies_to_msecs(jiffies);
        dev_priv->ips.last_count2 = I915_READ(0x112f4);
 -      getrawmonotonic(&dev_priv->ips.last_time2);
 +      dev_priv->ips.last_time2 = ktime_get_raw_ns();
  
        spin_unlock_irq(&mchdev_lock);
  }
@@@ -3719,7 -3719,6 +3719,6 @@@ static void gen6_enable_rps(struct drm_
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_engine_cs *ring;
        u32 rp_state_cap;
-       u32 gt_perf_status;
        u32 rc6vids, pcu_mbox = 0, rc6_mask = 0;
        u32 gtfifodbg;
        int rc6_mode;
        gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
  
        rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
-       gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
  
        parse_rp_state_cap(dev_priv, rp_state_cap);
  
@@@ -4715,16 -4713,18 +4713,16 @@@ static u16 pvid_to_extvid(struct drm_i9
  
  static void __i915_update_gfx_val(struct drm_i915_private *dev_priv)
  {
 -      struct timespec now, diff1;
 -      u64 diff;
 -      unsigned long diffms;
 +      u64 now, diff, diffms;
        u32 count;
  
        assert_spin_locked(&mchdev_lock);
  
 -      getrawmonotonic(&now);
 -      diff1 = timespec_sub(now, dev_priv->ips.last_time2);
 +      now = ktime_get_raw_ns();
 +      diffms = now - dev_priv->ips.last_time2;
 +      do_div(diffms, NSEC_PER_MSEC);
  
        /* Don't divide by 0 */
 -      diffms = diff1.tv_sec * 1000 + diff1.tv_nsec / 1000000;
        if (!diffms)
                return;
  
diff --combined include/drm/drm_crtc.h
index 0375d75552f18275e31ffc67225f8c91a4d321dd,38fae5d9ad7356df56fc22db2fe0e11a72f7692e..31344bf7887ee53a5c057c63051f74653569fd90
@@@ -218,6 -218,10 +218,6 @@@ struct drm_property 
        struct list_head enum_blob_list;
  };
  
 -void drm_modeset_lock_all(struct drm_device *dev);
 -void drm_modeset_unlock_all(struct drm_device *dev);
 -void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
 -
  struct drm_crtc;
  struct drm_connector;
  struct drm_encoder;
@@@ -341,6 -345,10 +341,6 @@@ struct drm_crtc 
        int cursor_x;
        int cursor_y;
  
 -      /* Temporary tracking of the old fb while a modeset is ongoing. Used
 -       * by drm_mode_set_config_internal to implement correct refcounting. */
 -      struct drm_framebuffer *old_fb;
 -
        bool enabled;
  
        /* Requested mode from modesetting. */
        void *helper_private;
  
        struct drm_object_properties properties;
 +
 +      /*
 +       * For legacy crtc ioctls so that atomic drivers can get at the locking
 +       * acquire context.
 +       */
 +      struct drm_modeset_acquire_ctx *acquire_ctx;
  };
  
  
@@@ -546,7 -548,6 +546,7 @@@ struct drm_connector 
        void *helper_private;
  
        /* forced on connector */
 +      struct drm_cmdline_mode cmdline_mode;
        enum drm_connector_force force;
        bool override_edid;
        uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
@@@ -581,7 -582,6 +581,7 @@@ struct drm_plane_funcs 
                            uint32_t src_w, uint32_t src_h);
        int (*disable_plane)(struct drm_plane *plane);
        void (*destroy)(struct drm_plane *plane);
 +      void (*reset)(struct drm_plane *plane);
  
        int (*set_property)(struct drm_plane *plane,
                            struct drm_property *property, uint64_t val);
@@@ -620,10 -620,6 +620,10 @@@ struct drm_plane 
        struct drm_crtc *crtc;
        struct drm_framebuffer *fb;
  
 +      /* Temporary tracking of the old fb while a modeset is ongoing. Used
 +       * by drm_mode_set_config_internal to implement correct refcounting. */
 +      struct drm_framebuffer *old_fb;
 +
        const struct drm_plane_funcs *funcs;
  
        struct drm_object_properties properties;
@@@ -908,7 -904,6 +908,7 @@@ int drm_connector_register(struct drm_c
  void drm_connector_unregister(struct drm_connector *connector);
  
  extern void drm_connector_cleanup(struct drm_connector *connector);
 +extern unsigned int drm_connector_index(struct drm_connector *connector);
  /* helper to unplug all connectors from sysfs for device */
  extern void drm_connector_unplug_all(struct drm_device *dev);
  
@@@ -948,7 -943,6 +948,7 @@@ extern int drm_plane_init(struct drm_de
                          const uint32_t *formats, uint32_t format_count,
                          bool is_primary);
  extern void drm_plane_cleanup(struct drm_plane *plane);
 +extern unsigned int drm_plane_index(struct drm_plane *plane);
  extern void drm_plane_force_disable(struct drm_plane *plane);
  extern int drm_crtc_check_viewport(const struct drm_crtc *crtc,
                                   int x, int y,
@@@ -1127,6 -1121,9 +1127,9 @@@ extern int drm_mode_obj_get_properties_
                                             struct drm_file *file_priv);
  extern int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
                                           struct drm_file *file_priv);
+ extern int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
+                                      struct drm_property *property,
+                                      uint64_t value);
  
  extern void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
                                 int *bpp);