Merge tag 'topic/drm-misc-2016-02-08' of git://anongit.freedesktop.org/drm-intel into drm-next

First drm-misc pull req for 4.6. Big one is the drm_event cleanup, which
is also prep work for adding android fence support to kms (Gustavo is
planning to do that). Otherwise random small bits all over.

* tag 'topic/drm-misc-2016-02-08' of git://anongit.freedesktop.org/drm-intel: (33 commits)
  gma500: clean up an excessive and confusing helper
  drm/gma500: remove helper function
  drm/vmwgfx: Nuke preclose hook
  drm/vc4: Nuke preclose hook
  drm/tilcdc: Nuke preclose hook
  drm/tegra: Stop cancelling page flip events
  drm/shmob: Nuke preclose hook
  drm/rcar: Nuke preclose hook
  drm/omap: Nuke close hooks
  drm/msm: Nuke preclose hooks
  drm/imx: Unconfuse preclose logic
  drm/exynos: Remove event cancelling from postclose
  drm/atmel: Nuke preclose
  drm/i915: Nuke intel_modeset_preclose
  drm: Nuke vblank event file cleanup code
  drm: Clean up pending events in the core
  drm/vblank: Use drm_event_reserve_init
  drm/vmwgfx: fix a NULL dereference
  drm/crtc-helper: Add caveat to disable_unused_functions doc
  drm/gma500: Remove empty preclose hook
  ...
This commit is contained in:
Dave Airlie 2016-02-09 10:39:11 +10:00
commit 316e376b65
54 changed files with 396 additions and 667 deletions

View File

@ -2886,52 +2886,8 @@ void (*postclose) (struct drm_device *, struct drm_file *);</synopsis>
</sect2> </sect2>
<sect2> <sect2>
<title>File Operations</title> <title>File Operations</title>
<synopsis>const struct file_operations *fops</synopsis> !Pdrivers/gpu/drm/drm_fops.c file operations
<abstract>File operations for the DRM device node.</abstract> !Edrivers/gpu/drm/drm_fops.c
<para>
Drivers must define the file operations structure that forms the DRM
userspace API entry point, even though most of those operations are
implemented in the DRM core. The <methodname>open</methodname>,
<methodname>release</methodname> and <methodname>ioctl</methodname>
operations are handled by
<programlisting>
.owner = THIS_MODULE,
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = drm_compat_ioctl,
#endif
</programlisting>
</para>
<para>
Drivers that implement private ioctls that requires 32/64bit
compatibility support must provide their own
<methodname>compat_ioctl</methodname> handler that processes private
ioctls and calls <function>drm_compat_ioctl</function> for core ioctls.
</para>
<para>
The <methodname>read</methodname> and <methodname>poll</methodname>
operations provide support for reading DRM events and polling them. They
are implemented by
<programlisting>
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
</programlisting>
</para>
<para>
The memory mapping implementation varies depending on how the driver
manages memory. Pre-GEM drivers will use <function>drm_mmap</function>,
while GEM-aware drivers will use <function>drm_gem_mmap</function>. See
<xref linkend="drm-gem"/>.
<programlisting>
.mmap = drm_gem_mmap,
</programlisting>
</para>
<para>
No other file operation is supported by the DRM API.
</para>
</sect2> </sect2>
<sect2> <sect2>
<title>IOCTLs</title> <title>IOCTLs</title>

View File

@ -188,9 +188,6 @@ static const struct file_operations armada_drm_fops = {
static struct drm_driver armada_drm_driver = { static struct drm_driver armada_drm_driver = {
.load = armada_drm_load, .load = armada_drm_load,
.open = NULL,
.preclose = NULL,
.postclose = NULL,
.lastclose = armada_drm_lastclose, .lastclose = armada_drm_lastclose,
.unload = armada_drm_unload, .unload = armada_drm_unload,
.set_busid = drm_platform_set_busid, .set_busid = drm_platform_set_busid,

View File

@ -280,24 +280,6 @@ static void atmel_hlcdc_crtc_destroy(struct drm_crtc *c)
kfree(crtc); kfree(crtc);
} }
void atmel_hlcdc_crtc_cancel_page_flip(struct drm_crtc *c,
struct drm_file *file)
{
struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
struct drm_pending_vblank_event *event;
struct drm_device *dev = c->dev;
unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags);
event = crtc->event;
if (event && event->base.file_priv == file) {
event->base.destroy(&event->base);
drm_vblank_put(dev, crtc->id);
crtc->event = NULL;
}
spin_unlock_irqrestore(&dev->event_lock, flags);
}
static void atmel_hlcdc_crtc_finish_page_flip(struct atmel_hlcdc_crtc *crtc) static void atmel_hlcdc_crtc_finish_page_flip(struct atmel_hlcdc_crtc *crtc)
{ {
struct drm_device *dev = crtc->base.dev; struct drm_device *dev = crtc->base.dev;

View File

@ -619,15 +619,6 @@ static void atmel_hlcdc_dc_connector_unplug_all(struct drm_device *dev)
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
} }
static void atmel_hlcdc_dc_preclose(struct drm_device *dev,
struct drm_file *file)
{
struct drm_crtc *crtc;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
atmel_hlcdc_crtc_cancel_page_flip(crtc, file);
}
static void atmel_hlcdc_dc_lastclose(struct drm_device *dev) static void atmel_hlcdc_dc_lastclose(struct drm_device *dev)
{ {
struct atmel_hlcdc_dc *dc = dev->dev_private; struct atmel_hlcdc_dc *dc = dev->dev_private;
@ -698,7 +689,6 @@ static struct drm_driver atmel_hlcdc_dc_driver = {
.driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM |
DRIVER_MODESET | DRIVER_PRIME | DRIVER_MODESET | DRIVER_PRIME |
DRIVER_ATOMIC, DRIVER_ATOMIC,
.preclose = atmel_hlcdc_dc_preclose,
.lastclose = atmel_hlcdc_dc_lastclose, .lastclose = atmel_hlcdc_dc_lastclose,
.irq_handler = atmel_hlcdc_dc_irq_handler, .irq_handler = atmel_hlcdc_dc_irq_handler,
.irq_preinstall = atmel_hlcdc_dc_irq_uninstall, .irq_preinstall = atmel_hlcdc_dc_irq_uninstall,

View File

@ -152,9 +152,6 @@ int atmel_hlcdc_plane_prepare_disc_area(struct drm_crtc_state *c_state);
void atmel_hlcdc_crtc_irq(struct drm_crtc *c); void atmel_hlcdc_crtc_irq(struct drm_crtc *c);
void atmel_hlcdc_crtc_cancel_page_flip(struct drm_crtc *crtc,
struct drm_file *file);
void atmel_hlcdc_crtc_suspend(struct drm_crtc *crtc); void atmel_hlcdc_crtc_suspend(struct drm_crtc *crtc);
void atmel_hlcdc_crtc_resume(struct drm_crtc *crtc); void atmel_hlcdc_crtc_resume(struct drm_crtc *crtc);

View File

@ -1347,46 +1347,25 @@ static struct drm_pending_vblank_event *create_vblank_event(
struct drm_device *dev, struct drm_file *file_priv, uint64_t user_data) struct drm_device *dev, struct drm_file *file_priv, uint64_t user_data)
{ {
struct drm_pending_vblank_event *e = NULL; struct drm_pending_vblank_event *e = NULL;
unsigned long flags; int ret;
spin_lock_irqsave(&dev->event_lock, flags);
if (file_priv->event_space < sizeof e->event) {
spin_unlock_irqrestore(&dev->event_lock, flags);
goto out;
}
file_priv->event_space -= sizeof e->event;
spin_unlock_irqrestore(&dev->event_lock, flags);
e = kzalloc(sizeof *e, GFP_KERNEL); e = kzalloc(sizeof *e, GFP_KERNEL);
if (e == NULL) { if (!e)
spin_lock_irqsave(&dev->event_lock, flags); return NULL;
file_priv->event_space += sizeof e->event;
spin_unlock_irqrestore(&dev->event_lock, flags);
goto out;
}
e->event.base.type = DRM_EVENT_FLIP_COMPLETE; e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
e->event.base.length = sizeof e->event; e->event.base.length = sizeof(e->event);
e->event.user_data = user_data; e->event.user_data = user_data;
e->base.event = &e->event.base;
e->base.file_priv = file_priv;
e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
out: ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base);
if (ret) {
kfree(e);
return NULL;
}
return e; return e;
} }
static void destroy_vblank_event(struct drm_device *dev,
struct drm_file *file_priv, struct drm_pending_vblank_event *e)
{
unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags);
file_priv->event_space += sizeof e->event;
spin_unlock_irqrestore(&dev->event_lock, flags);
kfree(e);
}
static int atomic_set_prop(struct drm_atomic_state *state, static int atomic_set_prop(struct drm_atomic_state *state,
struct drm_mode_object *obj, struct drm_property *prop, struct drm_mode_object *obj, struct drm_property *prop,
uint64_t prop_value) uint64_t prop_value)
@ -1646,8 +1625,7 @@ out:
if (!crtc_state->event) if (!crtc_state->event)
continue; continue;
destroy_vblank_event(dev, file_priv, drm_event_cancel_free(dev, &crtc_state->event->base);
crtc_state->event);
} }
} }

View File

@ -617,7 +617,6 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
for_each_connector_in_state(old_state, connector, old_conn_state, i) { for_each_connector_in_state(old_state, connector, old_conn_state, i) {
const struct drm_encoder_helper_funcs *funcs; const struct drm_encoder_helper_funcs *funcs;
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct drm_crtc_state *old_crtc_state;
/* Shut down everything that's in the changeset and currently /* Shut down everything that's in the changeset and currently
* still on. So need to check the old, saved state. */ * still on. So need to check the old, saved state. */
@ -2549,8 +2548,10 @@ void drm_atomic_helper_plane_reset(struct drm_plane *plane)
kfree(plane->state); kfree(plane->state);
plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL); plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL);
if (plane->state) if (plane->state) {
plane->state->plane = plane; plane->state->plane = plane;
plane->state->rotation = BIT(DRM_ROTATE_0);
}
} }
EXPORT_SYMBOL(drm_atomic_helper_plane_reset); EXPORT_SYMBOL(drm_atomic_helper_plane_reset);

View File

@ -5265,7 +5265,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct drm_framebuffer *fb = NULL; struct drm_framebuffer *fb = NULL;
struct drm_pending_vblank_event *e = NULL; struct drm_pending_vblank_event *e = NULL;
unsigned long flags;
int ret = -EINVAL; int ret = -EINVAL;
if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
@ -5316,41 +5315,26 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
} }
if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
ret = -ENOMEM; e = kzalloc(sizeof *e, GFP_KERNEL);
spin_lock_irqsave(&dev->event_lock, flags); if (!e) {
if (file_priv->event_space < sizeof(e->event)) { ret = -ENOMEM;
spin_unlock_irqrestore(&dev->event_lock, flags);
goto out; goto out;
} }
file_priv->event_space -= sizeof(e->event);
spin_unlock_irqrestore(&dev->event_lock, flags);
e = kzalloc(sizeof(*e), GFP_KERNEL);
if (e == NULL) {
spin_lock_irqsave(&dev->event_lock, flags);
file_priv->event_space += sizeof(e->event);
spin_unlock_irqrestore(&dev->event_lock, flags);
goto out;
}
e->event.base.type = DRM_EVENT_FLIP_COMPLETE; e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
e->event.base.length = sizeof(e->event); e->event.base.length = sizeof(e->event);
e->event.user_data = page_flip->user_data; e->event.user_data = page_flip->user_data;
e->base.event = &e->event.base; ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base);
e->base.file_priv = file_priv; if (ret) {
e->base.destroy = kfree(e);
(void (*) (struct drm_pending_event *)) kfree; goto out;
}
} }
crtc->primary->old_fb = crtc->primary->fb; crtc->primary->old_fb = crtc->primary->fb;
ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags); ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
if (ret) { if (ret) {
if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT)
spin_lock_irqsave(&dev->event_lock, flags); drm_event_cancel_free(dev, &e->base);
file_priv->event_space += sizeof(e->event);
spin_unlock_irqrestore(&dev->event_lock, flags);
kfree(e);
}
/* Keep the old fb, don't unref it. */ /* Keep the old fb, don't unref it. */
crtc->primary->old_fb = NULL; crtc->primary->old_fb = NULL;
} else { } else {

View File

@ -220,6 +220,15 @@ static void __drm_helper_disable_unused_functions(struct drm_device *dev)
* disconnected connectors. Then it will disable all unused encoders and CRTCs * disconnected connectors. Then it will disable all unused encoders and CRTCs
* either by calling their disable callback if available or by calling their * either by calling their disable callback if available or by calling their
* dpms callback with DRM_MODE_DPMS_OFF. * dpms callback with DRM_MODE_DPMS_OFF.
*
* NOTE:
*
* This function is part of the legacy modeset helper library and will cause
* major confusion with atomic drivers. This is because atomic helpers guarantee
* to never call ->disable() hooks on a disabled function, or ->enable() hooks
* on an enabled functions. drm_helper_disable_unused_functions() on the other
* hand throws such guarantees into the wind and calls disable hooks
* unconditionally on unused functions.
*/ */
void drm_helper_disable_unused_functions(struct drm_device *dev) void drm_helper_disable_unused_functions(struct drm_device *dev)
{ {
@ -578,8 +587,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
if (set->crtc->primary->fb == NULL) { if (set->crtc->primary->fb == NULL) {
DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
mode_changed = true; mode_changed = true;
} else if (set->fb == NULL) {
mode_changed = true;
} else if (set->fb->pixel_format != } else if (set->fb->pixel_format !=
set->crtc->primary->fb->pixel_format) { set->crtc->primary->fb->pixel_format) {
mode_changed = true; mode_changed = true;
@ -590,7 +597,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
if (set->x != set->crtc->x || set->y != set->crtc->y) if (set->x != set->crtc->x || set->y != set->crtc->y)
fb_changed = true; fb_changed = true;
if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { if (!drm_mode_equal(set->mode, &set->crtc->mode)) {
DRM_DEBUG_KMS("modes are different, full mode set\n"); DRM_DEBUG_KMS("modes are different, full mode set\n");
drm_mode_debug_printmodeline(&set->crtc->mode); drm_mode_debug_printmodeline(&set->crtc->mode);
drm_mode_debug_printmodeline(set->mode); drm_mode_debug_printmodeline(set->mode);

View File

@ -74,7 +74,8 @@ static struct drm_framebuffer_funcs drm_fb_cma_funcs = {
}; };
static struct drm_fb_cma *drm_fb_cma_alloc(struct drm_device *dev, static struct drm_fb_cma *drm_fb_cma_alloc(struct drm_device *dev,
const const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_cma_object **obj, const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_cma_object **obj,
unsigned int num_planes) unsigned int num_planes)
{ {
struct drm_fb_cma *fb_cma; struct drm_fb_cma *fb_cma;

View File

@ -2091,6 +2091,27 @@ out:
* drm_fb_helper_fill_fix() are provided as helpers to setup simple default * drm_fb_helper_fill_fix() are provided as helpers to setup simple default
* values for the fbdev info structure. * values for the fbdev info structure.
* *
* HANG DEBUGGING:
*
* When you have fbcon support built-in or already loaded, this function will do
* a full modeset to setup the fbdev console. Due to locking misdesign in the
* VT/fbdev subsystem that entire modeset sequence has to be done while holding
* console_lock. Until console_unlock is called no dmesg lines will be sent out
* to consoles, not even serial console. This means when your driver crashes,
* you will see absolutely nothing else but a system stuck in this function,
* with no further output. Any kind of printk() you place within your own driver
* or in the drm core modeset code will also never show up.
*
* Standard debug practice is to run the fbcon setup without taking the
* console_lock as a hack, to be able to see backtraces and crashes on the
* serial line. This can be done by setting the fb.lockless_register_fb=1 kernel
* cmdline option.
*
* The other option is to just disable fbdev emulation since very likely the
* first modest from userspace will crash in the same way, and is even easier to
* debug. This can be done by setting the drm_kms_helper.fbdev_emulation=0
* kernel cmdline option.
*
* RETURNS: * RETURNS:
* Zero if everything went ok, nonzero otherwise. * Zero if everything went ok, nonzero otherwise.
*/ */

View File

@ -1,4 +1,4 @@
/** /*
* \file drm_fops.c * \file drm_fops.c
* File operations for DRM * File operations for DRM
* *
@ -44,6 +44,46 @@
/* from BKL pushdown */ /* from BKL pushdown */
DEFINE_MUTEX(drm_global_mutex); DEFINE_MUTEX(drm_global_mutex);
/**
* DOC: file operations
*
* Drivers must define the file operations structure that forms the DRM
* userspace API entry point, even though most of those operations are
* implemented in the DRM core. The mandatory functions are drm_open(),
* drm_read(), drm_ioctl() and drm_compat_ioctl if CONFIG_COMPAT is enabled.
* Drivers which implement private ioctls that require 32/64 bit compatibility
* support must provided their onw .compat_ioctl() handler that processes
* private ioctls and calls drm_compat_ioctl() for core ioctls.
*
* In addition drm_read() and drm_poll() provide support for DRM events. DRM
* events are a generic and extensible means to send asynchronous events to
* userspace through the file descriptor. They are used to send vblank event and
* page flip completions by the KMS API. But drivers can also use it for their
* own needs, e.g. to signal completion of rendering.
*
* The memory mapping implementation will vary depending on how the driver
* manages memory. Legacy drivers will use the deprecated drm_legacy_mmap()
* function, modern drivers should use one of the provided memory-manager
* specific implementations. For GEM-based drivers this is drm_gem_mmap().
*
* No other file operations are supported by the DRM userspace API. Overall the
* following is an example #file_operations structure:
*
* static const example_drm_fops = {
* .owner = THIS_MODULE,
* .open = drm_open,
* .release = drm_release,
* .unlocked_ioctl = drm_ioctl,
* #ifdef CONFIG_COMPAT
* .compat_ioctl = drm_compat_ioctl,
* #endif
* .poll = drm_poll,
* .read = drm_read,
* .llseek = no_llseek,
* .mmap = drm_gem_mmap,
* };
*/
static int drm_open_helper(struct file *filp, struct drm_minor *minor); static int drm_open_helper(struct file *filp, struct drm_minor *minor);
static int drm_setup(struct drm_device * dev) static int drm_setup(struct drm_device * dev)
@ -67,15 +107,17 @@ static int drm_setup(struct drm_device * dev)
} }
/** /**
* Open file. * drm_open - open method for DRM file
* @inode: device inode
* @filp: file pointer.
* *
* \param inode device inode * This function must be used by drivers as their .open() #file_operations
* \param filp file pointer. * method. It looks up the correct DRM device and instantiates all the per-file
* \return zero on success or a negative number on failure. * resources for it.
* *
* Searches the DRM device with the same minor number, calls open_helper(), and * RETURNS:
* increments the device open count. If the open count was previous at zero, *
* i.e., it's the first that the device is open, then calls setup(). * 0 on success or negative errno value on falure.
*/ */
int drm_open(struct inode *inode, struct file *filp) int drm_open(struct inode *inode, struct file *filp)
{ {
@ -112,7 +154,7 @@ err_undo:
} }
EXPORT_SYMBOL(drm_open); EXPORT_SYMBOL(drm_open);
/** /*
* Check whether DRI will run on this CPU. * Check whether DRI will run on this CPU.
* *
* \return non-zero if the DRI will run on this CPU, or zero otherwise. * \return non-zero if the DRI will run on this CPU, or zero otherwise.
@ -125,7 +167,7 @@ static int drm_cpu_valid(void)
return 1; return 1;
} }
/** /*
* drm_new_set_master - Allocate a new master object and become master for the * drm_new_set_master - Allocate a new master object and become master for the
* associated master realm. * associated master realm.
* *
@ -179,7 +221,7 @@ out_err:
return ret; return ret;
} }
/** /*
* Called whenever a process opens /dev/drm. * Called whenever a process opens /dev/drm.
* *
* \param filp file pointer. * \param filp file pointer.
@ -222,6 +264,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
INIT_LIST_HEAD(&priv->fbs); INIT_LIST_HEAD(&priv->fbs);
mutex_init(&priv->fbs_lock); mutex_init(&priv->fbs_lock);
INIT_LIST_HEAD(&priv->blobs); INIT_LIST_HEAD(&priv->blobs);
INIT_LIST_HEAD(&priv->pending_event_list);
INIT_LIST_HEAD(&priv->event_list); INIT_LIST_HEAD(&priv->event_list);
init_waitqueue_head(&priv->event_wait); init_waitqueue_head(&priv->event_wait);
priv->event_space = 4096; /* set aside 4k for event buffer */ priv->event_space = 4096; /* set aside 4k for event buffer */
@ -311,18 +354,16 @@ static void drm_events_release(struct drm_file *file_priv)
{ {
struct drm_device *dev = file_priv->minor->dev; struct drm_device *dev = file_priv->minor->dev;
struct drm_pending_event *e, *et; struct drm_pending_event *e, *et;
struct drm_pending_vblank_event *v, *vt;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags); spin_lock_irqsave(&dev->event_lock, flags);
/* Remove pending flips */ /* Unlink pending events */
list_for_each_entry_safe(v, vt, &dev->vblank_event_list, base.link) list_for_each_entry_safe(e, et, &file_priv->pending_event_list,
if (v->base.file_priv == file_priv) { pending_link) {
list_del(&v->base.link); list_del(&e->pending_link);
drm_vblank_put(dev, v->pipe); e->file_priv = NULL;
v->base.destroy(&v->base); }
}
/* Remove unconsumed events */ /* Remove unconsumed events */
list_for_each_entry_safe(e, et, &file_priv->event_list, link) { list_for_each_entry_safe(e, et, &file_priv->event_list, link) {
@ -333,7 +374,7 @@ static void drm_events_release(struct drm_file *file_priv)
spin_unlock_irqrestore(&dev->event_lock, flags); spin_unlock_irqrestore(&dev->event_lock, flags);
} }
/** /*
* drm_legacy_dev_reinit * drm_legacy_dev_reinit
* *
* Reinitializes a legacy/ums drm device in it's lastclose function. * Reinitializes a legacy/ums drm device in it's lastclose function.
@ -350,7 +391,7 @@ static void drm_legacy_dev_reinit(struct drm_device *dev)
dev->if_version = 0; dev->if_version = 0;
} }
/** /*
* Take down the DRM device. * Take down the DRM device.
* *
* \param dev DRM device structure. * \param dev DRM device structure.
@ -387,16 +428,17 @@ int drm_lastclose(struct drm_device * dev)
} }
/** /**
* Release file. * drm_release - release method for DRM file
* @inode: device inode
* @filp: file pointer.
* *
* \param inode device inode * This function must be used by drivers as their .release() #file_operations
* \param file_priv DRM file private. * method. It frees any resources associated with the open file, and if this is
* \return zero on success or a negative number on failure. * the last open file for the DRM device also proceeds to call drm_lastclose().
* *
* If the hardware lock is held then free it, and take it again for the kernel * RETURNS:
* context since it's necessary to reclaim buffers. Unlink the file private *
* data from its list and free it. Decreases the open count and if it reaches * Always succeeds and returns 0.
* zero calls drm_lastclose().
*/ */
int drm_release(struct inode *inode, struct file *filp) int drm_release(struct inode *inode, struct file *filp)
{ {
@ -451,7 +493,7 @@ int drm_release(struct inode *inode, struct file *filp)
if (file_priv->is_master) { if (file_priv->is_master) {
struct drm_master *master = file_priv->master; struct drm_master *master = file_priv->master;
/** /*
* Since the master is disappearing, so is the * Since the master is disappearing, so is the
* possibility to lock. * possibility to lock.
*/ */
@ -508,6 +550,32 @@ int drm_release(struct inode *inode, struct file *filp)
} }
EXPORT_SYMBOL(drm_release); EXPORT_SYMBOL(drm_release);
/**
* drm_read - read method for DRM file
* @filp: file pointer
* @buffer: userspace destination pointer for the read
* @count: count in bytes to read
* @offset: offset to read
*
* This function must be used by drivers as their .read() #file_operations
* method iff they use DRM events for asynchronous signalling to userspace.
* Since events are used by the KMS API for vblank and page flip completion this
* means all modern display drivers must use it.
*
* @offset is ignore, DRM events are read like a pipe. Therefore drivers also
* must set the .llseek() #file_operation to no_llseek(). Polling support is
* provided by drm_poll().
*
* This function will only ever read a full event. Therefore userspace must
* supply a big enough buffer to fit any event to ensure forward progress. Since
* the maximum event space is currently 4K it's recommended to just use that for
* safety.
*
* RETURNS:
*
* Number of bytes read (always aligned to full events, and can be 0) or a
* negative error code on failure.
*/
ssize_t drm_read(struct file *filp, char __user *buffer, ssize_t drm_read(struct file *filp, char __user *buffer,
size_t count, loff_t *offset) size_t count, loff_t *offset)
{ {
@ -578,6 +646,22 @@ put_back_event:
} }
EXPORT_SYMBOL(drm_read); EXPORT_SYMBOL(drm_read);
/**
* drm_poll - poll method for DRM file
* @filp: file pointer
* @wait: poll waiter table
*
* This function must be used by drivers as their .read() #file_operations
* method iff they use DRM events for asynchronous signalling to userspace.
* Since events are used by the KMS API for vblank and page flip completion this
* means all modern display drivers must use it.
*
* See also drm_read().
*
* RETURNS:
*
* Mask of POLL flags indicating the current status of the file.
*/
unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
{ {
struct drm_file *file_priv = filp->private_data; struct drm_file *file_priv = filp->private_data;
@ -591,3 +675,164 @@ unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
return mask; return mask;
} }
EXPORT_SYMBOL(drm_poll); EXPORT_SYMBOL(drm_poll);
/**
* drm_event_reserve_init_locked - init a DRM event and reserve space for it
* @dev: DRM device
* @file_priv: DRM file private data
* @p: tracking structure for the pending event
* @e: actual event data to deliver to userspace
*
* This function prepares the passed in event for eventual delivery. If the event
* doesn't get delivered (because the IOCTL fails later on, before queuing up
* anything) then the even must be cancelled and freed using
* drm_event_cancel_free(). Successfully initialized events should be sent out
* using drm_send_event() or drm_send_event_locked() to signal completion of the
* asynchronous event to userspace.
*
* If callers embedded @p into a larger structure it must be allocated with
* kmalloc and @p must be the first member element.
*
* This is the locked version of drm_event_reserve_init() for callers which
* already hold dev->event_lock.
*
* RETURNS:
*
* 0 on success or a negative error code on failure.
*/
int drm_event_reserve_init_locked(struct drm_device *dev,
struct drm_file *file_priv,
struct drm_pending_event *p,
struct drm_event *e)
{
if (file_priv->event_space < e->length)
return -ENOMEM;
file_priv->event_space -= e->length;
p->event = e;
list_add(&p->pending_link, &file_priv->pending_event_list);
p->file_priv = file_priv;
/* we *could* pass this in as arg, but everyone uses kfree: */
p->destroy = (void (*) (struct drm_pending_event *)) kfree;
return 0;
}
EXPORT_SYMBOL(drm_event_reserve_init_locked);
/**
* drm_event_reserve_init - init a DRM event and reserve space for it
* @dev: DRM device
* @file_priv: DRM file private data
* @p: tracking structure for the pending event
* @e: actual event data to deliver to userspace
*
* This function prepares the passed in event for eventual delivery. If the event
* doesn't get delivered (because the IOCTL fails later on, before queuing up
* anything) then the even must be cancelled and freed using
* drm_event_cancel_free(). Successfully initialized events should be sent out
* using drm_send_event() or drm_send_event_locked() to signal completion of the
* asynchronous event to userspace.
*
* If callers embedded @p into a larger structure it must be allocated with
* kmalloc and @p must be the first member element.
*
* Callers which already hold dev->event_lock should use
* drm_event_reserve_init() instead.
*
* RETURNS:
*
* 0 on success or a negative error code on failure.
*/
int drm_event_reserve_init(struct drm_device *dev,
struct drm_file *file_priv,
struct drm_pending_event *p,
struct drm_event *e)
{
unsigned long flags;
int ret;
spin_lock_irqsave(&dev->event_lock, flags);
ret = drm_event_reserve_init_locked(dev, file_priv, p, e);
spin_unlock_irqrestore(&dev->event_lock, flags);
return ret;
}
EXPORT_SYMBOL(drm_event_reserve_init);
/**
* drm_event_cancel_free - free a DRM event and release it's space
* @dev: DRM device
* @p: tracking structure for the pending event
*
* This function frees the event @p initialized with drm_event_reserve_init()
* and releases any allocated space.
*/
void drm_event_cancel_free(struct drm_device *dev,
struct drm_pending_event *p)
{
unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags);
if (p->file_priv) {
p->file_priv->event_space += p->event->length;
list_del(&p->pending_link);
}
spin_unlock_irqrestore(&dev->event_lock, flags);
p->destroy(p);
}
EXPORT_SYMBOL(drm_event_cancel_free);
/**
* drm_send_event_locked - send DRM event to file descriptor
* @dev: DRM device
* @e: DRM event to deliver
*
* This function sends the event @e, initialized with drm_event_reserve_init(),
* to its associated userspace DRM file. Callers must already hold
* dev->event_lock, see drm_send_event() for the unlocked version.
*
* Note that the core will take care of unlinking and disarming events when the
* corresponding DRM file is closed. Drivers need not worry about whether the
* DRM file for this event still exists and can call this function upon
* completion of the asynchronous work unconditionally.
*/
void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e)
{
assert_spin_locked(&dev->event_lock);
if (!e->file_priv) {
e->destroy(e);
return;
}
list_del(&e->pending_link);
list_add_tail(&e->link,
&e->file_priv->event_list);
wake_up_interruptible(&e->file_priv->event_wait);
}
EXPORT_SYMBOL(drm_send_event_locked);
/**
* drm_send_event - send DRM event to file descriptor
* @dev: DRM device
* @e: DRM event to deliver
*
* This function sends the event @e, initialized with drm_event_reserve_init(),
* to its associated userspace DRM file. This function acquires dev->event_lock,
* see drm_send_event_locked() for callers which already hold this lock.
*
* Note that the core will take care of unlinking and disarming events when the
* corresponding DRM file is closed. Drivers need not worry about whether the
* DRM file for this event still exists and can call this function upon
* completion of the asynchronous work unconditionally.
*/
void drm_send_event(struct drm_device *dev, struct drm_pending_event *e)
{
unsigned long irqflags;
spin_lock_irqsave(&dev->event_lock, irqflags);
drm_send_event_locked(dev, e);
spin_unlock_irqrestore(&dev->event_lock, irqflags);
}
EXPORT_SYMBOL(drm_send_event);

View File

@ -983,15 +983,12 @@ static void send_vblank_event(struct drm_device *dev,
struct drm_pending_vblank_event *e, struct drm_pending_vblank_event *e,
unsigned long seq, struct timeval *now) unsigned long seq, struct timeval *now)
{ {
assert_spin_locked(&dev->event_lock);
e->event.sequence = seq; e->event.sequence = seq;
e->event.tv_sec = now->tv_sec; e->event.tv_sec = now->tv_sec;
e->event.tv_usec = now->tv_usec; e->event.tv_usec = now->tv_usec;
list_add_tail(&e->base.link, drm_send_event_locked(dev, &e->base);
&e->base.file_priv->event_list);
wake_up_interruptible(&e->base.file_priv->event_wait);
trace_drm_vblank_event_delivered(e->base.pid, e->pipe, trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
e->event.sequence); e->event.sequence);
} }
@ -1601,9 +1598,6 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
e->event.base.type = DRM_EVENT_VBLANK; e->event.base.type = DRM_EVENT_VBLANK;
e->event.base.length = sizeof(e->event); e->event.base.length = sizeof(e->event);
e->event.user_data = vblwait->request.signal; e->event.user_data = vblwait->request.signal;
e->base.event = &e->event.base;
e->base.file_priv = file_priv;
e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
spin_lock_irqsave(&dev->event_lock, flags); spin_lock_irqsave(&dev->event_lock, flags);
@ -1619,12 +1613,12 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
goto err_unlock; goto err_unlock;
} }
if (file_priv->event_space < sizeof(e->event)) { ret = drm_event_reserve_init_locked(dev, file_priv, &e->base,
ret = -EBUSY; &e->event.base);
goto err_unlock;
} if (ret)
goto err_unlock;
file_priv->event_space -= sizeof(e->event);
seq = drm_vblank_count_and_time(dev, pipe, &now); seq = drm_vblank_count_and_time(dev, pipe, &now);
if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) && if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) &&

View File

@ -340,20 +340,6 @@ static void exynos_drm_preclose(struct drm_device *dev,
static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
{ {
struct drm_pending_event *e, *et;
unsigned long flags;
if (!file->driver_priv)
return;
spin_lock_irqsave(&dev->event_lock, flags);
/* Release all events handled by page flip handler but not freed. */
list_for_each_entry_safe(e, et, &file->event_list, link) {
list_del(&e->link);
e->destroy(e);
}
spin_unlock_irqrestore(&dev->event_lock, flags);
kfree(file->driver_priv); kfree(file->driver_priv);
file->driver_priv = NULL; file->driver_priv = NULL;
} }

View File

@ -880,7 +880,6 @@ static void g2d_finish_event(struct g2d_data *g2d, u32 cmdlist_no)
struct g2d_runqueue_node *runqueue_node = g2d->runqueue_node; struct g2d_runqueue_node *runqueue_node = g2d->runqueue_node;
struct drm_exynos_pending_g2d_event *e; struct drm_exynos_pending_g2d_event *e;
struct timeval now; struct timeval now;
unsigned long flags;
if (list_empty(&runqueue_node->event_list)) if (list_empty(&runqueue_node->event_list))
return; return;
@ -893,10 +892,7 @@ static void g2d_finish_event(struct g2d_data *g2d, u32 cmdlist_no)
e->event.tv_usec = now.tv_usec; e->event.tv_usec = now.tv_usec;
e->event.cmdlist_no = cmdlist_no; e->event.cmdlist_no = cmdlist_no;
spin_lock_irqsave(&drm_dev->event_lock, flags); drm_send_event(drm_dev, &e->base);
list_move_tail(&e->base.link, &e->base.file_priv->event_list);
wake_up_interruptible(&e->base.file_priv->event_wait);
spin_unlock_irqrestore(&drm_dev->event_lock, flags);
} }
static irqreturn_t g2d_irq_handler(int irq, void *dev_id) static irqreturn_t g2d_irq_handler(int irq, void *dev_id)
@ -1072,7 +1068,6 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
struct drm_exynos_pending_g2d_event *e; struct drm_exynos_pending_g2d_event *e;
struct g2d_cmdlist_node *node; struct g2d_cmdlist_node *node;
struct g2d_cmdlist *cmdlist; struct g2d_cmdlist *cmdlist;
unsigned long flags;
int size; int size;
int ret; int ret;
@ -1094,21 +1089,8 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
node->event = NULL; node->event = NULL;
if (req->event_type != G2D_EVENT_NOT) { if (req->event_type != G2D_EVENT_NOT) {
spin_lock_irqsave(&drm_dev->event_lock, flags);
if (file->event_space < sizeof(e->event)) {
spin_unlock_irqrestore(&drm_dev->event_lock, flags);
ret = -ENOMEM;
goto err;
}
file->event_space -= sizeof(e->event);
spin_unlock_irqrestore(&drm_dev->event_lock, flags);
e = kzalloc(sizeof(*node->event), GFP_KERNEL); e = kzalloc(sizeof(*node->event), GFP_KERNEL);
if (!e) { if (!e) {
spin_lock_irqsave(&drm_dev->event_lock, flags);
file->event_space += sizeof(e->event);
spin_unlock_irqrestore(&drm_dev->event_lock, flags);
ret = -ENOMEM; ret = -ENOMEM;
goto err; goto err;
} }
@ -1116,9 +1098,12 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
e->event.base.type = DRM_EXYNOS_G2D_EVENT; e->event.base.type = DRM_EXYNOS_G2D_EVENT;
e->event.base.length = sizeof(e->event); e->event.base.length = sizeof(e->event);
e->event.user_data = req->user_data; e->event.user_data = req->user_data;
e->base.event = &e->event.base;
e->base.file_priv = file; ret = drm_event_reserve_init(drm_dev, file, &e->base, &e->event.base);
e->base.destroy = (void (*) (struct drm_pending_event *)) kfree; if (ret) {
kfree(e);
goto err;
}
node->event = e; node->event = e;
} }
@ -1219,12 +1204,8 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
err_unmap: err_unmap:
g2d_unmap_cmdlist_gem(g2d, node, file); g2d_unmap_cmdlist_gem(g2d, node, file);
err_free_event: err_free_event:
if (node->event) { if (node->event)
spin_lock_irqsave(&drm_dev->event_lock, flags); drm_event_cancel_free(drm_dev, &node->event->base);
file->event_space += sizeof(e->event);
spin_unlock_irqrestore(&drm_dev->event_lock, flags);
kfree(node->event);
}
err: err:
g2d_put_cmdlist(g2d, node); g2d_put_cmdlist(g2d, node);
return ret; return ret;

