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:
commit
316e376b65
|
@ -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>
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) &&
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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,
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue