Skip to content

Commit

Permalink
Merge tag 'topic/drm-misc-2015-05-06' of git://anongit.freedesktop.or…
Browse files Browse the repository at this point in the history
…g/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
  • Loading branch information
Dave Airlie committed May 7, 2015
2 parents 5ebe6af + 4a324d3 commit 49f8976
Show file tree
Hide file tree
Showing 12 changed files with 132 additions and 230 deletions.
9 changes: 5 additions & 4 deletions drivers/gpu/drm/drm_atomic_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -1309,13 +1310,13 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane,
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:
Expand Down
178 changes: 35 additions & 143 deletions drivers/gpu/drm/drm_auth.c
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
/**
* \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
*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* 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
Expand All @@ -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.
*
* \param dev DRM device.
* \param magic magic number.
*
* 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).
* 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 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.
* 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.
*
* 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)
Expand All @@ -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;
}
12 changes: 9 additions & 3 deletions drivers/gpu/drm/drm_dp_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -432,15 +432,15 @@ 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;

/*
* DP1.2 sections 2.7.7.1.5.6.1 and 2.7.7.1.6.6.1: A DP Source device
* 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);
Expand All @@ -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
Expand Down Expand Up @@ -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;

Expand Down
20 changes: 4 additions & 16 deletions drivers/gpu/drm/drm_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down
7 changes: 2 additions & 5 deletions drivers/gpu/drm/drm_fops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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);
Expand Down
1 change: 0 additions & 1 deletion drivers/gpu/drm/drm_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading

0 comments on commit 49f8976

Please sign in to comment.