View File

@ -618,27 +618,18 @@ static void ipp_clean_mem_nodes(struct drm_device *drm_dev,
mutex_unlock(&c_node->mem_lock); mutex_unlock(&c_node->mem_lock);
} }
static void ipp_free_event(struct drm_pending_event *event)
{
kfree(event);
}
static int ipp_get_event(struct drm_device *drm_dev, static int ipp_get_event(struct drm_device *drm_dev,
struct drm_exynos_ipp_cmd_node *c_node, struct drm_exynos_ipp_cmd_node *c_node,
struct drm_exynos_ipp_queue_buf *qbuf) struct drm_exynos_ipp_queue_buf *qbuf)
{ {
struct drm_exynos_ipp_send_event *e; struct drm_exynos_ipp_send_event *e;
unsigned long flags; int ret;
DRM_DEBUG_KMS("ops_id[%d]buf_id[%d]\n", qbuf->ops_id, qbuf->buf_id); DRM_DEBUG_KMS("ops_id[%d]buf_id[%d]\n", qbuf->ops_id, qbuf->buf_id);
e = kzalloc(sizeof(*e), GFP_KERNEL); e = kzalloc(sizeof(*e), GFP_KERNEL);
if (!e) { if (!e)
spin_lock_irqsave(&drm_dev->event_lock, flags);
c_node->filp->event_space += sizeof(e->event);
spin_unlock_irqrestore(&drm_dev->event_lock, flags);
return -ENOMEM; return -ENOMEM;
}
/* make event */ /* make event */
e->event.base.type = DRM_EXYNOS_IPP_EVENT; e->event.base.type = DRM_EXYNOS_IPP_EVENT;
@ -646,9 +637,13 @@ static int ipp_get_event(struct drm_device *drm_dev,
e->event.user_data = qbuf->user_data; e->event.user_data = qbuf->user_data;
e->event.prop_id = qbuf->prop_id; e->event.prop_id = qbuf->prop_id;
e->event.buf_id[EXYNOS_DRM_OPS_DST] = qbuf->buf_id; e->event.buf_id[EXYNOS_DRM_OPS_DST] = qbuf->buf_id;
e->base.event = &e->event.base;
e->base.file_priv = c_node->filp; ret = drm_event_reserve_init(drm_dev, c_node->filp, &e->base, &e->event.base);
e->base.destroy = ipp_free_event; if (ret) {
kfree(e);
return ret;
}
mutex_lock(&c_node->event_lock); mutex_lock(&c_node->event_lock);
list_add_tail(&e->base.link, &c_node->event_list); list_add_tail(&e->base.link, &c_node->event_list);
mutex_unlock(&c_node->event_lock); mutex_unlock(&c_node->event_lock);
@ -1412,7 +1407,6 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
struct drm_exynos_ipp_send_event *e; struct drm_exynos_ipp_send_event *e;
struct list_head *head; struct list_head *head;
struct timeval now; struct timeval now;
unsigned long flags;
u32 tbuf_id[EXYNOS_DRM_OPS_MAX] = {0, }; u32 tbuf_id[EXYNOS_DRM_OPS_MAX] = {0, };
int ret, i; int ret, i;
@ -1525,10 +1519,7 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
for_each_ipp_ops(i) for_each_ipp_ops(i)
e->event.buf_id[i] = tbuf_id[i]; e->event.buf_id[i] = tbuf_id[i];
spin_lock_irqsave(&drm_dev->event_lock, flags); drm_send_event(drm_dev, &e->base);
list_move_tail(&e->base.link, &e->base.file_priv->event_list);
wake_up_interruptible(&e->base.file_priv->event_wait);
spin_unlock_irqrestore(&drm_dev->event_lock, flags);
mutex_unlock(&c_node->event_lock); mutex_unlock(&c_node->event_lock);
DRM_DEBUG_KMS("done cmd[%d]prop_id[%d]buf_id[%d]\n", DRM_DEBUG_KMS("done cmd[%d]prop_id[%d]buf_id[%d]\n",

View File

@ -112,10 +112,6 @@ static int fsl_dcu_unload(struct drm_device *dev)
return 0; return 0;
} }
static void fsl_dcu_drm_preclose(struct drm_device *dev, struct drm_file *file)
{
}
static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg) static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
{ {
struct drm_device *dev = arg; struct drm_device *dev = arg;
@ -191,7 +187,6 @@ static struct drm_driver fsl_dcu_drm_driver = {
| DRIVER_PRIME | DRIVER_ATOMIC, | DRIVER_PRIME | DRIVER_ATOMIC,
.load = fsl_dcu_load, .load = fsl_dcu_load,
.unload = fsl_dcu_unload, .unload = fsl_dcu_unload,
.preclose = fsl_dcu_drm_preclose,
.irq_handler = fsl_dcu_drm_irq, .irq_handler = fsl_dcu_drm_irq,
.get_vblank_counter = drm_vblank_no_hw_counter, .get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = fsl_dcu_drm_enable_vblank, .enable_vblank = fsl_dcu_drm_enable_vblank,

View File

@ -674,29 +674,17 @@ static const struct drm_mode_config_funcs psb_mode_funcs = {
.output_poll_changed = psbfb_output_poll_changed, .output_poll_changed = psbfb_output_poll_changed,
}; };
static int psb_create_backlight_property(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = dev->dev_private;
struct drm_property *backlight;
if (dev_priv->backlight_property)
return 0;
backlight = drm_property_create_range(dev, 0, "backlight", 0, 100);
dev_priv->backlight_property = backlight;
return 0;
}
static void psb_setup_outputs(struct drm_device *dev) static void psb_setup_outputs(struct drm_device *dev)
{ {
struct drm_psb_private *dev_priv = dev->dev_private; struct drm_psb_private *dev_priv = dev->dev_private;
struct drm_connector *connector; struct drm_connector *connector;
drm_mode_create_scaling_mode_property(dev); drm_mode_create_scaling_mode_property(dev);
psb_create_backlight_property(dev);
/* It is ok for this to fail - we just don't get backlight control */
if (!dev_priv->backlight_property)
dev_priv->backlight_property = drm_property_create_range(dev, 0,
"backlight", 0, 100);
dev_priv->ops->output_init(dev); dev_priv->ops->output_init(dev);
list_for_each_entry(connector, &dev->mode_config.connector_list, list_for_each_entry(connector, &dev->mode_config.connector_list,

View File

@ -382,16 +382,6 @@ static int mdfld_dsi_connector_mode_valid(struct drm_connector *connector,
return MODE_OK; return MODE_OK;
} }
static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode)
{
if (mode == connector->dpms)
return;
/*first, execute dpms*/
drm_helper_connector_dpms(connector, mode);
}
static struct drm_encoder *mdfld_dsi_connector_best_encoder( static struct drm_encoder *mdfld_dsi_connector_best_encoder(
struct drm_connector *connector) struct drm_connector *connector)
{ {
@ -404,7 +394,7 @@ static struct drm_encoder *mdfld_dsi_connector_best_encoder(
/*DSI connector funcs*/ /*DSI connector funcs*/
static const struct drm_connector_funcs mdfld_dsi_connector_funcs = { static const struct drm_connector_funcs mdfld_dsi_connector_funcs = {
.dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms, .dpms = drm_helper_connector_dpms,
.detect = mdfld_dsi_connector_detect, .detect = mdfld_dsi_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.set_property = mdfld_dsi_connector_set_property, .set_property = mdfld_dsi_connector_set_property,

View File

@ -442,14 +442,6 @@ static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
/* FIXME: do we need to wrap the other side of this */ /* FIXME: do we need to wrap the other side of this */
} }
/*
* When a client dies:
* - Check for and clean up flipped page state
*/
static void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv)
{
}
static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
return drm_get_pci_dev(pdev, ent, &driver); return drm_get_pci_dev(pdev, ent, &driver);
@ -495,7 +487,6 @@ static struct drm_driver driver = {
.load = psb_driver_load, .load = psb_driver_load,
.unload = psb_driver_unload, .unload = psb_driver_unload,
.lastclose = psb_driver_lastclose, .lastclose = psb_driver_lastclose,
.preclose = psb_driver_preclose,
.set_busid = drm_pci_set_busid, .set_busid = drm_pci_set_busid,
.num_ioctls = ARRAY_SIZE(psb_ioctls), .num_ioctls = ARRAY_SIZE(psb_ioctls),

View File

@ -1261,8 +1261,6 @@ void i915_driver_preclose(struct drm_device *dev, struct drm_file *file)
i915_gem_context_close(dev, file); i915_gem_context_close(dev, file);
i915_gem_release(dev, file); i915_gem_release(dev, file);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
intel_modeset_preclose(dev, file);
} }
void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)

View File

@ -16310,24 +16310,3 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
err_printf(m, " VSYNC: %08x\n", error->transcoder[i].vsync); err_printf(m, " VSYNC: %08x\n", error->transcoder[i].vsync);
} }
} }
void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file)
{
struct intel_crtc *crtc;
for_each_intel_crtc(dev, crtc) {
struct intel_unpin_work *work;
spin_lock_irq(&dev->event_lock);
work = crtc->unpin_work;
if (work && work->event &&
work->event->base.file_priv == file) {
kfree(work->event);
work->event = NULL;
}
spin_unlock_irq(&dev->event_lock);
}
}

View File

@ -1212,7 +1212,6 @@ enum intel_display_power_domain
intel_display_port_aux_power_domain(struct intel_encoder *intel_encoder); intel_display_port_aux_power_domain(struct intel_encoder *intel_encoder);
void intel_mode_from_pipe_config(struct drm_display_mode *mode, void intel_mode_from_pipe_config(struct drm_display_mode *mode,
struct intel_crtc_state *pipe_config); struct intel_crtc_state *pipe_config);
void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state); int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state); int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);

