From 07096bd3c9d83f043c733c592974aa8ea93ba2db Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Thu, 14 Jan 2016 14:00:09 +0800 Subject: drm/crtc_helper/set_config: Remove redundant handling when set->fb is NULL We've done sanity NULL pointer check on set->fb at the beginning of drm_crtc_helper_set_config() and bailed out if necessary, thus any later on check or case handling is redundant. Signed-off-by: Liu Ying Link: http://patchwork.freedesktop.org/patch/msgid/1452751210-19216-1-git-send-email-gnuiyl@gmail.com Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index a02a7f9..63e8881 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -578,8 +578,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) if (set->crtc->primary->fb == NULL) { DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); mode_changed = true; - } else if (set->fb == NULL) { - mode_changed = true; } else if (set->fb->pixel_format != set->crtc->primary->fb->pixel_format) { mode_changed = true; -- cgit v0.10.2 From 2deafc7e163be631183bdfc066e2f636e7818e00 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Thu, 14 Jan 2016 14:00:10 +0800 Subject: drm/crtc_helper/set_config: Remove redundant NULL pointer check on set->mode We've done sanity NULL pointer check on set->mode at the beginning of drm_crtc_helper_set_config() and bailed out if necessary, thus any later on check is redundant. Signed-off-by: Liu Ying Link: http://patchwork.freedesktop.org/patch/msgid/1452751210-19216-2-git-send-email-gnuiyl@gmail.com Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 63e8881..5d4bc64 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -588,7 +588,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) if (set->x != set->crtc->x || set->y != set->crtc->y) 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_mode_debug_printmodeline(&set->crtc->mode); drm_mode_debug_printmodeline(set->mode); -- cgit v0.10.2 From c6c5c7fa7f3ec7d35541e9e4c6feb4ccd6cca7c9 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 18 Jan 2016 11:36:35 +0800 Subject: drm/atomic-helper: Remove redundant local var old_crtc_state in disable_outputs One of the two local variables old_crtc_state is redundantly defined in the function disable_outputs(). It has only a scope partway through the block for_each_connector_in_state. So, let's remove it and use the one which has the scope within the function disable_outputs(). Signed-off-by: Liu Ying Link: http://patchwork.freedesktop.org/patch/msgid/1453088195-2564-1-git-send-email-gnuiyl@gmail.com Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 57cccd6..b9d8b53 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -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) { const struct drm_encoder_helper_funcs *funcs; struct drm_encoder *encoder; - struct drm_crtc_state *old_crtc_state; /* Shut down everything that's in the changeset and currently * still on. So need to check the old, saved state. */ -- cgit v0.10.2 From 25aaa3a1e5dba6256fd4a548f088ee1ebbc4b5f8 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 19 Jan 2016 09:26:48 +0100 Subject: drm: initialize default rotation value to DRM_ROTATE_0 When no console framebuffer is enabled, the default plane state is defined by plane reset function. If driver uses generic helper, then rotation property is set to zero. This is not a valid value for that enum. This patch sets default rotation value to DRM_ROTATE_0. Signed-off-by: Marek Szyprowski Link: http://patchwork.freedesktop.org/patch/msgid/1453192008-13283-1-git-send-email-m.szyprowski@samsung.com Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index b9d8b53..f0c3984 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2532,8 +2532,10 @@ void drm_atomic_helper_plane_reset(struct drm_plane *plane) kfree(plane->state); plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL); - if (plane->state) + if (plane->state) { plane->state->plane = plane; + plane->state->rotation = BIT(DRM_ROTATE_0); + } } EXPORT_SYMBOL(drm_atomic_helper_plane_reset); -- cgit v0.10.2 From 70c0616d5a8458ae9148d74309cede07ba2f5164 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 20 Jan 2016 10:59:34 +0000 Subject: drm/fb_cma_helper: remove duplicate const from drm_fb_cma_alloc Duplicated const, only one is required. Also reformat line to ensure it is less than 80 columns wide. Signed-off-by: Colin Ian King Link: http://patchwork.freedesktop.org/patch/msgid/1453287574-3645-1-git-send-email-colin.king@canonical.com Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index c895b6f..bb88e3d 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -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, - 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) { struct drm_fb_cma *fb_cma; -- cgit v0.10.2 From 40f8cf4b5cb606c593be25cbf71c34d505815b90 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 22 Jan 2016 08:53:45 +0100 Subject: drm/fbdev-helper: Explain how to debug console_lock fun Every new KMS driver writer seems to run into this and wonder how exactly drm_fb_helper_initial_config can die doing nothing at all. Set up some big warnings signs around this newbie trap to avoid future frustration and wasting everyone's time. v2: Edits from Laurent. Cc: Carlos Palminha Cc: Xinliang Liu Cc: laurent.pinchart@ideasonboard.com Reviewed-by: Laurent Pinchart Link: http://patchwork.freedesktop.org/patch/msgid/1453449225-10954-1-git-send-email-daniel.vetter@ffwll.ch Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 1e103c4..76a364e 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -2091,6 +2091,27 @@ out: * drm_fb_helper_fill_fix() are provided as helpers to setup simple default * 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: * Zero if everything went ok, nonzero otherwise. */ -- cgit v0.10.2 From bcb877e4dcf21c3ba486fd7cc563126f08c39b8a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Jan 2016 22:40:55 +0100 Subject: drm: kerneldoc for drm_fops.c Just prep work before I throw more drm_event refactorings on top. Acked-by: Daniel Stone Reviewed-by: Alex Deucher Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-2-git-send-email-daniel.vetter@ffwll.ch Signed-off-by: Daniel Vetter diff --git a/Documentation/DocBook/gpu.tmpl b/Documentation/DocBook/gpu.tmpl index a866933..12731c2 100644 --- a/Documentation/DocBook/gpu.tmpl +++ b/Documentation/DocBook/gpu.tmpl @@ -2886,52 +2886,8 @@ void (*postclose) (struct drm_device *, struct drm_file *); File Operations - const struct file_operations *fops - File operations for the DRM device node. - - 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 open, - release and ioctl - operations are handled by - - .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - #ifdef CONFIG_COMPAT - .compat_ioctl = drm_compat_ioctl, - #endif - - - - Drivers that implement private ioctls that requires 32/64bit - compatibility support must provide their own - compat_ioctl handler that processes private - ioctls and calls drm_compat_ioctl for core ioctls. - - - The read and poll - operations provide support for reading DRM events and polling them. They - are implemented by - - .poll = drm_poll, - .read = drm_read, - .llseek = no_llseek, - - - - The memory mapping implementation varies depending on how the driver - manages memory. Pre-GEM drivers will use drm_mmap, - while GEM-aware drivers will use drm_gem_mmap. See - . - - .mmap = drm_gem_mmap, - - - - No other file operation is supported by the DRM API. - +!Pdrivers/gpu/drm/drm_fops.c file operations +!Edrivers/gpu/drm/drm_fops.c IOCTLs diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 1ea8790..1551d65 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -1,4 +1,4 @@ -/** +/* * \file drm_fops.c * File operations for DRM * @@ -44,6 +44,46 @@ /* from BKL pushdown */ 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_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 - * \param filp file pointer. - * \return zero on success or a negative number on failure. + * This function must be used by drivers as their .open() #file_operations + * method. It looks up the correct DRM device and instantiates all the per-file + * resources for it. + * + * RETURNS: * - * Searches the DRM device with the same minor number, calls open_helper(), and - * 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) { @@ -112,7 +154,7 @@ err_undo: } EXPORT_SYMBOL(drm_open); -/** +/* * Check whether DRI will run on this CPU. * * \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; } -/** +/* * drm_new_set_master - Allocate a new master object and become master for the * associated master realm. * @@ -179,7 +221,7 @@ out_err: return ret; } -/** +/* * Called whenever a process opens /dev/drm. * * \param filp file pointer. @@ -333,7 +375,7 @@ static void drm_events_release(struct drm_file *file_priv) spin_unlock_irqrestore(&dev->event_lock, flags); } -/** +/* * drm_legacy_dev_reinit * * Reinitializes a legacy/ums drm device in it's lastclose function. @@ -350,7 +392,7 @@ static void drm_legacy_dev_reinit(struct drm_device *dev) dev->if_version = 0; } -/** +/* * Take down the DRM device. * * \param dev DRM device structure. @@ -387,16 +429,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 - * \param file_priv DRM file private. - * \return zero on success or a negative number on failure. + * This function must be used by drivers as their .release() #file_operations + * method. It frees any resources associated with the open file, and if this is + * 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 - * 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 - * zero calls drm_lastclose(). + * RETURNS: + * + * Always succeeds and returns 0. */ int drm_release(struct inode *inode, struct file *filp) { @@ -451,7 +494,7 @@ int drm_release(struct inode *inode, struct file *filp) if (file_priv->is_master) { struct drm_master *master = file_priv->master; - /** + /* * Since the master is disappearing, so is the * possibility to lock. */ @@ -508,6 +551,32 @@ int drm_release(struct inode *inode, struct file *filp) } 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, size_t count, loff_t *offset) { @@ -578,6 +647,22 @@ put_back_event: } 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) { struct drm_file *file_priv = filp->private_data; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index d7162cf..a46a34f 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -919,15 +919,14 @@ extern long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags); - /* Device support (drm_fops.h) */ -extern int drm_open(struct inode *inode, struct file *filp); -extern ssize_t drm_read(struct file *filp, char __user *buffer, - size_t count, loff_t *offset); -extern int drm_release(struct inode *inode, struct file *filp); -extern int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv); - - /* Mapping support (drm_vm.h) */ -extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); +/* File Operations (drm_fops.c) */ +int drm_open(struct inode *inode, struct file *filp); +ssize_t drm_read(struct file *filp, char __user *buffer, + size_t count, loff_t *offset); +int drm_release(struct inode *inode, struct file *filp); +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); /* Misc. IOCTL support (drm_ioctl.c) */ int drm_noop(struct drm_device *dev, void *data, -- cgit v0.10.2 From 2dd500f1870e3d852488c9b30c4ecec91c6e2eea Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Jan 2016 22:40:56 +0100 Subject: drm: Add functions to setup/tear down drm_events. An attempt at not spreading out the file_priv->event_space stuff out quite so far and wide. And I think fixes something in ipp_get_event() that is broken (or if they are doing something more weird/subtle, then breaks it in a fun way). Based upon a patch from Rob Clark, rebased and polished. v2: Spelling fixes (Alex). Cc: Alex Deucher Acked-by: Daniel Stone Reviewed-by: Alex Deucher Cc: Rob Clark Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-3-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Laurent Pinchart Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 3f74193..8fb469c 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1347,44 +1347,23 @@ static struct drm_pending_vblank_event *create_vblank_event( struct drm_device *dev, struct drm_file *file_priv, uint64_t user_data) { struct drm_pending_vblank_event *e = NULL; - unsigned long flags; - - 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); + int ret; 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; - } + if (!e) + return NULL; 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->base.event = &e->event.base; - e->base.file_priv = file_priv; - e->base.destroy = (void (*) (struct drm_pending_event *)) kfree; - -out: - 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; + ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base); + if (ret) { + kfree(e); + return NULL; + } - spin_lock_irqsave(&dev->event_lock, flags); - file_priv->event_space += sizeof e->event; - spin_unlock_irqrestore(&dev->event_lock, flags); - kfree(e); + return e; } static int atomic_set_prop(struct drm_atomic_state *state, @@ -1646,8 +1625,7 @@ out: if (!crtc_state->event) continue; - destroy_vblank_event(dev, file_priv, - crtc_state->event); + drm_event_cancel_free(dev, &crtc_state->event->base); } } diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index d40bab2..6e6514e 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -5265,7 +5265,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, struct drm_crtc *crtc; struct drm_framebuffer *fb = NULL; struct drm_pending_vblank_event *e = NULL; - unsigned long flags; int ret = -EINVAL; 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) { - ret = -ENOMEM; - 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); - if (e == NULL) { - spin_lock_irqsave(&dev->event_lock, flags); - file_priv->event_space += sizeof(e->event); - spin_unlock_irqrestore(&dev->event_lock, flags); + e = kzalloc(sizeof *e, GFP_KERNEL); + if (!e) { + ret = -ENOMEM; goto out; } - e->event.base.type = DRM_EVENT_FLIP_COMPLETE; e->event.base.length = sizeof(e->event); e->event.user_data = page_flip->user_data; - e->base.event = &e->event.base; - e->base.file_priv = file_priv; - e->base.destroy = - (void (*) (struct drm_pending_event *)) kfree; + ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base); + if (ret) { + kfree(e); + goto out; + } } crtc->primary->old_fb = crtc->primary->fb; ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags); if (ret) { - if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { - spin_lock_irqsave(&dev->event_lock, flags); - file_priv->event_space += sizeof(e->event); - spin_unlock_irqrestore(&dev->event_lock, flags); - kfree(e); - } + if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) + drm_event_cancel_free(dev, &e->base); /* Keep the old fb, don't unref it. */ crtc->primary->old_fb = NULL; } else { diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 1551d65..f9eacbb 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -676,3 +676,70 @@ unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) return mask; } EXPORT_SYMBOL(drm_poll); + +/** + * 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(). + * + * If callers embedded @p into a larger structure it must be allocated with + * kmalloc and @p must be the first member element. + * + * 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 = 0; + + spin_lock_irqsave(&dev->event_lock, flags); + + if (file_priv->event_space < e->length) { + ret = -ENOMEM; + goto out; + } + + file_priv->event_space -= e->length; + + p->event = e; + p->file_priv = file_priv; + + /* we *could* pass this in as arg, but everyone uses kfree: */ + p->destroy = (void (*) (struct drm_pending_event *)) kfree; + +out: + 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); + p->file_priv->event_space += p->event->length; + spin_unlock_irqrestore(&dev->event_lock, flags); + p->destroy(p); +} +EXPORT_SYMBOL(drm_event_cancel_free); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index a46a34f..04a6646 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -925,8 +925,13 @@ ssize_t drm_read(struct file *filp, char __user *buffer, size_t count, loff_t *offset); int drm_release(struct inode *inode, struct file *filp); 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); +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); /* Misc. IOCTL support (drm_ioctl.c) */ int drm_noop(struct drm_device *dev, void *data, -- cgit v0.10.2 From 7142a348e7714102ec705cca5fa2e092f29f4834 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Jan 2016 22:40:57 +0100 Subject: drm/exynos: Use the new event init/free functions Also fixes a bug in IPP with not correctly checking/allocating for space in the event space. Not a too serious bug since it's not a real ringbuffer, just a limit to avoid too much kernel allocations. Cc: Rob Clark Cc: Inki Dae Acked-by: Daniel Stone Reviewed-by: Alex Deucher Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-4-git-send-email-daniel.vetter@ffwll.ch Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index c17efdb..82e7f95 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -1072,7 +1072,6 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, struct drm_exynos_pending_g2d_event *e; struct g2d_cmdlist_node *node; struct g2d_cmdlist *cmdlist; - unsigned long flags; int size; int ret; @@ -1094,21 +1093,8 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, node->event = NULL; 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); 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; goto err; } @@ -1116,9 +1102,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.length = sizeof(e->event); e->event.user_data = req->user_data; - e->base.event = &e->event.base; - e->base.file_priv = file; - e->base.destroy = (void (*) (struct drm_pending_event *)) kfree; + + ret = drm_event_reserve_init(drm_dev, file, &e->base, &e->event.base); + if (ret) { + kfree(e); + goto err; + } node->event = e; } @@ -1219,12 +1208,8 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, err_unmap: g2d_unmap_cmdlist_gem(g2d, node, file); err_free_event: - if (node->event) { - spin_lock_irqsave(&drm_dev->event_lock, flags); - file->event_space += sizeof(e->event); - spin_unlock_irqrestore(&drm_dev->event_lock, flags); - kfree(node->event); - } + if (node->event) + drm_event_cancel_free(drm_dev, &node->event->base); err: g2d_put_cmdlist(g2d, node); return ret; diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index 67d2423..c8819c0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -618,27 +618,18 @@ static void ipp_clean_mem_nodes(struct drm_device *drm_dev, 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, struct drm_exynos_ipp_cmd_node *c_node, struct drm_exynos_ipp_queue_buf *qbuf) { 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); e = kzalloc(sizeof(*e), GFP_KERNEL); - 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); + if (!e) return -ENOMEM; - } /* make 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.prop_id = qbuf->prop_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; - e->base.destroy = ipp_free_event; + + ret = drm_event_reserve_init(drm_dev, c_node->filp, &e->base, &e->event.base); + if (ret) { + kfree(e); + return ret; + } + mutex_lock(&c_node->event_lock); list_add_tail(&e->base.link, &c_node->event_list); mutex_unlock(&c_node->event_lock); -- cgit v0.10.2 From 6d3729ac1332e3b63b7a140d29fb60ef77d61af6 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Jan 2016 22:40:58 +0100 Subject: drm/vmwgfx: Use the new event init/free functions Cc: Rob Clark Acked-by: Daniel Stone Reviewed-by: Alex Deucher Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-5-git-send-email-daniel.vetter@ffwll.ch Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index 8e689b4..eda93bf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -1025,38 +1025,26 @@ static int vmw_event_fence_action_create(struct drm_file *file_priv, struct vmw_event_fence_pending *event; struct vmw_fence_manager *fman = fman_from_fence(fence); struct drm_device *dev = fman->dev_priv->dev; - unsigned long irq_flags; 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); if (unlikely(event == NULL)) { DRM_ERROR("Failed to allocate an event.\n"); ret = -ENOMEM; - goto out_no_event; + goto out_no_space; } event->event.base.type = DRM_VMW_EVENT_FENCE_SIGNALED; event->event.base.length = sizeof(*event); event->event.user_data = user_data; - event->base.event = &event->event.base; - event->base.file_priv = file_priv; - event->base.destroy = (void (*) (struct drm_pending_event *)) kfree; + ret = drm_event_reserve_init(dev, file_priv, &event->base, &event->event.base); + 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) ret = vmw_event_fence_action_queue(file_priv, fence, @@ -1076,11 +1064,7 @@ static int vmw_event_fence_action_create(struct drm_file *file_priv, return 0; out_no_queue: - event->base.destroy(&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); + drm_event_cancel_free(dev, &event->base); out_no_space: return ret; } -- cgit v0.10.2 From fb740cf2492cc1e8f2216bc5ad9f5b2c49a32752 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Jan 2016 22:40:59 +0100 Subject: drm: Create drm_send_event helpers Use them in the core vblank code and exynos/vmwgfx drivers. Note that the difference between wake_up_all and _interruptible in vmwgfx doesn't matter since the only waiter is the core code in drm_fops.c. And that is interruptible. v2: Adjust existing kerneldoc too. Reviewed-by: Alex Deucher (v1) Acked-by: Daniel Stone Cc: Alex Deucher Cc: Thomas Hellstrom Cc: Inki Dae Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-6-git-send-email-daniel.vetter@ffwll.ch Reviewed-by: Laurent Pinchart [danvet: Squash in compile fixup, spotted by 0-day.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index f9eacbb..e13501e 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -687,7 +687,9 @@ EXPORT_SYMBOL(drm_poll); * 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(). + * 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. @@ -743,3 +745,41 @@ void drm_event_cancel_free(struct drm_device *dev, 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. + */ +void drm_send_event_locked(struct drm_device *dev, struct drm_pending_event *e) +{ + assert_spin_locked(&dev->event_lock); + + 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. + */ +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); diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index d12a4ef..4ec8bca 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -983,15 +983,12 @@ static void send_vblank_event(struct drm_device *dev, struct drm_pending_vblank_event *e, unsigned long seq, struct timeval *now) { - assert_spin_locked(&dev->event_lock); - e->event.sequence = seq; e->event.tv_sec = now->tv_sec; e->event.tv_usec = now->tv_usec; - list_add_tail(&e->base.link, - &e->base.file_priv->event_list); - wake_up_interruptible(&e->base.file_priv->event_wait); + drm_send_event_locked(dev, &e->base); + trace_drm_vblank_event_delivered(e->base.pid, e->pipe, e->event.sequence); } diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 82e7f95..9936981 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -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 drm_exynos_pending_g2d_event *e; struct timeval now; - unsigned long flags; if (list_empty(&runqueue_node->event_list)) 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.cmdlist_no = cmdlist_no; - spin_lock_irqsave(&drm_dev->event_lock, flags); - 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); + drm_send_event(drm_dev, &e->base); } static irqreturn_t g2d_irq_handler(int irq, void *dev_id) diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index c8819c0..3eab0d1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -1407,7 +1407,6 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv, struct drm_exynos_ipp_send_event *e; struct list_head *head; struct timeval now; - unsigned long flags; u32 tbuf_id[EXYNOS_DRM_OPS_MAX] = {0, }; int ret, i; @@ -1520,10 +1519,7 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv, for_each_ipp_ops(i) e->event.buf_id[i] = tbuf_id[i]; - spin_lock_irqsave(&drm_dev->event_lock, flags); - 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); + drm_send_event(drm_dev, &e->base); mutex_unlock(&c_node->event_lock); DRM_DEBUG_KMS("done cmd[%d]prop_id[%d]buf_id[%d]\n", diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index eda93bf..e0edf14 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -880,9 +880,8 @@ static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action) } list_del_init(&eaction->fpriv_head); - list_add_tail(&eaction->event->link, &file_priv->event_list); eaction->event = NULL; - wake_up_all(&file_priv->event_wait); + drm_send_event_locked(dev, eaction->event); spin_unlock_irqrestore(&dev->event_lock, irq_flags); } diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 04a6646..306ef32 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -932,6 +932,8 @@ int drm_event_reserve_init(struct drm_device *dev, 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) */ int drm_noop(struct drm_device *dev, void *data, -- cgit v0.10.2 From 0b5ef656f764e6cc1fe1e0aaf080a19560f2f76a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Jan 2016 22:41:00 +0100 Subject: drm/fsl: Remove preclose hook Doesn't do anything, but annoys when auditing them all. Cc: Jianwei Wang Acked-by: Daniel Stone Reviewed-by: Alex Deucher Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-7-git-send-email-daniel.vetter@ffwll.ch Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c index fca97d3..9648b7f 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c @@ -112,10 +112,6 @@ static int fsl_dcu_unload(struct drm_device *dev) 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) { struct drm_device *dev = arg; @@ -191,7 +187,6 @@ static struct drm_driver fsl_dcu_drm_driver = { | DRIVER_PRIME | DRIVER_ATOMIC, .load = fsl_dcu_load, .unload = fsl_dcu_unload, - .preclose = fsl_dcu_drm_preclose, .irq_handler = fsl_dcu_drm_irq, .get_vblank_counter = drm_vblank_no_hw_counter, .enable_vblank = fsl_dcu_drm_enable_vblank, -- cgit v0.10.2 From d704f8e1a649a6dc1cca693846df96e54d80744f Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Jan 2016 22:41:01 +0100 Subject: drm/armada: Remove NULL open/pre/postclose hooks The compiler will do this, but the void hits when grepping all the hooks for a subsystem wide audit are slightly annoying. So remove them for next time around. Cc: Russell King Acked-by: Daniel Stone Reviewed-by: Alex Deucher Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-8-git-send-email-daniel.vetter@ffwll.ch Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 3bd7e1c..82043c2 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -188,9 +188,6 @@ static const struct file_operations armada_drm_fops = { static struct drm_driver armada_drm_driver = { .load = armada_drm_load, - .open = NULL, - .preclose = NULL, - .postclose = NULL, .lastclose = armada_drm_lastclose, .unload = armada_drm_unload, .set_busid = drm_platform_set_busid, -- cgit v0.10.2 From 941a77b078e6127c4d441439ad1669347750288e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 11 Jan 2016 22:41:02 +0100 Subject: drm/gma500: Remove empty preclose hook I'm auditing them all, empty ones just confuse ... Cc: Patrik Jakobsson Acked-by: Daniel Stone Reviewed-by: Alex Deucher Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-9-git-send-email-daniel.vetter@ffwll.ch Acked-by: Patrik Jakobsson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 92e7e57..4e1c685 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -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 */ } -/* - * 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) { return drm_get_pci_dev(pdev, ent, &driver); @@ -495,7 +487,6 @@ static struct drm_driver driver = { .load = psb_driver_load, .unload = psb_driver_unload, .lastclose = psb_driver_lastclose, - .preclose = psb_driver_preclose, .set_busid = drm_pci_set_busid, .num_ioctls = ARRAY_SIZE(psb_ioctls), -- cgit v0.10.2 From 09859d2a3c2090ae2452cbf1c8fdde30ba38d934 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 13 Jan 2016 15:31:16 +0100 Subject: drm/crtc-helper: Add caveat to disable_unused_functions doc This shouldn't be used by atomic drivers any more, it confuses the state tracking. Cc: Maxime Ripard Cc: Laurent Pinchart Acked-by: Laurent Pinchart Link: http://patchwork.freedesktop.org/patch/msgid/1452695476-31147-1-git-send-email-daniel.vetter@ffwll.ch Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 5d4bc64..9f8b894 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -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 * either by calling their disable callback if available or by calling their * 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) { -- cgit v0.10.2 From 15b6b804b6e43297d9c05306554a39d8891966f9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 28 Jan 2016 12:06:46 +0300 Subject: drm/vmwgfx: fix a NULL dereference We dereference "eaction->event" inside the call to drm_send_event_locked() so should hold off on setting it to NULL until afterward. Fixes: fb740cf2492c ("drm: Create drm_send_event helpers") Signed-off-by: Dan Carpenter Link: http://patchwork.freedesktop.org/patch/msgid/20160128090646.GA5824@mwanda Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index e0edf14..37c305b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -880,8 +880,8 @@ static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action) } list_del_init(&eaction->fpriv_head); - eaction->event = NULL; drm_send_event_locked(dev, eaction->event); + eaction->event = NULL; spin_unlock_irqrestore(&dev->event_lock, irq_flags); } -- cgit v0.10.2 From 4020b220edb3419975c0d9322ee0e0c07e09f6bf Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 28 Jan 2016 12:01:04 +0100 Subject: drm/vblank: Use drm_event_reserve_init Well we can't use that directly since that code must hold dev->event_lock already. Extract an _unlocked version. Embarrassingly I've totally forgotten about this patch and any kind of event-based vblank wait totally blew up, killing the kernel. v2: Pick the right base struct, someone didn't noticed that gcc was unhappy. No bug since the addresses at least matched (Daniel Stone) Cc: Alex Deucher Cc: Daniel Stone Cc: Laurent Pinchart Reviewed-by: Daniel Stone Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453978864-1513-1-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index e13501e..eb6a02f 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -678,7 +678,7 @@ unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) EXPORT_SYMBOL(drm_poll); /** - * drm_event_reserve_init - init a DRM event and reserve space for it + * 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 @@ -694,24 +694,20 @@ EXPORT_SYMBOL(drm_poll); * 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(struct drm_device *dev, - struct drm_file *file_priv, - struct drm_pending_event *p, - struct drm_event *e) +int drm_event_reserve_init_locked(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_pending_event *p, + struct drm_event *e) { - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&dev->event_lock, flags); - - if (file_priv->event_space < e->length) { - ret = -ENOMEM; - goto out; - } + if (file_priv->event_space < e->length) + return -ENOMEM; file_priv->event_space -= e->length; @@ -721,8 +717,46 @@ int drm_event_reserve_init(struct drm_device *dev, /* we *could* pass this in as arg, but everyone uses kfree: */ p->destroy = (void (*) (struct drm_pending_event *)) kfree; -out: + 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); diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 4ec8bca..96d03ac 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -1598,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.length = sizeof(e->event); 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); @@ -1616,12 +1613,12 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, goto err_unlock; } - if (file_priv->event_space < sizeof(e->event)) { - ret = -EBUSY; + ret = drm_event_reserve_init_locked(dev, file_priv, &e->base, + &e->event.base); + + if (ret) goto err_unlock; - } - file_priv->event_space -= sizeof(e->event); seq = drm_vblank_count_and_time(dev, pipe, &now); if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) && diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 306ef32..1b71852 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -926,6 +926,10 @@ ssize_t drm_read(struct file *filp, char __user *buffer, int drm_release(struct inode *inode, struct file *filp); 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); +int drm_event_reserve_init_locked(struct drm_device *dev, + 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, -- cgit v0.10.2 From 681047b48601841c8380abd406301648c3590592 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 25 Jan 2016 22:16:43 +0100 Subject: drm: Clean up pending events in the core There's really no reason to not do so, instead of replicating this for every use-case and every driver. Now we can't just nuke the events, since that would still mean that all drm_event users would need to know when that has happened, since calling e.g. drm_send_event isn't allowed any more. Instead just unlink them from the file, and detect this case and handle it appropriately in all functions. v2: Adjust existing kerneldoc too. v3: Improve wording of the kerneldoc and split out vblank cleanup (Laurent). Cc: Alex Deucher Cc: Laurent Pinchart Acked-by: Daniel Stone Reviewed-by: Alex Deucher (v1) Reviewed-by: Laurent Pinchart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453756616-28942-2-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index eb6a02f..afe8c53 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -264,6 +264,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor) INIT_LIST_HEAD(&priv->fbs); mutex_init(&priv->fbs_lock); INIT_LIST_HEAD(&priv->blobs); + INIT_LIST_HEAD(&priv->pending_event_list); INIT_LIST_HEAD(&priv->event_list); init_waitqueue_head(&priv->event_wait); priv->event_space = 4096; /* set aside 4k for event buffer */ @@ -366,6 +367,13 @@ static void drm_events_release(struct drm_file *file_priv) v->base.destroy(&v->base); } + /* Unlink pending events */ + list_for_each_entry_safe(e, et, &file_priv->pending_event_list, + pending_link) { + list_del(&e->pending_link); + e->file_priv = NULL; + } + /* Remove unconsumed events */ list_for_each_entry_safe(e, et, &file_priv->event_list, link) { list_del(&e->link); @@ -712,6 +720,7 @@ int drm_event_reserve_init_locked(struct drm_device *dev, 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: */ @@ -774,7 +783,10 @@ void drm_event_cancel_free(struct drm_device *dev, { unsigned long flags; spin_lock_irqsave(&dev->event_lock, flags); - p->file_priv->event_space += p->event->length; + 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); } @@ -788,11 +800,22 @@ EXPORT_SYMBOL(drm_event_cancel_free); * 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); @@ -807,6 +830,11 @@ EXPORT_SYMBOL(drm_send_event_locked); * 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) { diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 1b71852..3c8422c 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -283,6 +283,7 @@ struct drm_ioctl_desc { struct drm_pending_event { struct drm_event *event; struct list_head link; + struct list_head pending_link; struct drm_file *file_priv; pid_t pid; /* pid of requester, no guarantee it's valid by the time we deliver the event, for tracing only */ @@ -346,6 +347,7 @@ struct drm_file { struct list_head blobs; wait_queue_head_t event_wait; + struct list_head pending_event_list; struct list_head event_list; int event_space; -- cgit v0.10.2 From 7eb98020b73e20ce18d3ed704d7b7988ddad5dfd Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 25 Jan 2016 22:16:44 +0100 Subject: drm: Nuke vblank event file cleanup code The core code now takes care of unlinking drm_events from the file in a generic way, so this code isn't needed any more. For those wondering where the drm_vblank_put went to: With the new logic events only get unlinked, but still exist. Hence any resources (like vblank counters) don't need to be released since the event user will still process the event normally. In this case this is the callsites of send_vblank_event, which of course already have a drm_vblank_put. Cc: Laurent Pinchart Acked-by: Daniel Stone Reviewed-by: Alex Deucher Reviewed-by: Laurent Pinchart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453756616-28942-3-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index afe8c53..aeef58e 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -354,19 +354,10 @@ static void drm_events_release(struct drm_file *file_priv) { struct drm_device *dev = file_priv->minor->dev; struct drm_pending_event *e, *et; - struct drm_pending_vblank_event *v, *vt; unsigned long flags; spin_lock_irqsave(&dev->event_lock, flags); - /* Remove pending flips */ - list_for_each_entry_safe(v, vt, &dev->vblank_event_list, base.link) - if (v->base.file_priv == file_priv) { - list_del(&v->base.link); - drm_vblank_put(dev, v->pipe); - v->base.destroy(&v->base); - } - /* Unlink pending events */ list_for_each_entry_safe(e, et, &file_priv->pending_event_list, pending_link) { -- cgit v0.10.2 From 00648f18e0fd48b2452200659ce8610d4d2f8060 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 25 Jan 2016 22:16:45 +0100 Subject: drm/i915: Nuke intel_modeset_preclose Now that the drm core unlinks/disarms events there's no need to do so ourselves anymore. Nuke the code. Acked-by: Daniel Stone Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453756616-28942-4-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index d70d96f..1c3d254 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1261,8 +1261,6 @@ void i915_driver_preclose(struct drm_device *dev, struct drm_file *file) i915_gem_context_close(dev, file); i915_gem_release(dev, file); mutex_unlock(&dev->struct_mutex); - - intel_modeset_preclose(dev, file); } void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 580d094..8816ba1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -16140,24 +16140,3 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, 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); - } -} diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ea54158..98e4345 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1207,7 +1207,6 @@ enum intel_display_power_domain intel_display_port_aux_power_domain(struct intel_encoder *intel_encoder); void intel_mode_from_pipe_config(struct drm_display_mode *mode, 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_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state); -- cgit v0.10.2 From 9c333c28838f9ceaa0fdb66747da3bdc1fcec53c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 25 Jan 2016 22:16:46 +0100 Subject: drm/atmel: Nuke preclose The only thing this did was cancle pending flip events, and the core takes care of that now. Cc: Boris Brezillon Acked-by: Daniel Stone Reviewed-by: Alex Deucher Acked-by: Boris Brezillon Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453756616-28942-5-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index 468a14f..9863291 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -280,24 +280,6 @@ static void atmel_hlcdc_crtc_destroy(struct drm_crtc *c) 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) { struct drm_device *dev = crtc->base.dev; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index a45b32b..3d8d164 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -619,15 +619,6 @@ static void atmel_hlcdc_dc_connector_unplug_all(struct drm_device *dev) 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) { 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_MODESET | DRIVER_PRIME | DRIVER_ATOMIC, - .preclose = atmel_hlcdc_dc_preclose, .lastclose = atmel_hlcdc_dc_lastclose, .irq_handler = atmel_hlcdc_dc_irq_handler, .irq_preinstall = atmel_hlcdc_dc_irq_uninstall, diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h index cf6b375..fed517f 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h @@ -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_cancel_page_flip(struct drm_crtc *crtc, - struct drm_file *file); - void atmel_hlcdc_crtc_suspend(struct drm_crtc *crtc); void atmel_hlcdc_crtc_resume(struct drm_crtc *crtc); -- cgit v0.10.2 From 84b29a553e90d7933d9ada64302ae30d4a9084fd Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 25 Jan 2016 22:16:47 +0100 Subject: drm/exynos: Remove event cancelling from postclose The core takes care of this now. And since kfree(NULL) is ok we can simplify the function even further now. Note: There's another spin on this patch, but for different reasons, in-flight already: http://www.spinics.net/lists/dri-devel/msg97922.html Cc: Inki Dae Acked-by: Daniel Stone Reviewed-by: Alex Deucher Acked-by: Inki Dae Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453756616-28942-6-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 68f0f36..1e535f9 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -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) { - 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); file->driver_priv = NULL; } -- cgit v0.10.2 From 4eced321bf3d2f45b9dd221ba806a9b3c7d3a67a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 25 Jan 2016 22:16:48 +0100 Subject: drm/imx: Unconfuse preclose logic So this one is special, since it tries to prevent races when userspace crashes simply by disabling the vblank machinery. Well except that imx always has vblanks enabled, and the disable_vblank hook actually just tries to cancel a pending pageflip. Without any locking whatsoever. Of course this is wrong, since it'll result in the hw not actually displaying what drm thinks is the current frontbuffer. Well since the core takes care of the disappearing DRM fd now. So we can nuke all this confused code without ill side-effects. Someone else needs to audit the locking for ->newfb and ->page_flip_event and fix it up. Common approach is to reuse dev->event_lock for this. Cc: Sascha Hauer Cc: Philipp Zabel Acked-by: Daniel Stone Reviewed-by: Alex Deucher Acked-by: Philipp Zabel Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453756616-28942-7-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index 2f57d79..7c4d125 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -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); } -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 = { .owner = THIS_MODULE, .open = drm_open, @@ -463,7 +451,6 @@ static struct drm_driver imx_drm_driver = { .load = imx_drm_driver_load, .unload = imx_drm_driver_unload, .lastclose = imx_drm_driver_lastclose, - .preclose = imx_drm_driver_preclose, .set_busid = drm_platform_set_busid, .gem_free_object = drm_gem_cma_free_object, .gem_vm_ops = &drm_gem_cma_vm_ops, diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index 30a5718..846b5f5 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -285,10 +285,6 @@ static int ipu_enable_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, -- cgit v0.10.2 From 53190c7194d9a8337fe419134e44c30eb63ebd08 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 25 Jan 2016 22:16:49 +0100 Subject: drm/msm: Nuke preclose hooks They only complete the page flip events to avoid oops when the drm file closes. The core takes care of that now and we can remove this code. Cc: Rob Clark Acked-by: Daniel Stone Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453756616-28942-8-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index 28df397..909d742 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c @@ -575,13 +575,6 @@ uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc) 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. */ void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config) { diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c index 5a8e3d6..1c8e330 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c @@ -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) { 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, .get_format = mdp_get_format, .round_pixclk = mdp4_round_pixclk, - .preclose = mdp4_preclose, .destroy = mdp4_destroy, }, .set_irqmask = mdp4_set_irqmask, diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h index d2c96ef..9ec53b4 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h @@ -199,7 +199,6 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev, enum mdp4_pipe pipe_id, bool private_plane); 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_intf(struct drm_crtc *crtc, enum mdp4_intf intf, int mixer); void mdp4_crtc_wait_for_commit_done(struct drm_crtc *crtc); diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 20cee5c..46682aa 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -721,12 +721,6 @@ uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc) 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, struct mdp5_interface *intf, struct mdp5_ctl *ctl) { diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index e115318..5e4d16b 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c @@ -117,16 +117,6 @@ static int mdp5_set_split_display(struct msm_kms *kms, 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) { 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, .round_pixclk = mdp5_round_pixclk, .set_split_display = mdp5_set_split_display, - .preclose = mdp5_preclose, .destroy = mdp5_destroy, }, .set_irqmask = mdp5_set_irqmask, diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h index 00730ba..9a25898 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h @@ -211,7 +211,6 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, uint32_t mdp5_crtc_vblank(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, struct mdp5_interface *intf, struct mdp5_ctl *ctl); void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc); -- cgit v0.10.2 From 8c04fdeef343a18617968b672f212d1634add14d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 25 Jan 2016 22:16:50 +0100 Subject: drm/omap: Nuke close hooks Again since the core takes care of this we can remove them. While at it also remove the postclose hook, it's empty. v2: Laurent pointed me at even more code to delete. v3: Remove unused flags (Tomi). Cc: Laurent Pinchart Cc: Tomi Valkeinen Acked-by: Daniel Stone Reviewed-by: Alex Deucher Reviewed-by: Laurent Pinchart Acked-by: Tomi Valkeinen Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453756616-28942-9-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 2ed0754..d38fcbc 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -269,18 +269,7 @@ static void omap_crtc_complete_page_flip(struct drm_crtc *crtc) return; spin_lock_irqsave(&dev->event_lock, flags); - - 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); - + drm_crtc_send_vblank_event(crtc, event); spin_unlock_irqrestore(&dev->event_lock, flags); } diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index dfafdb6..33370f4 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -142,7 +142,6 @@ static int omap_atomic_commit(struct drm_device *dev, { struct omap_drm_private *priv = dev->dev_private; struct omap_atomic_state_commit *commit; - unsigned long flags; unsigned int i; int ret; @@ -175,17 +174,6 @@ static int omap_atomic_commit(struct drm_device *dev, priv->commit.pending |= commit->crtcs; 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. */ 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); init_waitqueue_head(&priv->commit.wait); spin_lock_init(&priv->commit.lock); - INIT_LIST_HEAD(&priv->commit.events); spin_lock_init(&priv->list_lock); 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 = { .fault = omap_gem_fault, .open = drm_gem_vm_open, @@ -838,8 +798,6 @@ static struct drm_driver omap_drm_driver = { .unload = dev_unload, .open = dev_open, .lastclose = dev_lastclose, - .preclose = dev_preclose, - .postclose = dev_postclose, .set_busid = drm_platform_set_busid, .get_vblank_counter = drm_vblank_no_hw_counter, .enable_vblank = omap_irq_enable_vblank, diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 9e00307..c23cbe6 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -106,7 +106,6 @@ struct omap_drm_private { /* atomic commit */ struct { - struct list_head events; wait_queue_head_t wait; u32 pending; spinlock_t lock; /* Protects commit.pending */ -- cgit v0.10.2 From 0a346629f5304a8390004a91e8d4f1206b87792b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 25 Jan 2016 22:16:51 +0100 Subject: drm/rcar: Nuke preclose hook Again since the drm core takes care of event unlinking/disarming this is now just needless code. Cc: Laurent Pinchart Acked-by: Daniel Stone Reviewed-by: Alex Deucher Reviewed-by: Laurent Pinchart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453756616-28942-10-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 88a4b70..4ec80ae 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -282,26 +282,6 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc) * 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) { struct drm_pending_vblank_event *event; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h index 4b95d9d..2bbe3f5 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h @@ -67,8 +67,6 @@ enum rcar_du_output { 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_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_resume(struct rcar_du_crtc *rcrtc); diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 40422f6..0bb2b31 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -220,15 +220,6 @@ done: 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) { struct rcar_du_device *rcdu = dev->dev_private; @@ -271,7 +262,6 @@ static struct drm_driver rcar_du_driver = { | DRIVER_ATOMIC, .load = rcar_du_load, .unload = rcar_du_unload, - .preclose = rcar_du_preclose, .lastclose = rcar_du_lastclose, .set_busid = drm_platform_set_busid, .get_vblank_counter = drm_vblank_no_hw_counter, -- cgit v0.10.2 From e37fb79db7b989d08f52ab2b25daa9e3aaa3830f Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 25 Jan 2016 22:16:52 +0100 Subject: drm/shmob: Nuke preclose hook Again since the drm core takes care of event unlinking/disarming this is now just needless code. v2: Fixup misplaced hunk. Cc: Laurent Pinchart Acked-by: Daniel Stone Reviewed-by: Alex Deucher (v1) Reviewed-by: Laurent Pinchart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453756616-28942-11-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index db07637..27342fd 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -438,26 +438,6 @@ static const struct drm_crtc_helper_funcs crtc_helper_funcs = { .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) { struct drm_pending_vblank_event *event; diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h index eddad6d..38ed4ff 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h @@ -47,8 +47,6 @@ struct shmob_drm_connector { 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_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_suspend(struct shmob_drm_crtc *scrtc); void shmob_drm_crtc_resume(struct shmob_drm_crtc *scrtc); diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c index 04e66e3..7700ff1 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c @@ -200,13 +200,6 @@ done: 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) { struct drm_device *dev = arg; @@ -266,7 +259,6 @@ static struct drm_driver shmob_drm_driver = { | DRIVER_PRIME, .load = shmob_drm_load, .unload = shmob_drm_unload, - .preclose = shmob_drm_preclose, .set_busid = drm_platform_set_busid, .irq_handler = shmob_drm_irq, .get_vblank_counter = drm_vblank_no_hw_counter, -- cgit v0.10.2 From 0417d424ac0db7095c3c43bd06d7d27b6bb97ced Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 25 Jan 2016 22:16:53 +0100 Subject: drm/tegra: Stop cancelling page flip events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The core takes care of that now. v2: Fixup misplaced hunk. Cc: Thierry Reding Cc: Terje Bergström Acked-by: Daniel Stone Reviewed-by: Alex Deucher Acked-by: Thierry Reding Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453756616-28942-12-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index dde6f20..fb2b4b0 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -988,23 +988,6 @@ static void tegra_dc_finish_page_flip(struct tegra_dc *dc) 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) { drm_crtc_cleanup(crtc); diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index c5c856a..021d0e1 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -860,9 +860,6 @@ static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file) struct tegra_drm_context *context, *tmp; 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) tegra_drm_context_free(context); diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index c088f2f..8a10f5b 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -195,7 +195,6 @@ struct tegra_dc_window { u32 tegra_dc_get_vblank_counter(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_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file); void tegra_dc_commit(struct tegra_dc *dc); int tegra_dc_state_setup_clock(struct tegra_dc *dc, struct drm_crtc_state *crtc_state, -- cgit v0.10.2 From b19ac0b05d7229d89d9846a5c2e6725113624702 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 25 Jan 2016 22:16:54 +0100 Subject: drm/tilcdc: Nuke preclose hook Again since the drm core takes care of event unlinking/disarming this is now just needless code. v2: Fixup misplaced hunks. Cc: Rob Clark Acked-by: Daniel Stone Reviewed-by: Alex Deucher (v1) Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453756616-28942-13-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 7d07733..4802da8 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -662,26 +662,6 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc) 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 tilcdc_crtc *tilcdc_crtc; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index d7f5b89..8190ac3 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -350,13 +350,6 @@ fail_free_priv: 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) { 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, .load = tilcdc_load, .unload = tilcdc_unload, - .preclose = tilcdc_preclose, .lastclose = tilcdc_lastclose, .set_busid = drm_platform_set_busid, .irq_handler = tilcdc_irq, diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h index e863ad0..66105d8 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h @@ -163,7 +163,6 @@ struct tilcdc_panel_info { #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) 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); void tilcdc_crtc_update_clk(struct drm_crtc *crtc); void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc, -- cgit v0.10.2 From 32a3dbeb2b951044111042ce6ccb2dcd7bca35de Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 25 Jan 2016 22:16:55 +0100 Subject: drm/vc4: Nuke preclose hook Again since the drm core takes care of event unlinking/disarming this is now just needless code. v2: Fixup misplaced hunk. Cc: Eric Anholt Acked-by: Daniel Stone Reviewed-by: Alex Deucher (v1) Acked-by: Eric Anholt Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1453756616-28942-14-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 018145e..9374097 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -593,26 +593,6 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { .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 = { .hvs_channel = 0, .encoder0_type = VC4_ENCODER_TYPE_DSI0, diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index f1655ff..b7d2ff0 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -43,14 +43,6 @@ void __iomem *vc4_ioremap_regs(struct platform_device *dev, int index) 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) { struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -91,8 +83,6 @@ static struct drm_driver vc4_drm_driver = { DRIVER_HAVE_IRQ | DRIVER_PRIME), .lastclose = vc4_lastclose, - .preclose = vc4_drm_preclose, - .irq_handler = vc4_irq, .irq_preinstall = vc4_irq_preinstall, .irq_postinstall = vc4_irq_postinstall, diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 080865e..4c734d0 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -376,7 +376,6 @@ int vc4_bo_stats_debugfs(struct seq_file *m, void *arg); extern struct platform_driver vc4_crtc_driver; 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_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file); int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg); /* vc4_debugfs.c */ -- cgit v0.10.2 From 1c0230de6dd096e46c46294e93ba68cc16f70331 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 25 Jan 2016 22:16:56 +0100 Subject: drm/vmwgfx: Nuke preclose hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Again since the drm core takes care of event unlinking/disarming this is now just needless code. v2: I've completely missed eaction->fpriv_head and all the related code. We need to nuke that too to avoid accidentally deferencing the freed-up vmwgfx-private fpriv. v3: Also remove vmw_fpriv->fence_events and unused variables I missed. Cc: Thomas Hellström Acked-by: Daniel Stone Reviewed-by: Alex Deucher Reviewed-by: Thomas Hellstrom Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-23-git-send-email-daniel.vetter@ffwll.ch Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index c49812b..c96a2d2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -971,15 +971,6 @@ static int vmw_driver_unload(struct drm_device *dev) 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, struct drm_file *file_priv) { @@ -1010,7 +1001,6 @@ static int vmw_driver_open(struct drm_device *dev, struct drm_file *file_priv) if (unlikely(vmw_fp == NULL)) return ret; - INIT_LIST_HEAD(&vmw_fp->fence_events); vmw_fp->tfile = ttm_object_file_init(dev_priv->tdev, 10); if (unlikely(vmw_fp->tfile == NULL)) goto out_no_tfile; @@ -1500,7 +1490,6 @@ static struct drm_driver driver = { .master_set = vmw_master_set, .master_drop = vmw_master_drop, .open = vmw_driver_open, - .preclose = vmw_preclose, .postclose = vmw_postclose, .set_busid = drm_pci_set_busid, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 469cdd5..5cb1b16 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -80,7 +80,6 @@ struct vmw_fpriv { struct drm_master *locked_master; struct ttm_object_file *tfile; - struct list_head fence_events; bool gb_aware; }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index 37c305b..e959df6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -71,7 +71,6 @@ struct vmw_user_fence { */ struct vmw_event_fence_action { struct vmw_fence_action action; - struct list_head fpriv_head; struct drm_pending_event *event; struct vmw_fence_obj *fence; @@ -808,44 +807,6 @@ int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data, } /** - * 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 * * @action: The struct vmw_fence_action embedded in a struct @@ -879,7 +840,6 @@ static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action) *eaction->tv_usec = tv.tv_usec; } - list_del_init(&eaction->fpriv_head); drm_send_event_locked(dev, eaction->event); eaction->event = NULL; spin_unlock_irqrestore(&dev->event_lock, irq_flags); @@ -898,12 +858,6 @@ static void vmw_event_fence_action_cleanup(struct vmw_fence_action *action) { struct vmw_event_fence_action *eaction = 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); kfree(eaction); @@ -983,8 +937,6 @@ int vmw_event_fence_action_queue(struct drm_file *file_priv, { struct vmw_event_fence_action *eaction; 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); if (unlikely(eaction == NULL)) @@ -1001,10 +953,6 @@ int vmw_event_fence_action_queue(struct drm_file *file_priv, eaction->tv_sec = tv_sec; 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); return 0; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h index 8be6c29..83ae301 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h @@ -116,8 +116,6 @@ extern int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int vmw_fence_event_ioctl(struct drm_device *dev, void *data, 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, struct vmw_fence_obj *fence, struct drm_pending_event *event, -- cgit v0.10.2 From db9b60400f9253c25ae639797df2d0ff7a35d9d8 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Tue, 2 Feb 2016 11:35:55 +0530 Subject: drm/gma500: remove helper function We were getting build warning about: drivers/gpu/drm/gma500/mdfld_dsi_output.c:407:2: warning: initialization from incompatible pointer type The callback to dpms was pointing to a helper function which had a return type of void, whereas the callback should point to a function which has a return type of int. On closer look it turned out that we do not need the helper function since if we call drm_helper_connector_dpms() directly, the first check that drm_helper_connector_dpms() does is: if (mode == connector->dpms) Signed-off-by: Sudip Mukherjee Link: http://patchwork.freedesktop.org/patch/msgid/1454393155-13142-1-git-send-email-sudipm.mukherjee@gmail.com Acked-by: Patrik Jakobsson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c index d758f4c..907cb51 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c +++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c @@ -382,16 +382,6 @@ static int mdfld_dsi_connector_mode_valid(struct drm_connector *connector, 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( struct drm_connector *connector) { @@ -404,7 +394,7 @@ static struct drm_encoder *mdfld_dsi_connector_best_encoder( /*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, .fill_modes = drm_helper_probe_single_connector_modes, .set_property = mdfld_dsi_connector_set_property, -- cgit v0.10.2 From 13619ce570ee57bb509394b896b21eba41fa4392 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 29 Jan 2016 19:37:48 +0000 Subject: gma500: clean up an excessive and confusing helper This is a left over from the great clean ups in the past. It's confusing as it returns an int, yet has one caller that never uses it. The caller already has all the right private variables local so the entire function can be replaced by a simple if call. Signed-off-by: Alan Cox Link: http://patchwork.freedesktop.org/patch/msgid/20160129193731.8475.47809.stgit@localhost.localdomain Acked-by: Patrik Jakobsson Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index ee95c03..f936540 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -672,29 +672,17 @@ static const struct drm_mode_config_funcs psb_mode_funcs = { .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) { struct drm_psb_private *dev_priv = dev->dev_private; struct drm_connector *connector; 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); list_for_each_entry(connector, &dev->mode_config.connector_list, -- cgit v0.10.2