Merge tag 'topic/drm-misc-2015-05-06' of git://anongit.freedesktop.org/drm-intel into drm-next
misc drm core patches. * tag 'topic/drm-misc-2015-05-06' of git://anongit.freedesktop.org/drm-intel: drm: simplify master cleanup drm: simplify authentication management drm: drop unused 'magicfree' list drm: fix a memleak on mutex failure path drm/atomic-helper: Really recover pre-atomic plane/cursor behavior drm/qxl: Fix qxl_noop_get_vblank_counter() drm: Zero out invalid vblank timestamp in drm_update_vblank_count. (v2) drm: Prevent invalid use of vblank_disable_immediate. (v2) drm/vblank: Fixup and document timestamp update/read barriers DRM: Don't re-poll connector for disconnect drm: Fix for DP CTS test 4.2.2.5 - I2C DEFER handling drm: Fix the 'native defer' message in drm_dp_i2c_do_msg() drm/atomic-helper: Don't call atomic_update_plane when it stays off
This commit is contained in:
commit
49f897647a
|
@ -1138,7 +1138,8 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
|
|||
if (drm_atomic_plane_disabling(plane, old_plane_state) &&
|
||||
funcs->atomic_disable)
|
||||
funcs->atomic_disable(plane, old_plane_state);
|
||||
else
|
||||
else if (plane->state->crtc ||
|
||||
drm_atomic_plane_disabling(plane, old_plane_state))
|
||||
funcs->atomic_update(plane, old_plane_state);
|
||||
}
|
||||
|
||||
|
@ -1309,13 +1310,13 @@ retry:
|
|||
plane_state->src_h = src_h;
|
||||
plane_state->src_w = src_w;
|
||||
|
||||
if (plane == crtc->cursor)
|
||||
state->legacy_cursor_update = true;
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
if (ret != 0)
|
||||
goto fail;
|
||||
|
||||
if (plane == crtc->cursor)
|
||||
state->legacy_cursor_update = true;
|
||||
|
||||
/* Driver takes ownership of state on successful commit. */
|
||||
return 0;
|
||||
fail:
|
||||
|
|
|
@ -1,11 +1,3 @@
|
|||
/**
|
||||
* \file drm_auth.c
|
||||
* IOCTLs for authentication
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* \author Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
|
||||
*
|
||||
|
@ -13,6 +5,9 @@
|
|||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Author Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
|
@ -36,154 +31,47 @@
|
|||
#include <drm/drmP.h>
|
||||
#include "drm_internal.h"
|
||||
|
||||
struct drm_magic_entry {
|
||||
struct list_head head;
|
||||
struct drm_hash_item hash_item;
|
||||
struct drm_file *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* Find the file with the given magic number.
|
||||
* drm_getmagic - Get unique magic of a client
|
||||
* @dev: DRM device to operate on
|
||||
* @data: ioctl data containing the drm_auth object
|
||||
* @file_priv: DRM file that performs the operation
|
||||
*
|
||||
* \param dev DRM device.
|
||||
* \param magic magic number.
|
||||
* This looks up the unique magic of the passed client and returns it. If the
|
||||
* client did not have a magic assigned, yet, a new one is registered. The magic
|
||||
* is stored in the passed drm_auth object.
|
||||
*
|
||||
* Searches in drm_device::magiclist within all files with the same hash key
|
||||
* the one with matching magic number, while holding the drm_device::struct_mutex
|
||||
* lock.
|
||||
*/
|
||||
static struct drm_file *drm_find_file(struct drm_master *master, drm_magic_t magic)
|
||||
{
|
||||
struct drm_file *retval = NULL;
|
||||
struct drm_magic_entry *pt;
|
||||
struct drm_hash_item *hash;
|
||||
struct drm_device *dev = master->minor->dev;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
if (!drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) {
|
||||
pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
|
||||
retval = pt->priv;
|
||||
}
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a magic number.
|
||||
*
|
||||
* \param dev DRM device.
|
||||
* \param priv file private data.
|
||||
* \param magic magic number.
|
||||
*
|
||||
* Creates a drm_magic_entry structure and appends to the linked list
|
||||
* associated the magic number hash key in drm_device::magiclist, while holding
|
||||
* the drm_device::struct_mutex lock.
|
||||
*/
|
||||
static int drm_add_magic(struct drm_master *master, struct drm_file *priv,
|
||||
drm_magic_t magic)
|
||||
{
|
||||
struct drm_magic_entry *entry;
|
||||
struct drm_device *dev = master->minor->dev;
|
||||
DRM_DEBUG("%d\n", magic);
|
||||
|
||||
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
entry->priv = priv;
|
||||
entry->hash_item.key = (unsigned long)magic;
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
drm_ht_insert_item(&master->magiclist, &entry->hash_item);
|
||||
list_add_tail(&entry->head, &master->magicfree);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a magic number.
|
||||
*
|
||||
* \param dev DRM device.
|
||||
* \param magic magic number.
|
||||
*
|
||||
* Searches and unlinks the entry in drm_device::magiclist with the magic
|
||||
* number hash key, while holding the drm_device::struct_mutex lock.
|
||||
*/
|
||||
int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
|
||||
{
|
||||
struct drm_magic_entry *pt;
|
||||
struct drm_hash_item *hash;
|
||||
struct drm_device *dev = master->minor->dev;
|
||||
|
||||
DRM_DEBUG("%d\n", magic);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
if (drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
|
||||
drm_ht_remove_item(&master->magiclist, hash);
|
||||
list_del(&pt->head);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
kfree(pt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a unique magic number (ioctl).
|
||||
*
|
||||
* \param inode device inode.
|
||||
* \param file_priv DRM file private.
|
||||
* \param cmd command.
|
||||
* \param arg pointer to a resulting drm_auth structure.
|
||||
* \return zero on success, or a negative number on failure.
|
||||
*
|
||||
* If there is a magic number in drm_file::magic then use it, otherwise
|
||||
* searches an unique non-zero magic number and add it associating it with \p
|
||||
* file_priv.
|
||||
* This ioctl needs protection by the drm_global_mutex, which protects
|
||||
* struct drm_file::magic and struct drm_magic_entry::priv.
|
||||
* Returns: 0 on success, negative error code on failure.
|
||||
*/
|
||||
int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
static drm_magic_t sequence = 0;
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
struct drm_auth *auth = data;
|
||||
int ret = 0;
|
||||
|
||||
/* Find unique magic */
|
||||
if (file_priv->magic) {
|
||||
auth->magic = file_priv->magic;
|
||||
} else {
|
||||
do {
|
||||
spin_lock(&lock);
|
||||
if (!sequence)
|
||||
++sequence; /* reserve 0 */
|
||||
auth->magic = sequence++;
|
||||
spin_unlock(&lock);
|
||||
} while (drm_find_file(file_priv->master, auth->magic));
|
||||
file_priv->magic = auth->magic;
|
||||
drm_add_magic(file_priv->master, file_priv, auth->magic);
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
if (!file_priv->magic) {
|
||||
ret = idr_alloc(&file_priv->master->magic_map, file_priv,
|
||||
1, 0, GFP_KERNEL);
|
||||
if (ret >= 0)
|
||||
file_priv->magic = ret;
|
||||
}
|
||||
auth->magic = file_priv->magic;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
DRM_DEBUG("%u\n", auth->magic);
|
||||
|
||||
return 0;
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate with a magic.
|
||||
* drm_authmagic - Authenticate client with a magic
|
||||
* @dev: DRM device to operate on
|
||||
* @data: ioctl data containing the drm_auth object
|
||||
* @file_priv: DRM file that performs the operation
|
||||
*
|
||||
* \param inode device inode.
|
||||
* \param file_priv DRM file private.
|
||||
* \param cmd command.
|
||||
* \param arg pointer to a drm_auth structure.
|
||||
* \return zero if authentication successed, or a negative number otherwise.
|
||||
* This looks up a DRM client by the passed magic and authenticates it.
|
||||
*
|
||||
* Checks if \p file_priv is associated with the magic number passed in \arg.
|
||||
* This ioctl needs protection by the drm_global_mutex, which protects
|
||||
* struct drm_file::magic and struct drm_magic_entry::priv.
|
||||
* Returns: 0 on success, negative error code on failure.
|
||||
*/
|
||||
int drm_authmagic(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
|
@ -192,10 +80,14 @@ int drm_authmagic(struct drm_device *dev, void *data,
|
|||
struct drm_file *file;
|
||||
|
||||
DRM_DEBUG("%u\n", auth->magic);
|
||||
if ((file = drm_find_file(file_priv->master, auth->magic))) {
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
file = idr_find(&file_priv->master->magic_map, auth->magic);
|
||||
if (file) {
|
||||
file->authenticated = 1;
|
||||
drm_remove_magic(file_priv->master, auth->magic);
|
||||
return 0;
|
||||
idr_replace(&file_priv->master->magic_map, NULL, auth->magic);
|
||||
}
|
||||
return -EINVAL;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return file ? 0 : -EINVAL;
|
||||
}
|
||||
|
|
|
@ -432,7 +432,7 @@ static u32 drm_dp_i2c_functionality(struct i2c_adapter *adapter)
|
|||
*/
|
||||
static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
||||
{
|
||||
unsigned int retry;
|
||||
unsigned int retry, defer_i2c;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
|
@ -440,7 +440,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
|||
* is required to retry at least seven times upon receiving AUX_DEFER
|
||||
* before giving up the AUX transaction.
|
||||
*/
|
||||
for (retry = 0; retry < 7; retry++) {
|
||||
for (retry = 0, defer_i2c = 0; retry < (7 + defer_i2c); retry++) {
|
||||
mutex_lock(&aux->hw_mutex);
|
||||
ret = aux->transfer(aux, msg);
|
||||
mutex_unlock(&aux->hw_mutex);
|
||||
|
@ -466,7 +466,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
|||
return -EREMOTEIO;
|
||||
|
||||
case DP_AUX_NATIVE_REPLY_DEFER:
|
||||
DRM_DEBUG_KMS("native defer");
|
||||
DRM_DEBUG_KMS("native defer\n");
|
||||
/*
|
||||
* We could check for I2C bit rate capabilities and if
|
||||
* available adjust this interval. We could also be
|
||||
|
@ -499,7 +499,13 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
|||
|
||||
case DP_AUX_I2C_REPLY_DEFER:
|
||||
DRM_DEBUG_KMS("I2C defer\n");
|
||||
/* DP Compliance Test 4.2.2.5 Requirement:
|
||||
* Must have at least 7 retries for I2C defers on the
|
||||
* transaction to pass this test
|
||||
*/
|
||||
aux->i2c_defer_count++;
|
||||
if (defer_i2c < 7)
|
||||
defer_i2c++;
|
||||
usleep_range(400, 500);
|
||||
continue;
|
||||
|
||||
|
|
|
@ -92,8 +92,6 @@ void drm_ut_debug_printk(const char *function_name, const char *format, ...)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_ut_debug_printk);
|
||||
|
||||
#define DRM_MAGIC_HASH_ORDER 4 /**< Size of key hash table. Must be power of 2. */
|
||||
|
||||
struct drm_master *drm_master_create(struct drm_minor *minor)
|
||||
{
|
||||
struct drm_master *master;
|
||||
|
@ -105,11 +103,7 @@ struct drm_master *drm_master_create(struct drm_minor *minor)
|
|||
kref_init(&master->refcount);
|
||||
spin_lock_init(&master->lock.spinlock);
|
||||
init_waitqueue_head(&master->lock.lock_queue);
|
||||
if (drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER)) {
|
||||
kfree(master);
|
||||
return NULL;
|
||||
}
|
||||
INIT_LIST_HEAD(&master->magicfree);
|
||||
idr_init(&master->magic_map);
|
||||
master->minor = minor;
|
||||
|
||||
return master;
|
||||
|
@ -138,16 +132,10 @@ static void drm_master_destroy(struct kref *kref)
|
|||
r_list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (master->unique) {
|
||||
kfree(master->unique);
|
||||
master->unique = NULL;
|
||||
master->unique_len = 0;
|
||||
}
|
||||
|
||||
drm_ht_remove(&master->magiclist);
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
idr_destroy(&master->magic_map);
|
||||
kfree(master->unique);
|
||||
kfree(master);
|
||||
}
|
||||
|
||||
|
|
|
@ -380,6 +380,8 @@ int drm_release(struct inode *inode, struct file *filp)
|
|||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
list_del(&file_priv->lhead);
|
||||
if (file_priv->magic)
|
||||
idr_remove(&file_priv->master->magic_map, file_priv->magic);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
if (dev->driver->preclose)
|
||||
|
@ -394,11 +396,6 @@ int drm_release(struct inode *inode, struct file *filp)
|
|||
(long)old_encode_dev(file_priv->minor->kdev->devt),
|
||||
dev->open_count);
|
||||
|
||||
/* Release any auth tokens that might point to this file_priv,
|
||||
(do that under the drm_global_mutex) */
|
||||
if (file_priv->magic)
|
||||
(void) drm_remove_magic(file_priv->master, file_priv->magic);
|
||||
|
||||
/* if the master has gone away we can't do anything with the lock */
|
||||
if (file_priv->minor->master)
|
||||
drm_master_release(dev, filp);
|
||||
|
|
|
@ -69,7 +69,6 @@ int drm_getmagic(struct drm_device *dev, void *data,
|
|||
struct drm_file *file_priv);
|
||||
int drm_authmagic(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
int drm_remove_magic(struct drm_master *master, drm_magic_t magic);
|
||||
|
||||
/* drm_sysfs.c */
|
||||
extern struct class *drm_class;
|
||||
|
|
|
@ -74,6 +74,36 @@ module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
|
|||
module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
|
||||
module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
|
||||
|
||||
static void store_vblank(struct drm_device *dev, int crtc,
|
||||
unsigned vblank_count_inc,
|
||||
struct timeval *t_vblank)
|
||||
{
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
|
||||
u32 tslot;
|
||||
|
||||
assert_spin_locked(&dev->vblank_time_lock);
|
||||
|
||||
if (t_vblank) {
|
||||
/* All writers hold the spinlock, but readers are serialized by
|
||||
* the latching of vblank->count below.
|
||||
*/
|
||||
tslot = vblank->count + vblank_count_inc;
|
||||
vblanktimestamp(dev, crtc, tslot) = *t_vblank;
|
||||
}
|
||||
|
||||
/*
|
||||
* vblank timestamp updates are protected on the write side with
|
||||
* vblank_time_lock, but on the read side done locklessly using a
|
||||
* sequence-lock on the vblank counter. Ensure correct ordering using
|
||||
* memory barrriers. We need the barrier both before and also after the
|
||||
* counter update to synchronize with the next timestamp write.
|
||||
* The read-side barriers for this are in drm_vblank_count_and_time.
|
||||
*/
|
||||
smp_wmb();
|
||||
vblank->count += vblank_count_inc;
|
||||
smp_wmb();
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_update_vblank_count - update the master vblank counter
|
||||
* @dev: DRM device
|
||||
|
@ -93,7 +123,7 @@ module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
|
|||
static void drm_update_vblank_count(struct drm_device *dev, int crtc)
|
||||
{
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
|
||||
u32 cur_vblank, diff, tslot;
|
||||
u32 cur_vblank, diff;
|
||||
bool rc;
|
||||
struct timeval t_vblank;
|
||||
|
||||
|
@ -129,18 +159,15 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc)
|
|||
if (diff == 0)
|
||||
return;
|
||||
|
||||
/* Reinitialize corresponding vblank timestamp if high-precision query
|
||||
* available. Skip this step if query unsupported or failed. Will
|
||||
* reinitialize delayed at next vblank interrupt in that case.
|
||||
/*
|
||||
* Only reinitialize corresponding vblank timestamp if high-precision query
|
||||
* available and didn't fail. Otherwise reinitialize delayed at next vblank
|
||||
* interrupt and assign 0 for now, to mark the vblanktimestamp as invalid.
|
||||
*/
|
||||
if (rc) {
|
||||
tslot = atomic_read(&vblank->count) + diff;
|
||||
vblanktimestamp(dev, crtc, tslot) = t_vblank;
|
||||
}
|
||||
if (!rc)
|
||||
t_vblank = (struct timeval) {0, 0};
|
||||
|
||||
smp_mb__before_atomic();
|
||||
atomic_add(diff, &vblank->count);
|
||||
smp_mb__after_atomic();
|
||||
store_vblank(dev, crtc, diff, &t_vblank);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -218,7 +245,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
|
|||
/* Compute time difference to stored timestamp of last vblank
|
||||
* as updated by last invocation of drm_handle_vblank() in vblank irq.
|
||||
*/
|
||||
vblcount = atomic_read(&vblank->count);
|
||||
vblcount = vblank->count;
|
||||
diff_ns = timeval_to_ns(&tvblank) -
|
||||
timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount));
|
||||
|
||||
|
@ -234,17 +261,8 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
|
|||
* available. In that case we can't account for this and just
|
||||
* hope for the best.
|
||||
*/
|
||||
if (vblrc && (abs64(diff_ns) > 1000000)) {
|
||||
/* Store new timestamp in ringbuffer. */
|
||||
vblanktimestamp(dev, crtc, vblcount + 1) = tvblank;
|
||||
|
||||
/* Increment cooked vblank count. This also atomically commits
|
||||
* the timestamp computed above.
|
||||
*/
|
||||
smp_mb__before_atomic();
|
||||
atomic_inc(&vblank->count);
|
||||
smp_mb__after_atomic();
|
||||
}
|
||||
if (vblrc && (abs64(diff_ns) > 1000000))
|
||||
store_vblank(dev, crtc, 1, &tvblank);
|
||||
|
||||
spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
|
||||
}
|
||||
|
@ -337,6 +355,13 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
|
|||
else
|
||||
DRM_INFO("No driver support for vblank timestamp query.\n");
|
||||
|
||||
/* Must have precise timestamping for reliable vblank instant disable */
|
||||
if (dev->vblank_disable_immediate && !dev->driver->get_vblank_timestamp) {
|
||||
dev->vblank_disable_immediate = false;
|
||||
DRM_INFO("Setting vblank_disable_immediate to false because "
|
||||
"get_vblank_timestamp == NULL\n");
|
||||
}
|
||||
|
||||
dev->vblank_disable_allowed = false;
|
||||
|
||||
return 0;
|
||||
|
@ -852,7 +877,7 @@ u32 drm_vblank_count(struct drm_device *dev, int crtc)
|
|||
|
||||
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||
return 0;
|
||||
return atomic_read(&vblank->count);
|
||||
return vblank->count;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_count);
|
||||
|
||||
|
@ -897,16 +922,17 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
|
|||
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||
return 0;
|
||||
|
||||
/* Read timestamp from slot of _vblank_time ringbuffer
|
||||
* that corresponds to current vblank count. Retry if
|
||||
* count has incremented during readout. This works like
|
||||
* a seqlock.
|
||||
/*
|
||||
* Vblank timestamps are read lockless. To ensure consistency the vblank
|
||||
* counter is rechecked and ordering is ensured using memory barriers.
|
||||
* This works like a seqlock. The write-side barriers are in store_vblank.
|
||||
*/
|
||||
do {
|
||||
cur_vblank = atomic_read(&vblank->count);
|
||||
cur_vblank = vblank->count;
|
||||
smp_rmb();
|
||||
*vblanktime = vblanktimestamp(dev, crtc, cur_vblank);
|
||||
smp_rmb();
|
||||
} while (cur_vblank != atomic_read(&vblank->count));
|
||||
} while (cur_vblank != vblank->count);
|
||||
|
||||
return cur_vblank;
|
||||
}
|
||||
|
@ -1715,7 +1741,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
|
|||
*/
|
||||
|
||||
/* Get current timestamp and count. */
|
||||
vblcount = atomic_read(&vblank->count);
|
||||
vblcount = vblank->count;
|
||||
drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ);
|
||||
|
||||
/* Compute time difference to timestamp of last vblank */
|
||||
|
@ -1731,20 +1757,11 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
|
|||
* e.g., due to spurious vblank interrupts. We need to
|
||||
* ignore those for accounting.
|
||||
*/
|
||||
if (abs64(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS) {
|
||||
/* Store new timestamp in ringbuffer. */
|
||||
vblanktimestamp(dev, crtc, vblcount + 1) = tvblank;
|
||||
|
||||
/* Increment cooked vblank count. This also atomically commits
|
||||
* the timestamp computed above.
|
||||
*/
|
||||
smp_mb__before_atomic();
|
||||
atomic_inc(&vblank->count);
|
||||
smp_mb__after_atomic();
|
||||
} else {
|
||||
if (abs64(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS)
|
||||
store_vblank(dev, crtc, 1, &tvblank);
|
||||
else
|
||||
DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n",
|
||||
crtc, (int) diff_ns);
|
||||
}
|
||||
|
||||
spin_unlock(&dev->vblank_time_lock);
|
||||
|
||||
|
|
|
@ -80,8 +80,10 @@ int __drm_modeset_lock_all(struct drm_device *dev,
|
|||
return -ENOMEM;
|
||||
|
||||
if (trylock) {
|
||||
if (!mutex_trylock(&config->mutex))
|
||||
return -EBUSY;
|
||||
if (!mutex_trylock(&config->mutex)) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
mutex_lock(&config->mutex);
|
||||
}
|
||||
|
@ -114,6 +116,8 @@ fail:
|
|||
goto retry;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(ctx);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(__drm_modeset_lock_all);
|
||||
|
|
|
@ -323,8 +323,6 @@ static void output_poll_execute(struct work_struct *work)
|
|||
if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD)
|
||||
continue;
|
||||
|
||||
repoll = true;
|
||||
|
||||
old_status = connector->status;
|
||||
/* if we are connected and don't want to poll for disconnect
|
||||
skip it */
|
||||
|
@ -332,6 +330,8 @@ static void output_poll_execute(struct work_struct *work)
|
|||
!(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT))
|
||||
continue;
|
||||
|
||||
repoll = true;
|
||||
|
||||
connector->status = connector->funcs->detect(connector, false);
|
||||
if (old_status != connector->status) {
|
||||
const char *old, *new;
|
||||
|
|
|
@ -172,10 +172,6 @@ static void intel_plane_atomic_update(struct drm_plane *plane,
|
|||
struct intel_plane_state *intel_state =
|
||||
to_intel_plane_state(plane->state);
|
||||
|
||||
/* Don't disable an already disabled plane */
|
||||
if (!plane->state->fb && !old_state->fb)
|
||||
return;
|
||||
|
||||
intel_plane->commit_plane(plane, intel_state);
|
||||
}
|
||||
|
||||
|
|
|
@ -198,7 +198,7 @@ static int qxl_pm_restore(struct device *dev)
|
|||
|
||||
static u32 qxl_noop_get_vblank_counter(struct drm_device *dev, int crtc)
|
||||
{
|
||||
return dev->vblank[crtc].count.counter;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qxl_noop_enable_vblank(struct drm_device *dev, int crtc)
|
||||
|
|
|
@ -355,8 +355,7 @@ struct drm_lock_data {
|
|||
* @minor: Link back to minor char device we are master for. Immutable.
|
||||
* @unique: Unique identifier: e.g. busid. Protected by drm_global_mutex.
|
||||
* @unique_len: Length of unique field. Protected by drm_global_mutex.
|
||||
* @magiclist: Hash of used authentication tokens. Protected by struct_mutex.
|
||||
* @magicfree: List of used authentication tokens. Protected by struct_mutex.
|
||||
* @magic_map: Map of used authentication tokens. Protected by struct_mutex.
|
||||
* @lock: DRI lock information.
|
||||
* @driver_priv: Pointer to driver-private information.
|
||||
*/
|
||||
|
@ -365,8 +364,7 @@ struct drm_master {
|
|||
struct drm_minor *minor;
|
||||
char *unique;
|
||||
int unique_len;
|
||||
struct drm_open_hash magiclist;
|
||||
struct list_head magicfree;
|
||||
struct idr magic_map;
|
||||
struct drm_lock_data lock;
|
||||
void *driver_priv;
|
||||
};
|
||||
|
@ -686,9 +684,13 @@ struct drm_pending_vblank_event {
|
|||
struct drm_vblank_crtc {
|
||||
struct drm_device *dev; /* pointer to the drm_device */
|
||||
wait_queue_head_t queue; /**< VBLANK wait queue */
|
||||
struct timeval time[DRM_VBLANKTIME_RBSIZE]; /**< timestamp of current count */
|
||||
struct timer_list disable_timer; /* delayed disable timer */
|
||||
atomic_t count; /**< number of VBLANK interrupts */
|
||||
|
||||
/* vblank counter, protected by dev->vblank_time_lock for writes */
|
||||
unsigned long count;
|
||||
/* vblank timestamps, protected by dev->vblank_time_lock for writes */
|
||||
struct timeval time[DRM_VBLANKTIME_RBSIZE];
|
||||
|
||||
atomic_t refcount; /* number of users of vblank interruptsper crtc */
|
||||
u32 last; /* protected by dev->vbl_lock, used */
|
||||
/* for wraparound handling */
|
||||
|
|
Loading…
Reference in a new issue