View File

@ -171,18 +171,6 @@ static void imx_drm_disable_vblank(struct drm_device *drm, unsigned int pipe)
imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc); imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc);
} }
static void imx_drm_driver_preclose(struct drm_device *drm,
struct drm_file *file)
{
int i;
if (!file->is_master)
return;
for (i = 0; i < MAX_CRTC; i++)
imx_drm_disable_vblank(drm, i);
}
static const struct file_operations imx_drm_driver_fops = { static const struct file_operations imx_drm_driver_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = drm_open, .open = drm_open,
@ -463,7 +451,6 @@ static struct drm_driver imx_drm_driver = {
.load = imx_drm_driver_load, .load = imx_drm_driver_load,
.unload = imx_drm_driver_unload, .unload = imx_drm_driver_unload,
.lastclose = imx_drm_driver_lastclose, .lastclose = imx_drm_driver_lastclose,
.preclose = imx_drm_driver_preclose,
.set_busid = drm_platform_set_busid, .set_busid = drm_platform_set_busid,
.gem_free_object = drm_gem_cma_free_object, .gem_free_object = drm_gem_cma_free_object,
.gem_vm_ops = &drm_gem_cma_vm_ops, .gem_vm_ops = &drm_gem_cma_vm_ops,

View File

@ -285,10 +285,6 @@ static int ipu_enable_vblank(struct drm_crtc *crtc)
static void ipu_disable_vblank(struct drm_crtc *crtc) static void ipu_disable_vblank(struct drm_crtc *crtc)
{ {
struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
ipu_crtc->page_flip_event = NULL;
ipu_crtc->newfb = NULL;
} }
static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc,

View File

@ -575,13 +575,6 @@ uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc)
return mdp4_crtc->vblank.irqmask; return mdp4_crtc->vblank.irqmask;
} }
void mdp4_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file)
{
struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
DBG("%s: cancel: %p", mdp4_crtc->name, file);
complete_flip(crtc, file);
}
/* set dma config, ie. the format the encoder wants. */ /* set dma config, ie. the format the encoder wants. */
void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config) void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config)
{ {

View File

@ -179,16 +179,6 @@ static long mdp4_round_pixclk(struct msm_kms *kms, unsigned long rate,
} }
} }
static void mdp4_preclose(struct msm_kms *kms, struct drm_file *file)
{
struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
struct msm_drm_private *priv = mdp4_kms->dev->dev_private;
unsigned i;
for (i = 0; i < priv->num_crtcs; i++)
mdp4_crtc_cancel_pending_flip(priv->crtcs[i], file);
}
static void mdp4_destroy(struct msm_kms *kms) static void mdp4_destroy(struct msm_kms *kms)
{ {
struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms)); struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
@ -213,7 +203,6 @@ static const struct mdp_kms_funcs kms_funcs = {
.wait_for_crtc_commit_done = mdp4_wait_for_crtc_commit_done, .wait_for_crtc_commit_done = mdp4_wait_for_crtc_commit_done,
.get_format = mdp_get_format, .get_format = mdp_get_format,
.round_pixclk = mdp4_round_pixclk, .round_pixclk = mdp4_round_pixclk,
.preclose = mdp4_preclose,
.destroy = mdp4_destroy, .destroy = mdp4_destroy,
}, },
.set_irqmask = mdp4_set_irqmask, .set_irqmask = mdp4_set_irqmask,

