Skip to content

Commit

Permalink
Merge tag 'topic/drm-misc-2016-04-29' of git://anongit.freedesktop.or…
Browse files Browse the repository at this point in the history
…g/drm-intel into drm-next

- prep work for struct_mutex-less gem_free_object
- more invasive/tricky mst fixes from Lyude for broken hw. I discussed
  this with Ville/Jani and we all agreed more soaking in -next would be
  real good this late in the -rc cycle. They're cc: stable too to make
  sure they're not getting lost. Feel free to cherry-pick those four if
  you disagree.
- few small things all over

* tag 'topic/drm-misc-2016-04-29' of git://anongit.freedesktop.org/drm-intel:
  drm/atomic: Add missing drm_crtc_internal.h include
  drm/dp: Allow signals to interrupt drm_aux-dev reads/writes
  drm: Quiet down drm_mode_getresources
  drm: Quiet down drm_mode_getconnector
  drm: Protect dev->filelist with its own mutex
  drm: Make drm_vm_open/close_locked private to drm_vm.c
  drm: Hide master MAP cleanup in drm_bufs.c
  drm: Forbid legacy MAP functions for DRIVER_MODESET
  drm: Push struct_mutex into ->master_destroy
  drm: Move drm_getmap into drm_bufs.c and give it a legacy prefix
  drm: Put legacy lastclose work into drm_legacy_dev_reinit
  drm: Give drm_agp_clear drm_legacy_ prefix
  drm/sysfs: Annote lockless show functions with READ_ONCE
  MAINTAINERS: Update the files list for the GMA500 DRM driver
  drm: rcar-du: Fix compilation warning
  drm/i915: Get rid of intel_dp_dpcd_read_wake()
  drm/dp_helper: Perform throw-away read before actual read in drm_dp_dpcd_read()
  drm/dp_helper: Retry aux transactions on all errors
  drm/dp_helper: Always wait before retrying native aux transactions
  • Loading branch information
Dave Airlie committed May 4, 2016
2 parents fffb675 + be35f94 commit 2b8f01f
Show file tree
Hide file tree
Showing 22 changed files with 236 additions and 221 deletions.
3 changes: 1 addition & 2 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -3851,8 +3851,7 @@ M: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
L: dri-devel@lists.freedesktop.org
T: git git://github.com/patjak/drm-gma500
S: Maintained
F: drivers/gpu/drm/gma500
F: include/drm/gma500*
F: drivers/gpu/drm/gma500/

DRM DRIVERS FOR NVIDIA TEGRA
M: Thierry Reding <thierry.reding@gmail.com>
Expand Down
10 changes: 5 additions & 5 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ void amdgpu_gem_force_release(struct amdgpu_device *adev)
struct drm_device *ddev = adev->ddev;
struct drm_file *file;

mutex_lock(&ddev->struct_mutex);
mutex_lock(&ddev->filelist_mutex);

list_for_each_entry(file, &ddev->filelist, lhead) {
struct drm_gem_object *gobj;
Expand All @@ -103,13 +103,13 @@ void amdgpu_gem_force_release(struct amdgpu_device *adev)
spin_lock(&file->table_lock);
idr_for_each_entry(&file->object_idr, gobj, handle) {
WARN_ONCE(1, "And also active allocations!\n");
drm_gem_object_unreference(gobj);
drm_gem_object_unreference_unlocked(gobj);
}
idr_destroy(&file->object_idr);
spin_unlock(&file->table_lock);
}

mutex_unlock(&ddev->struct_mutex);
mutex_unlock(&ddev->filelist_mutex);
}