View File

@ -199,7 +199,6 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev,
enum mdp4_pipe pipe_id, bool private_plane); enum mdp4_pipe pipe_id, bool private_plane);
uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc); uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc);
void mdp4_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config); void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config);
void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf, int mixer); void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf, int mixer);
void mdp4_crtc_wait_for_commit_done(struct drm_crtc *crtc); void mdp4_crtc_wait_for_commit_done(struct drm_crtc *crtc);

View File

@ -721,12 +721,6 @@ uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc)
return mdp5_crtc->vblank.irqmask; return mdp5_crtc->vblank.irqmask;
} }
void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file)
{
DBG("cancel: %p", file);
complete_flip(crtc, file);
}
void mdp5_crtc_set_pipeline(struct drm_crtc *crtc, void mdp5_crtc_set_pipeline(struct drm_crtc *crtc,
struct mdp5_interface *intf, struct mdp5_ctl *ctl) struct mdp5_interface *intf, struct mdp5_ctl *ctl)
{ {

View File

@ -117,16 +117,6 @@ static int mdp5_set_split_display(struct msm_kms *kms,
return mdp5_encoder_set_split_display(encoder, slave_encoder); return mdp5_encoder_set_split_display(encoder, slave_encoder);
} }
static void mdp5_preclose(struct msm_kms *kms, struct drm_file *file)
{
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
struct msm_drm_private *priv = mdp5_kms->dev->dev_private;
unsigned i;
for (i = 0; i < priv->num_crtcs; i++)
mdp5_crtc_cancel_pending_flip(priv->crtcs[i], file);
}
static void mdp5_destroy(struct msm_kms *kms) static void mdp5_destroy(struct msm_kms *kms)
{ {
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
@ -164,7 +154,6 @@ static const struct mdp_kms_funcs kms_funcs = {
.get_format = mdp_get_format, .get_format = mdp_get_format,
.round_pixclk = mdp5_round_pixclk, .round_pixclk = mdp5_round_pixclk,
.set_split_display = mdp5_set_split_display, .set_split_display = mdp5_set_split_display,
.preclose = mdp5_preclose,
.destroy = mdp5_destroy, .destroy = mdp5_destroy,
}, },
.set_irqmask = mdp5_set_irqmask, .set_irqmask = mdp5_set_irqmask,

View File

@ -211,7 +211,6 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev,
uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc); uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
int mdp5_crtc_get_lm(struct drm_crtc *crtc); int mdp5_crtc_get_lm(struct drm_crtc *crtc);
void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
void mdp5_crtc_set_pipeline(struct drm_crtc *crtc, void mdp5_crtc_set_pipeline(struct drm_crtc *crtc,
struct mdp5_interface *intf, struct mdp5_ctl *ctl); struct mdp5_interface *intf, struct mdp5_ctl *ctl);
void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc); void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc);

View File

@ -269,18 +269,7 @@ static void omap_crtc_complete_page_flip(struct drm_crtc *crtc)
return; return;
spin_lock_irqsave(&dev->event_lock, flags); spin_lock_irqsave(&dev->event_lock, flags);
drm_crtc_send_vblank_event(crtc, event);
list_del(&event->base.link);
/*
* Queue the event for delivery if it's still linked to a file
* handle, otherwise just destroy it.
*/
if (event->base.file_priv)
drm_crtc_send_vblank_event(crtc, event);
else
event->base.destroy(&event->base);
spin_unlock_irqrestore(&dev->event_lock, flags); spin_unlock_irqrestore(&dev->event_lock, flags);
} }

View File

@ -142,7 +142,6 @@ static int omap_atomic_commit(struct drm_device *dev,
{ {
struct omap_drm_private *priv = dev->dev_private; struct omap_drm_private *priv = dev->dev_private;
struct omap_atomic_state_commit *commit; struct omap_atomic_state_commit *commit;
unsigned long flags;
unsigned int i; unsigned int i;
int ret; int ret;
@ -175,17 +174,6 @@ static int omap_atomic_commit(struct drm_device *dev,
priv->commit.pending |= commit->crtcs; priv->commit.pending |= commit->crtcs;
spin_unlock(&priv->commit.lock); spin_unlock(&priv->commit.lock);
/* Keep track of all CRTC events to unlink them in preclose(). */
spin_lock_irqsave(&dev->event_lock, flags);
for (i = 0; i < dev->mode_config.num_crtc; ++i) {
struct drm_crtc_state *cstate = state->crtc_states[i];
if (cstate && cstate->event)
list_add_tail(&cstate->event->base.link,
&priv->commit.events);
}
spin_unlock_irqrestore(&dev->event_lock, flags);
/* Swap the state, this is the point of no return. */ /* Swap the state, this is the point of no return. */
drm_atomic_helper_swap_state(dev, state); drm_atomic_helper_swap_state(dev, state);
@ -673,7 +661,6 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
priv->wq = alloc_ordered_workqueue("omapdrm", 0); priv->wq = alloc_ordered_workqueue("omapdrm", 0);
init_waitqueue_head(&priv->commit.wait); init_waitqueue_head(&priv->commit.wait);
spin_lock_init(&priv->commit.lock); spin_lock_init(&priv->commit.lock);
INIT_LIST_HEAD(&priv->commit.events);
spin_lock_init(&priv->list_lock); spin_lock_init(&priv->list_lock);
INIT_LIST_HEAD(&priv->obj_list); INIT_LIST_HEAD(&priv->obj_list);
@ -787,33 +774,6 @@ static void dev_lastclose(struct drm_device *dev)
} }
} }
static void dev_preclose(struct drm_device *dev, struct drm_file *file)
{
struct omap_drm_private *priv = dev->dev_private;
struct drm_pending_event *event;
unsigned long flags;
DBG("preclose: dev=%p", dev);
/*
* Unlink all pending CRTC events to make sure they won't be queued up
* by a pending asynchronous commit.
*/
spin_lock_irqsave(&dev->event_lock, flags);
list_for_each_entry(event, &priv->commit.events, link) {
if (event->file_priv == file) {
file->event_space += event->event->length;
event->file_priv = NULL;
}
}
spin_unlock_irqrestore(&dev->event_lock, flags);
}
static void dev_postclose(struct drm_device *dev, struct drm_file *file)
{
DBG("postclose: dev=%p, file=%p", dev, file);
}
static const struct vm_operations_struct omap_gem_vm_ops = { static const struct vm_operations_struct omap_gem_vm_ops = {
.fault = omap_gem_fault, .fault = omap_gem_fault,
.open = drm_gem_vm_open, .open = drm_gem_vm_open,
@ -838,8 +798,6 @@ static struct drm_driver omap_drm_driver = {
.unload = dev_unload, .unload = dev_unload,
.open = dev_open, .open = dev_open,
.lastclose = dev_lastclose, .lastclose = dev_lastclose,
.preclose = dev_preclose,
.postclose = dev_postclose,
.set_busid = drm_platform_set_busid, .set_busid = drm_platform_set_busid,
.get_vblank_counter = drm_vblank_no_hw_counter, .get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = omap_irq_enable_vblank, .enable_vblank = omap_irq_enable_vblank,

View File

@ -106,7 +106,6 @@ struct omap_drm_private {
/* atomic commit */ /* atomic commit */
struct { struct {
struct list_head events;
wait_queue_head_t wait; wait_queue_head_t wait;
u32 pending; u32 pending;
spinlock_t lock; /* Protects commit.pending */ spinlock_t lock; /* Protects commit.pending */

View File

@ -282,26 +282,6 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
* Page Flip * Page Flip
*/ */
void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc *rcrtc,
struct drm_file *file)
{
struct drm_pending_vblank_event *event;
struct drm_device *dev = rcrtc->crtc.dev;
unsigned long flags;
/* Destroy the pending vertical blanking event associated with the
* pending page flip, if any, and disable vertical blanking interrupts.
*/
spin_lock_irqsave(&dev->event_lock, flags);
event = rcrtc->event;
if (event && event->base.file_priv == file) {
rcrtc->event = NULL;
event->base.destroy(&event->base);
drm_crtc_vblank_put(&rcrtc->crtc);
}
spin_unlock_irqrestore(&dev->event_lock, flags);
}
static void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc) static void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc)
{ {
struct drm_pending_vblank_event *event; struct drm_pending_vblank_event *event;

View File

@ -67,8 +67,6 @@ enum rcar_du_output {
int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index); int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index);
void rcar_du_crtc_enable_vblank(struct rcar_du_crtc *rcrtc, bool enable); void rcar_du_crtc_enable_vblank(struct rcar_du_crtc *rcrtc, bool enable);
void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc *rcrtc,
struct drm_file *file);
void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc); void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc);
void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc); void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc);

View File