/*
Expand Down Expand Up @@ -769,7 +769,7 @@ static int amdgpu_debugfs_gem_info(struct seq_file *m, void *data)
struct drm_file *file;
int r;

r = mutex_lock_interruptible(&dev->struct_mutex);
r = mutex_lock_interruptible(&dev->filelist_mutex);
if (r)
return r;

Expand All @@ -793,7 +793,7 @@ static int amdgpu_debugfs_gem_info(struct seq_file *m, void *data)
spin_unlock(&file->table_lock);
}

mutex_unlock(&dev->struct_mutex);
mutex_unlock(&dev->filelist_mutex);
return 0;
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/drm_agpsupport.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ struct drm_agp_head *drm_agp_init(struct drm_device *dev)
}

/**
* drm_agp_clear - Clear AGP resource list
* drm_legacy_agp_clear - Clear AGP resource list
* @dev: DRM device
*
* Iterate over all AGP resources and remove them. But keep the AGP head
Expand All @@ -434,7 +434,7 @@ struct drm_agp_head *drm_agp_init(struct drm_device *dev)
* resources from getting destroyed. Drivers are responsible of cleaning them up
* during device shutdown.
*/
void drm_agp_clear(struct drm_device *dev)
void drm_legacy_agp_clear(struct drm_device *dev)
{
struct drm_agp_mem *entry, *tempe;

Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/drm_atomic.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include <drm/drm_mode.h>
#include <drm/drm_plane_helper.h>

#include "drm_crtc_internal.h"

/**
* drm_atomic_state_default_release -
* release memory initialized by drm_atomic_state_init
Expand Down
91 changes: 86 additions & 5 deletions drivers/gpu/drm/drm_bufs.c
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,10 @@ int drm_legacy_addmap_ioctl(struct drm_device *dev, void *data,
if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP || map->type == _DRM_SHM))
return -EPERM;

if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;

err = drm_addmap_core(dev, map->offset, map->size, map->type,
map->flags, &maplist);

Expand All @@ -416,6 +420,62 @@ int drm_legacy_addmap_ioctl(struct drm_device *dev, void *data,
return 0;
}

/*
* Get a mapping information.
*
* \param inode device inode.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument, pointing to a drm_map structure.
*
* \return zero on success or a negative number on failure.
*
* Searches for the mapping with the specified offset and copies its information
* into userspace
*/
int drm_legacy_getmap_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_map *map = data;
struct drm_map_list *r_list = NULL;
struct list_head *list;
int idx;
int i;

if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;

idx = map->offset;
if (idx < 0)
return -EINVAL;

i = 0;
mutex_lock(&dev->struct_mutex);
list_for_each(list, &dev->maplist) {
if (i == idx) {
r_list = list_entry(list, struct drm_map_list, head);
break;
}
i++;
}
if (!r_list || !r_list->map) {
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}

map->offset = r_list->map->offset;
map->size = r_list->map->size;
map->type = r_list->map->type;
map->flags = r_list->map->flags;
map->handle = (void *)(unsigned long) r_list->user_token;
map->mtrr = arch_phys_wc_index(r_list->map->mtrr);

mutex_unlock(&dev->struct_mutex);

return 0;
}