@ -220,15 +220,6 @@ done:
return ret; return ret;
} }
static void rcar_du_preclose(struct drm_device *dev, struct drm_file *file)
{
struct rcar_du_device *rcdu = dev->dev_private;
unsigned int i;
for (i = 0; i < rcdu->num_crtcs; ++i)
rcar_du_crtc_cancel_page_flip(&rcdu->crtcs[i], file);
}
static void rcar_du_lastclose(struct drm_device *dev) static void rcar_du_lastclose(struct drm_device *dev)
{ {
struct rcar_du_device *rcdu = dev->dev_private; struct rcar_du_device *rcdu = dev->dev_private;
@ -271,7 +262,6 @@ static struct drm_driver rcar_du_driver = {
| DRIVER_ATOMIC, | DRIVER_ATOMIC,
.load = rcar_du_load, .load = rcar_du_load,
.unload = rcar_du_unload, .unload = rcar_du_unload,
.preclose = rcar_du_preclose,
.lastclose = rcar_du_lastclose, .lastclose = rcar_du_lastclose,
.set_busid = drm_platform_set_busid, .set_busid = drm_platform_set_busid,
.get_vblank_counter = drm_vblank_no_hw_counter, .get_vblank_counter = drm_vblank_no_hw_counter,

View File

@ -438,26 +438,6 @@ static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
.mode_set_base = shmob_drm_crtc_mode_set_base, .mode_set_base = shmob_drm_crtc_mode_set_base,
}; };
void shmob_drm_crtc_cancel_page_flip(struct shmob_drm_crtc *scrtc,
struct drm_file *file)
{
struct drm_pending_vblank_event *event;
struct drm_device *dev = scrtc->crtc.dev;
unsigned long flags;
/* Destroy the pending vertical blanking event associated with the
* pending page flip, if any, and disable vertical blanking interrupts.
*/
spin_lock_irqsave(&dev->event_lock, flags);
event = scrtc->event;
if (event && event->base.file_priv == file) {
scrtc->event = NULL;
event->base.destroy(&event->base);
drm_vblank_put(dev, 0);
}
spin_unlock_irqrestore(&dev->event_lock, flags);
}
void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc) void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc)
{ {
struct drm_pending_vblank_event *event; struct drm_pending_vblank_event *event;

View File

@ -47,8 +47,6 @@ struct shmob_drm_connector {
int shmob_drm_crtc_create(struct shmob_drm_device *sdev); int shmob_drm_crtc_create(struct shmob_drm_device *sdev);
void shmob_drm_crtc_enable_vblank(struct shmob_drm_device *sdev, bool enable); void shmob_drm_crtc_enable_vblank(struct shmob_drm_device *sdev, bool enable);
void shmob_drm_crtc_cancel_page_flip(struct shmob_drm_crtc *scrtc,
struct drm_file *file);
void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc); void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc);
void shmob_drm_crtc_suspend(struct shmob_drm_crtc *scrtc); void shmob_drm_crtc_suspend(struct shmob_drm_crtc *scrtc);
void shmob_drm_crtc_resume(struct shmob_drm_crtc *scrtc); void shmob_drm_crtc_resume(struct shmob_drm_crtc *scrtc);

View File

@ -200,13 +200,6 @@ done:
return ret; return ret;
} }
static void shmob_drm_preclose(struct drm_device *dev, struct drm_file *file)
{
struct shmob_drm_device *sdev = dev->dev_private;
shmob_drm_crtc_cancel_page_flip(&sdev->crtc, file);
}
static irqreturn_t shmob_drm_irq(int irq, void *arg) static irqreturn_t shmob_drm_irq(int irq, void *arg)
{ {
struct drm_device *dev = arg; struct drm_device *dev = arg;
@ -266,7 +259,6 @@ static struct drm_driver shmob_drm_driver = {
| DRIVER_PRIME, | DRIVER_PRIME,
.load = shmob_drm_load, .load = shmob_drm_load,
.unload = shmob_drm_unload, .unload = shmob_drm_unload,
.preclose = shmob_drm_preclose,
.set_busid = drm_platform_set_busid, .set_busid = drm_platform_set_busid,
.irq_handler = shmob_drm_irq, .irq_handler = shmob_drm_irq,
.get_vblank_counter = drm_vblank_no_hw_counter, .get_vblank_counter = drm_vblank_no_hw_counter,

View File

@ -988,23 +988,6 @@ static void tegra_dc_finish_page_flip(struct tegra_dc *dc)
spin_unlock_irqrestore(&drm->event_lock, flags); spin_unlock_irqrestore(&drm->event_lock, flags);
} }
void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
{
struct tegra_dc *dc = to_tegra_dc(crtc);
struct drm_device *drm = crtc->dev;
unsigned long flags;
spin_lock_irqsave(&drm->event_lock, flags);
if (dc->event && dc->event->base.file_priv == file) {
dc->event->base.destroy(&dc->event->base);
drm_crtc_vblank_put(crtc);
dc->event = NULL;
}
spin_unlock_irqrestore(&drm->event_lock, flags);
}
static void tegra_dc_destroy(struct drm_crtc *crtc) static void tegra_dc_destroy(struct drm_crtc *crtc)
{ {
drm_crtc_cleanup(crtc); drm_crtc_cleanup(crtc);

View File

@ -860,9 +860,6 @@ static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file)
struct tegra_drm_context *context, *tmp; struct tegra_drm_context *context, *tmp;
struct drm_crtc *crtc; struct drm_crtc *crtc;
list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
tegra_dc_cancel_page_flip(crtc, file);
list_for_each_entry_safe(context, tmp, &fpriv->contexts, list) list_for_each_entry_safe(context, tmp, &fpriv->contexts, list)
tegra_drm_context_free(context); tegra_drm_context_free(context);

View File

@ -195,7 +195,6 @@ struct tegra_dc_window {
u32 tegra_dc_get_vblank_counter(struct tegra_dc *dc); u32 tegra_dc_get_vblank_counter(struct tegra_dc *dc);
void tegra_dc_enable_vblank(struct tegra_dc *dc); void tegra_dc_enable_vblank(struct tegra_dc *dc);
void tegra_dc_disable_vblank(struct tegra_dc *dc); void tegra_dc_disable_vblank(struct tegra_dc *dc);
void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file);
void tegra_dc_commit(struct tegra_dc *dc); void tegra_dc_commit(struct tegra_dc *dc);
int tegra_dc_state_setup_clock(struct tegra_dc *dc, int tegra_dc_state_setup_clock(struct tegra_dc *dc,
struct drm_crtc_state *crtc_state, struct drm_crtc_state *crtc_state,

View File

@ -662,26 +662,6 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
void tilcdc_crtc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
{
struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
struct drm_pending_vblank_event *event;
struct drm_device *dev = crtc->dev;
unsigned long flags;
/* Destroy the pending vertical blanking event associated with the
* pending page flip, if any, and disable vertical blanking interrupts.
*/
spin_lock_irqsave(&dev->event_lock, flags);
event = tilcdc_crtc->event;
if (event && event->base.file_priv == file) {
tilcdc_crtc->event = NULL;
event->base.destroy(&event->base);
drm_vblank_put(dev, 0);
}
spin_unlock_irqrestore(&dev->event_lock, flags);
}
struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev) struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
{ {
struct tilcdc_crtc *tilcdc_crtc; struct tilcdc_crtc *tilcdc_crtc;

View File

@ -350,13 +350,6 @@ fail_free_priv:
return ret; return ret;
} }
static void tilcdc_preclose(struct drm_device *dev, struct drm_file *file)
{
struct tilcdc_drm_private *priv = dev->dev_private;
tilcdc_crtc_cancel_page_flip(priv->crtc, file);
}
static void tilcdc_lastclose(struct drm_device *dev) static void tilcdc_lastclose(struct drm_device *dev)
{ {
struct tilcdc_drm_private *priv = dev->dev_private; struct tilcdc_drm_private *priv = dev->dev_private;
@ -557,7 +550,6 @@ static struct drm_driver tilcdc_driver = {
.driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET, .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET,
.load = tilcdc_load, .load = tilcdc_load,
.unload = tilcdc_unload, .unload = tilcdc_unload,
.preclose = tilcdc_preclose,
.lastclose = tilcdc_lastclose, .lastclose = tilcdc_lastclose,
.set_busid = drm_platform_set_busid, .set_busid = drm_platform_set_busid,
.irq_handler = tilcdc_irq, .irq_handler = tilcdc_irq,

View File

@ -163,7 +163,6 @@ struct tilcdc_panel_info {
#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev); struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev);
void tilcdc_crtc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file);
irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc); irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc);
void tilcdc_crtc_update_clk(struct drm_crtc *crtc); void tilcdc_crtc_update_clk(struct drm_crtc *crtc);
void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc, void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc,

View File

@ -593,26 +593,6 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
.atomic_flush = vc4_crtc_atomic_flush, .atomic_flush = vc4_crtc_atomic_flush,
}; };
/* Frees the page flip event when the DRM device is closed with the
* event still outstanding.
*/
void vc4_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
{
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
struct drm_device *dev = crtc->dev;
unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags);
if (vc4_crtc->event && vc4_crtc->event->base.file_priv == file) {
vc4_crtc->event->base.destroy(&vc4_crtc->event->base);
drm_crtc_vblank_put(crtc);
vc4_crtc->event = NULL;
}
spin_unlock_irqrestore(&dev->event_lock, flags);
}
static const struct vc4_crtc_data pv0_data = { static const struct vc4_crtc_data pv0_data = {
.hvs_channel = 0, .hvs_channel = 0,
.encoder0_type = VC4_ENCODER_TYPE_DSI0, .encoder0_type = VC4_ENCODER_TYPE_DSI0,

View File

@ -43,14 +43,6 @@ void __iomem *vc4_ioremap_regs(struct platform_device *dev, int index)
return map; return map;
} }
static void vc4_drm_preclose(struct drm_device *dev, struct drm_file *file)
{
struct drm_crtc *crtc;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
vc4_cancel_page_flip(crtc, file);
}
static void vc4_lastclose(struct drm_device *dev) static void vc4_lastclose(struct drm_device *dev)
{ {
struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_dev *vc4 = to_vc4_dev(dev);
@ -91,8 +83,6 @@ static struct drm_driver vc4_drm_driver = {
DRIVER_HAVE_IRQ | DRIVER_HAVE_IRQ |
DRIVER_PRIME), DRIVER_PRIME),
.lastclose = vc4_lastclose, .lastclose = vc4_lastclose,
.preclose = vc4_drm_preclose,
.irq_handler = vc4_irq, .irq_handler = vc4_irq,
.irq_preinstall = vc4_irq_preinstall, .irq_preinstall = vc4_irq_preinstall,
.irq_postinstall = vc4_irq_postinstall, .irq_postinstall = vc4_irq_postinstall,

View File

@ -376,7 +376,6 @@ int vc4_bo_stats_debugfs(struct seq_file *m, void *arg);
extern struct platform_driver vc4_crtc_driver; extern struct platform_driver vc4_crtc_driver;
int vc4_enable_vblank(struct drm_device *dev, unsigned int crtc_id); int vc4_enable_vblank(struct drm_device *dev, unsigned int crtc_id);
void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id); void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id);
void vc4_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file);
int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg); int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg);
/* vc4_debugfs.c */ /* vc4_debugfs.c */

View File

@ -972,15 +972,6 @@ static int vmw_driver_unload(struct drm_device *dev)
return 0; return 0;
} }
static void vmw_preclose(struct drm_device *dev,
struct drm_file *file_priv)
{
struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
struct vmw_private *dev_priv = vmw_priv(dev);
vmw_event_fence_fpriv_gone(dev_priv->fman, &vmw_fp->fence_events);
}
static void vmw_postclose(struct drm_device *dev, static void vmw_postclose(struct drm_device *dev,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
@ -1011,7 +1002,6 @@ static int vmw_driver_open(struct drm_device *dev, struct drm_file *file_priv)
if (unlikely(vmw_fp == NULL)) if (unlikely(vmw_fp == NULL))
return ret; return ret;
INIT_LIST_HEAD(&vmw_fp->fence_events);
vmw_fp->tfile = ttm_object_file_init(dev_priv->tdev, 10); vmw_fp->tfile = ttm_object_file_init(dev_priv->tdev, 10);
if (unlikely(vmw_fp->tfile == NULL)) if (unlikely(vmw_fp->tfile == NULL))
goto out_no_tfile; goto out_no_tfile;
@ -1501,7 +1491,6 @@ static struct drm_driver driver = {
.master_set = vmw_master_set, .master_set = vmw_master_set,
.master_drop = vmw_master_drop, .master_drop = vmw_master_drop,
.open = vmw_driver_open, .open = vmw_driver_open,
.preclose = vmw_preclose,
.postclose = vmw_postclose, .postclose = vmw_postclose,
.set_busid = drm_pci_set_busid, .set_busid = drm_pci_set_busid,

View File

@ -80,7 +80,6 @@
struct vmw_fpriv { struct vmw_fpriv {
struct drm_master *locked_master; struct drm_master *locked_master;
struct ttm_object_file *tfile; struct ttm_object_file *tfile;
struct list_head fence_events;
bool gb_aware; bool gb_aware;
}; };

View File

@ -71,7 +71,6 @@ struct vmw_user_fence {
*/ */
struct vmw_event_fence_action { struct vmw_event_fence_action {
struct vmw_fence_action action; struct vmw_fence_action action;
struct list_head fpriv_head;
struct drm_pending_event *event; struct drm_pending_event *event;
struct vmw_fence_obj *fence; struct vmw_fence_obj *fence;
@ -807,44 +806,6 @@ int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data,
TTM_REF_USAGE); TTM_REF_USAGE);
} }
/**
* vmw_event_fence_fpriv_gone - Remove references to struct drm_file objects
*
* @fman: Pointer to a struct vmw_fence_manager
* @event_list: Pointer to linked list of struct vmw_event_fence_action objects
* with pointers to a struct drm_file object about to be closed.
*
* This function removes all pending fence events with references to a
* specific struct drm_file object about to be closed. The caller is required
* to pass a list of all struct vmw_event_fence_action objects with such
* events attached. This function is typically called before the
* struct drm_file object's event management is taken down.
*/
void vmw_event_fence_fpriv_gone(struct vmw_fence_manager *fman,
struct list_head *event_list)
{
struct vmw_event_fence_action *eaction;
struct drm_pending_event *event;
unsigned long irq_flags;
while (1) {
spin_lock_irqsave(&fman->lock, irq_flags);
if (list_empty(event_list))
goto out_unlock;
eaction = list_first_entry(event_list,
struct vmw_event_fence_action,
fpriv_head);
list_del_init(&eaction->fpriv_head);
event = eaction->event;
eaction->event = NULL;
spin_unlock_irqrestore(&fman->lock, irq_flags);
event->destroy(event);
}
out_unlock:
spin_unlock_irqrestore(&fman->lock, irq_flags);
}
/** /**
* vmw_event_fence_action_seq_passed * vmw_event_fence_action_seq_passed
* *
@ -879,10 +840,8 @@ static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action)
*eaction->tv_usec = tv.tv_usec; *eaction->tv_usec = tv.tv_usec;
} }
list_del_init(&eaction->fpriv_head); drm_send_event_locked(dev, eaction->event);
list_add_tail(&eaction->event->link, &file_priv->event_list);
eaction->event = NULL; eaction->event = NULL;
wake_up_all(&file_priv->event_wait);
spin_unlock_irqrestore(&dev->event_lock, irq_flags); spin_unlock_irqrestore(&dev->event_lock, irq_flags);
} }
@ -899,12 +858,6 @@ static void vmw_event_fence_action_cleanup(struct vmw_fence_action *action)
{ {
struct vmw_event_fence_action *eaction = struct vmw_event_fence_action *eaction =
container_of(action, struct vmw_event_fence_action, action); container_of(action, struct vmw_event_fence_action, action);
struct vmw_fence_manager *fman = fman_from_fence(eaction->fence);
unsigned long irq_flags;
spin_lock_irqsave(&fman->lock, irq_flags);
list_del(&eaction->fpriv_head);
spin_unlock_irqrestore(&fman->lock, irq_flags);
vmw_fence_obj_unreference(&eaction->fence); vmw_fence_obj_unreference(&eaction->fence);
kfree(eaction); kfree(eaction);
@ -984,8 +937,6 @@ int vmw_event_fence_action_queue(struct drm_file *file_priv,
{ {
struct vmw_event_fence_action *eaction; struct vmw_event_fence_action *eaction;
struct vmw_fence_manager *fman = fman_from_fence(fence); struct vmw_fence_manager *fman = fman_from_fence(fence);
struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
unsigned long irq_flags;
eaction = kzalloc(sizeof(*eaction), GFP_KERNEL); eaction = kzalloc(sizeof(*eaction), GFP_KERNEL);
if (unlikely(eaction == NULL)) if (unlikely(eaction == NULL))
@ -1002,10 +953,6 @@ int vmw_event_fence_action_queue(struct drm_file *file_priv,
eaction->tv_sec = tv_sec; eaction->tv_sec = tv_sec;
eaction->tv_usec = tv_usec; eaction->tv_usec = tv_usec;
spin_lock_irqsave(&fman->lock, irq_flags);
list_add_tail(&eaction->fpriv_head, &vmw_fp->fence_events);
spin_unlock_irqrestore(&fman->lock, irq_flags);
vmw_fence_obj_add_action(fence, &eaction->action); vmw_fence_obj_add_action(fence, &eaction->action);
return 0; return 0;
@ -1025,38 +972,26 @@ static int vmw_event_fence_action_create(struct drm_file *file_priv,
struct vmw_event_fence_pending *event; struct vmw_event_fence_pending *event;
struct vmw_fence_manager *fman = fman_from_fence(fence); struct vmw_fence_manager *fman = fman_from_fence(fence);
struct drm_device *dev = fman->dev_priv->dev; struct drm_device *dev = fman->dev_priv->dev;
unsigned long irq_flags;
int ret; int ret;
spin_lock_irqsave(&dev->event_lock, irq_flags);
ret = (file_priv->event_space < sizeof(event->event)) ? -EBUSY : 0;
if (likely(ret == 0))
file_priv->event_space -= sizeof(event->event);
spin_unlock_irqrestore(&dev->event_lock, irq_flags);
if (unlikely(ret != 0)) {
DRM_ERROR("Failed to allocate event space for this file.\n");
goto out_no_space;
}
event = kzalloc(sizeof(*event), GFP_KERNEL); event = kzalloc(sizeof(*event), GFP_KERNEL);
if (unlikely(event == NULL)) { if (unlikely(event == NULL)) {
DRM_ERROR("Failed to allocate an event.\n"); DRM_ERROR("Failed to allocate an event.\n");
ret = -ENOMEM; ret = -ENOMEM;
goto out_no_event; goto out_no_space;
} }
event->event.base.type = DRM_VMW_EVENT_FENCE_SIGNALED; event->event.base.type = DRM_VMW_EVENT_FENCE_SIGNALED;
event->event.base.length = sizeof(*event); event->event.base.length = sizeof(*event);
event->event.user_data = user_data; event->event.user_data = user_data;
event->base.event = &event->event.base; ret = drm_event_reserve_init(dev, file_priv, &event->base, &event->event.base);
event->base.file_priv = file_priv;
event->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
if (unlikely(ret != 0)) {
DRM_ERROR("Failed to allocate event space for this file.\n");
kfree(event);
goto out_no_space;
}
if (flags & DRM_VMW_FE_FLAG_REQ_TIME) if (flags & DRM_VMW_FE_FLAG_REQ_TIME)
ret = vmw_event_fence_action_queue(file_priv, fence, ret = vmw_event_fence_action_queue(file_priv, fence,
@ -1076,11 +1011,7 @@ static int vmw_event_fence_action_create(struct drm_file *file_priv,
return 0; return 0;
out_no_queue: out_no_queue:
event->base.destroy(&event->base); drm_event_cancel_free(dev, &event->base);
out_no_event:
spin_lock_irqsave(&dev->event_lock, irq_flags);
file_priv->event_space += sizeof(*event);
spin_unlock_irqrestore(&dev->event_lock, irq_flags);
out_no_space: out_no_space:
return ret; return ret;
} }

View File

@ -116,8 +116,6 @@ extern int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern int vmw_fence_event_ioctl(struct drm_device *dev, void *data, extern int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern void vmw_event_fence_fpriv_gone(struct vmw_fence_manager *fman,
struct list_head *event_list);
extern int vmw_event_fence_action_queue(struct drm_file *filee_priv, extern int vmw_event_fence_action_queue(struct drm_file *filee_priv,
struct vmw_fence_obj *fence, struct vmw_fence_obj *fence,
struct drm_pending_event *event, struct drm_pending_event *event,

View File

@ -283,6 +283,7 @@ struct drm_ioctl_desc {
struct drm_pending_event { struct drm_pending_event {
struct drm_event *event; struct drm_event *event;
struct list_head link; struct list_head link;
struct list_head pending_link;
struct drm_file *file_priv; struct drm_file *file_priv;
pid_t pid; /* pid of requester, no guarantee it's valid by the time pid_t pid; /* pid of requester, no guarantee it's valid by the time
we deliver the event, for tracing only */ we deliver the event, for tracing only */
@ -346,6 +347,7 @@ struct drm_file {
struct list_head blobs; struct list_head blobs;
wait_queue_head_t event_wait; wait_queue_head_t event_wait;
struct list_head pending_event_list;
struct list_head event_list; struct list_head event_list;
int event_space; int event_space;
@ -919,15 +921,25 @@ extern long drm_compat_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags); extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags);
/* Device support (drm_fops.h) */ /* File Operations (drm_fops.c) */
extern int drm_open(struct inode *inode, struct file *filp); int drm_open(struct inode *inode, struct file *filp);
extern ssize_t drm_read(struct file *filp, char __user *buffer, ssize_t drm_read(struct file *filp, char __user *buffer,
size_t count, loff_t *offset); size_t count, loff_t *offset);
extern int drm_release(struct inode *inode, struct file *filp); int drm_release(struct inode *inode, struct file *filp);
extern int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv); int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv);
unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
/* Mapping support (drm_vm.h) */ int drm_event_reserve_init_locked(struct drm_device *dev,
extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); struct drm_file *file_priv,
struct drm_pending_event *p,
struct drm_event *e);
int drm_event_reserve_init(struct drm_device *dev,
struct drm_file *file_priv,
struct drm_pending_event *p,
struct drm_event *e);
void drm_event_cancel_free(struct drm_device *dev,
struct drm_pending_event *p);
void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e);
void drm_send_event(struct drm_device *dev, struct drm_pending_event *e);
/* Misc. IOCTL support (drm_ioctl.c) */ /* Misc. IOCTL support (drm_ioctl.c) */
int drm_noop(struct drm_device *dev, void *data, int drm_noop(struct drm_device *dev, void *data,