/**
* Remove a map private from list and deallocate resources if the mapping
* isn't in use.
Expand Down Expand Up @@ -482,18 +542,35 @@ int drm_legacy_rmmap_locked(struct drm_device *dev, struct drm_local_map *map)
}
EXPORT_SYMBOL(drm_legacy_rmmap_locked);

int drm_legacy_rmmap(struct drm_device *dev, struct drm_local_map *map)
void drm_legacy_rmmap(struct drm_device *dev, struct drm_local_map *map)
{
int ret;
if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
drm_core_check_feature(dev, DRIVER_MODESET))
return;

mutex_lock(&dev->struct_mutex);
ret = drm_legacy_rmmap_locked(dev, map);
drm_legacy_rmmap_locked(dev, map);
mutex_unlock(&dev->struct_mutex);

return ret;
}
EXPORT_SYMBOL(drm_legacy_rmmap);

void drm_legacy_master_rmmaps(struct drm_device *dev, struct drm_master *master)
{
struct drm_map_list *r_list, *list_temp;

if (drm_core_check_feature(dev, DRIVER_MODESET))
return;

mutex_lock(&dev->struct_mutex);
list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) {
if (r_list->master == master) {
drm_legacy_rmmap_locked(dev, r_list->map);
r_list = NULL;
}
}
mutex_unlock(&dev->struct_mutex);
}

/* The rmmap ioctl appears to be unnecessary. All mappings are torn down on
* the last close of the device, and this is necessary for cleanup when things
* exit uncleanly. Therefore, having userland manually remove mappings seems
Expand All @@ -517,6 +594,10 @@ int drm_legacy_rmmap_ioctl(struct drm_device *dev, void *data,
struct drm_map_list *r_list;
int ret;

if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;

mutex_lock(&dev->struct_mutex);
list_for_each_entry(r_list, &dev->maplist, head) {
if (r_list->map &&
Expand Down
12 changes: 0 additions & 12 deletions drivers/gpu/drm/drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1936,8 +1936,6 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
copied = 0;
crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
drm_for_each_crtc(crtc, dev) {
DRM_DEBUG_KMS("[CRTC:%d:%s]\n",
crtc->base.id, crtc->name);
if (put_user(crtc->base.id, crtc_id + copied)) {
ret = -EFAULT;
goto out;
Expand All @@ -1952,8 +1950,6 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
copied = 0;
encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
drm_for_each_encoder(encoder, dev) {
DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id,
encoder->name);
if (put_user(encoder->base.id, encoder_id +
copied)) {
ret = -EFAULT;
Expand All @@ -1969,9 +1965,6 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
copied = 0;
connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
drm_for_each_connector(connector, dev) {
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
connector->base.id,
connector->name);
if (put_user(connector->base.id,
connector_id + copied)) {
ret = -EFAULT;
Expand All @@ -1982,9 +1975,6 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
}
card_res->count_connectors = connector_count;

DRM_DEBUG_KMS("CRTC[%d] CONNECTORS[%d] ENCODERS[%d]\n", card_res->count_crtcs,
card_res->count_connectors, card_res->count_encoders);

out:
mutex_unlock(&dev->mode_config.mutex);
return ret;
Expand Down Expand Up @@ -2143,8 +2133,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,

memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));

DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);

mutex_lock(&dev->mode_config.mutex);

connector = drm_connector_find(dev, out_resp->connector_id);
Expand Down
12 changes: 12 additions & 0 deletions drivers/gpu/drm/drm_dp_aux_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,12 @@ static ssize_t auxdev_read(struct file *file, char __user *buf, size_t count,
uint8_t localbuf[DP_AUX_MAX_PAYLOAD_BYTES];
ssize_t todo = min_t(size_t, bytes_pending, sizeof(localbuf));

if (signal_pending(current)) {
res = num_bytes_processed ?
num_bytes_processed : -ERESTARTSYS;
goto out;
}

res = drm_dp_dpcd_read(aux_dev->aux, *offset, localbuf, todo);
if (res <= 0) {
res = num_bytes_processed ? num_bytes_processed : res;
Expand Down Expand Up @@ -202,6 +208,12 @@ static ssize_t auxdev_write(struct file *file, const char __user *buf,
uint8_t localbuf[DP_AUX_MAX_PAYLOAD_BYTES];
ssize_t todo = min_t(size_t, bytes_pending, sizeof(localbuf));

if (signal_pending(current)) {
res = num_bytes_processed ?
num_bytes_processed : -ERESTARTSYS;
goto out;
}

if (__copy_from_user(localbuf,
buf + num_bytes_processed, todo)) {
res = num_bytes_processed ?
Expand Down
66 changes: 43 additions & 23 deletions drivers/gpu/drm/drm_dp_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
unsigned int offset, void *buffer, size_t size)
{
struct drm_dp_aux_msg msg;
unsigned int retry;
int err = 0;
unsigned int retry, native_reply;
int err = 0, ret = 0;

memset(&msg, 0, sizeof(msg));
msg.address = offset;
Expand All @@ -196,38 +196,39 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
* sufficient, bump to 32 which makes Dell 4k monitors happier.
*/
for (retry = 0; retry < 32; retry++) {

err = aux->transfer(aux, &msg);
if (err < 0) {
if (err == -EBUSY)
continue;

goto unlock;
if (ret != 0 && ret != -ETIMEDOUT) {
usleep_range(AUX_RETRY_INTERVAL,
AUX_RETRY_INTERVAL + 100);
}

ret = aux->transfer(aux, &msg);

switch (msg.reply & DP_AUX_NATIVE_REPLY_MASK) {
case DP_AUX_NATIVE_REPLY_ACK:
if (err < size)
err = -EPROTO;
goto unlock;
if (ret > 0) {
native_reply = msg.reply & DP_AUX_NATIVE_REPLY_MASK;
if (native_reply == DP_AUX_NATIVE_REPLY_ACK) {
if (ret == size)
goto unlock;

case DP_AUX_NATIVE_REPLY_NACK:
err = -EIO;
goto unlock;

case DP_AUX_NATIVE_REPLY_DEFER:
usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
break;
ret = -EPROTO;
} else
ret = -EIO;
}

/*
* We want the error we return to be the error we received on
* the first transaction, since we may get a different error the
* next time we retry
*/
if (!err)
err = ret;
}

DRM_DEBUG_KMS("too many retries, giving up\n");
err = -EIO;
ret = err;

unlock:
mutex_unlock(&aux->hw_mutex);
return err;
return ret;
}

/**
Expand All @@ -247,6 +248,25 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
void *buffer, size_t size)
{
int ret;

/*
* HP ZR24w corrupts the first DPCD access after entering power save
* mode. Eg. on a read, the entire buffer will be filled with the same
* byte. Do a throw away read to avoid corrupting anything we care
* about. Afterwards things will work correctly until the monitor
* gets woken up and subsequently re-enters power save mode.
*
* The user pressing any button on the monitor is enough to wake it
* up, so there is no particularly good place to do the workaround.
* We just have to do it before any DPCD access and hope that the
* monitor doesn't power down exactly after the throw away read.
*/
ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, DP_DPCD_REV, buffer,
1);
if (ret != 1)
return ret;

return drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, offset, buffer,
size);
}
Expand Down
Loading

0 comments on commit 2b8f01f

Please sign in to comment.