Skip to content

Commit

Permalink
Merge tag 'drm-fixes-2020-07-17-1' of git://anongit.freedesktop.org/d…
Browse files Browse the repository at this point in the history
…rm/drm into master

Pull drm fixes from Dave Airlie:
 "Weekly fixes pull, big bigger than I'd normally like, but they are
  fairly scattered and small individually.

  The vmwgfx one is a black screen regression, otherwise the largest is
  an MST encoder fix for amdgpu which results in a WARN in some cases,
  and a scattering of i915 fixes.

  I'm tracking two regressions at the moment that hopefully we get
  nailed down this week for rc7.

  dma-buf:
   - sleeping atomic fix

  amdgpu:
   - Fix a race condition with KIQ
   - Preemption fix
   - Fix handling of fake MST encoders
   - OLED panel fix
   - Handle allocation failure in stream construction
   - Renoir SMC fix
   - SDMA 5.x fix

  i915:
   - FBC w/a stride fix
   - Fix use-after-free fix on module reload
   - Ignore irq enabling on the virtual engines to fix device sleep
   - Use GTT when saving/restoring engine GPR
   - Fix selftest sort function

  vmwgfx:
   - black screen fix

  aspeed:
   - fbcon init warn fix"

* tag 'drm-fixes-2020-07-17-1' of git://anongit.freedesktop.org/drm/drm:
  drm/amdgpu/sdma5: fix wptr overwritten in ->get_wptr()
  drm/amdgpu/powerplay: Modify SMC message name for setting power profile mode
  drm/amd/display: handle failed allocation during stream construction
  drm/amd/display: OLED panel backlight adjust not work with external display connected
  drm/amdgpu/display: create fake mst encoders ahead of time (v4)
  drm/amdgpu: fix preemption unit test
  drm/amdgpu/gfx10: fix race condition for kiq
  drm/i915: Recalculate FBC w/a stride when needed
  drm/i915: Move cec_notifier to intel_hdmi_connector_unregister, v2.
  drm/i915/gt: Only swap to a random sibling once upon creation
  drm/i915/gt: Ignore irq enabling on the virtual engines
  drm/i915/perf: Use GTT when saving/restoring engine GPR
  drm/i915/selftests: Fix compare functions provided for sorting
  drm/vmwgfx: fix update of display surface when resolution changes
  dmabuf: use spinlock to access dmabuf->name
  drm/aspeed: Call drm_fbdev_generic_setup after drm_dev_register
  • Loading branch information
Linus Torvalds committed Jul 17, 2020
2 parents 07a56bb + adbe8a3 commit 8882572
Show file tree
Hide file tree
Showing 19 changed files with 153 additions and 99 deletions.
11 changes: 7 additions & 4 deletions drivers/dma-buf/dma-buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen)
size_t ret = 0;

dmabuf = dentry->d_fsdata;
dma_resv_lock(dmabuf->resv, NULL);
spin_lock(&dmabuf->name_lock);
if (dmabuf->name)
ret = strlcpy(name, dmabuf->name, DMA_BUF_NAME_LEN);
dma_resv_unlock(dmabuf->resv);
spin_unlock(&dmabuf->name_lock);

return dynamic_dname(dentry, buffer, buflen, "/%s:%s",
dentry->d_name.name, ret > 0 ? name : "");
Expand Down Expand Up @@ -338,8 +338,10 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
kfree(name);
goto out_unlock;
}
spin_lock(&dmabuf->name_lock);
kfree(dmabuf->name);
dmabuf->name = name;
spin_unlock(&dmabuf->name_lock);

out_unlock:
dma_resv_unlock(dmabuf->resv);
Expand Down Expand Up @@ -402,10 +404,10 @@ static void dma_buf_show_fdinfo(struct seq_file *m, struct file *file)
/* Don't count the temporary reference taken inside procfs seq_show */
seq_printf(m, "count:\t%ld\n", file_count(dmabuf->file) - 1);
seq_printf(m, "exp_name:\t%s\n", dmabuf->exp_name);
dma_resv_lock(dmabuf->resv, NULL);
spin_lock(&dmabuf->name_lock);
if (dmabuf->name)
seq_printf(m, "name:\t%s\n", dmabuf->name);
dma_resv_unlock(dmabuf->resv);
spin_unlock(&dmabuf->name_lock);
}

static const struct file_operations dma_buf_fops = {
Expand Down Expand Up @@ -542,6 +544,7 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
dmabuf->size = exp_info->size;
dmabuf->exp_name = exp_info->exp_name;
dmabuf->owner = exp_info->owner;
spin_lock_init(&dmabuf->name_lock);
init_waitqueue_head(&dmabuf->poll);
dmabuf->cb_excl.poll = dmabuf->cb_shared.poll = &dmabuf->poll;
dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0;
Expand Down
20 changes: 15 additions & 5 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1295,27 +1295,37 @@ static void amdgpu_ib_preempt_job_recovery(struct drm_gpu_scheduler *sched)
static void amdgpu_ib_preempt_mark_partial_job(struct amdgpu_ring *ring)
{
struct amdgpu_job *job;
struct drm_sched_job *s_job;
struct drm_sched_job *s_job, *tmp;
uint32_t preempt_seq;
struct dma_fence *fence, **ptr;
struct amdgpu_fence_driver *drv = &ring->fence_drv;
struct drm_gpu_scheduler *sched = &ring->sched;
bool preempted = true;

if (ring->funcs->type != AMDGPU_RING_TYPE_GFX)
return;

preempt_seq = le32_to_cpu(*(drv->cpu_addr + 2));
if (preempt_seq <= atomic_read(&drv->last_seq))
return;
if (preempt_seq <= atomic_read(&drv->last_seq)) {
preempted = false;
goto no_preempt;
}

preempt_seq &= drv->num_fences_mask;
ptr = &drv->fences[preempt_seq];
fence = rcu_dereference_protected(*ptr, 1);

no_preempt:
spin_lock(&sched->job_list_lock);
list_for_each_entry(s_job, &sched->ring_mirror_list, node) {
list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) {
if (dma_fence_is_signaled(&s_job->s_fence->finished)) {
/* remove job from ring_mirror_list */
list_del_init(&s_job->node);
sched->ops->free_job(s_job);
continue;
}
job = to_amdgpu_job(s_job);
if (job->fence == fence)
if (preempted && job->fence == fence)
/* mark the job as preempted */
job->preemption_status |= AMDGPU_IB_PREEMPTED;
}
Expand Down
9 changes: 8 additions & 1 deletion drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
Original file line number Diff line number Diff line change
Expand Up @@ -7513,12 +7513,17 @@ static int gfx_v10_0_ring_preempt_ib(struct amdgpu_ring *ring)
struct amdgpu_device *adev = ring->adev;
struct amdgpu_kiq *kiq = &adev->gfx.kiq;
struct amdgpu_ring *kiq_ring = &kiq->ring;
unsigned long flags;

if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
return -EINVAL;

if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size))
spin_lock_irqsave(&kiq->ring_lock, flags);

if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size)) {
spin_unlock_irqrestore(&kiq->ring_lock, flags);
return -ENOMEM;
}

/* assert preemption condition */
amdgpu_ring_set_preempt_cond_exec(ring, false);
Expand All @@ -7529,6 +7534,8 @@ static int gfx_v10_0_ring_preempt_ib(struct amdgpu_ring *ring)
++ring->trail_seq);
amdgpu_ring_commit(kiq_ring);

spin_unlock_irqrestore(&kiq->ring_lock, flags);

/* poll the trailing fence */
for (i = 0; i < adev->usec_timeout; i++) {
if (ring->trail_seq ==
Expand Down
26 changes: 8 additions & 18 deletions drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,30 +314,20 @@ static uint64_t sdma_v5_0_ring_get_rptr(struct amdgpu_ring *ring)
static uint64_t sdma_v5_0_ring_get_wptr(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
u64 *wptr = NULL;
uint64_t local_wptr = 0;
u64 wptr;

if (ring->use_doorbell) {
/* XXX check if swapping is necessary on BE */
wptr = ((u64 *)&adev->wb.wb[ring->wptr_offs]);
DRM_DEBUG("wptr/doorbell before shift == 0x%016llx\n", *wptr);
*wptr = (*wptr) >> 2;
DRM_DEBUG("wptr/doorbell after shift == 0x%016llx\n", *wptr);
wptr = READ_ONCE(*((u64 *)&adev->wb.wb[ring->wptr_offs]));
DRM_DEBUG("wptr/doorbell before shift == 0x%016llx\n", wptr);
} else {
u32 lowbit, highbit;

wptr = &local_wptr;
lowbit = RREG32(sdma_v5_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR)) >> 2;
highbit = RREG32(sdma_v5_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR_HI)) >> 2;

DRM_DEBUG("wptr [%i]high== 0x%08x low==0x%08x\n",
ring->me, highbit, lowbit);
*wptr = highbit;
*wptr = (*wptr) << 32;
*wptr |= lowbit;
wptr = RREG32(sdma_v5_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR_HI));
wptr = wptr << 32;
wptr |= RREG32(sdma_v5_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR));
DRM_DEBUG("wptr before shift [%i] wptr == 0x%016llx\n", ring->me, wptr);
}

return *wptr;
return wptr >> 2;
}

/**
Expand Down
14 changes: 14 additions & 0 deletions drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
/* Update the actual used number of crtc */
adev->mode_info.num_crtc = adev->dm.display_indexes_num;

/* create fake encoders for MST */
dm_dp_create_fake_mst_encoders(adev);

/* TODO: Add_display_info? */

/* TODO use dynamic cursor width */
Expand All @@ -997,6 +1000,12 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)

static void amdgpu_dm_fini(struct amdgpu_device *adev)
{
int i;

for (i = 0; i < adev->dm.display_indexes_num; i++) {
drm_encoder_cleanup(&adev->dm.mst_encoders[i].base);
}

amdgpu_dm_audio_fini(adev);

amdgpu_dm_destroy_drm_device(&adev->dm);
Expand Down Expand Up @@ -2010,13 +2019,18 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
struct amdgpu_display_manager *dm;
struct drm_connector *conn_base;
struct amdgpu_device *adev;
struct dc_link *link = NULL;
static const u8 pre_computed_values[] = {
50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69,
71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98};

if (!aconnector || !aconnector->dc_link)
return;

link = aconnector->dc_link;
if (link->connector_signal != SIGNAL_TYPE_EDP)
return;

conn_base = &aconnector->base;
adev = conn_base->dev->dev_private;
dm = &adev->dm;
Expand Down
11 changes: 10 additions & 1 deletion drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
*/

#define AMDGPU_DM_MAX_DISPLAY_INDEX 31

#define AMDGPU_DM_MAX_CRTC 6

/*
#include "include/amdgpu_dal_power_if.h"
#include "amdgpu_dm_irq.h"
Expand Down Expand Up @@ -328,6 +331,13 @@ struct amdgpu_display_manager {
* available in FW
*/
const struct gpu_info_soc_bounding_box_v1_0 *soc_bounding_box;

/**
* @mst_encoders:
*
* fake encoders used for DP MST.
*/
struct amdgpu_encoder mst_encoders[AMDGPU_DM_MAX_CRTC];
};

struct amdgpu_dm_connector {
Expand Down Expand Up @@ -356,7 +366,6 @@ struct amdgpu_dm_connector {
struct amdgpu_dm_dp_aux dm_dp_aux;
struct drm_dp_mst_port *port;
struct amdgpu_dm_connector *mst_port;
struct amdgpu_encoder *mst_encoder;
struct drm_dp_aux *dsc_aux;

/* TODO see if we can merge with ddc_bus or make a dm_connector */
Expand Down
53 changes: 26 additions & 27 deletions drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector)
{
struct amdgpu_dm_connector *aconnector =
to_amdgpu_dm_connector(connector);
struct amdgpu_encoder *amdgpu_encoder = aconnector->mst_encoder;

if (aconnector->dc_sink) {
dc_link_remove_remote_sink(aconnector->dc_link,
Expand All @@ -105,8 +104,6 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector)

kfree(aconnector->edid);

drm_encoder_cleanup(&amdgpu_encoder->base);
kfree(amdgpu_encoder);
drm_connector_cleanup(connector);
drm_dp_mst_put_port_malloc(aconnector->port);
kfree(aconnector);
Expand Down Expand Up @@ -243,7 +240,11 @@ static struct drm_encoder *
dm_mst_atomic_best_encoder(struct drm_connector *connector,
struct drm_connector_state *connector_state)
{
return &to_amdgpu_dm_connector(connector)->mst_encoder->base;
struct drm_device *dev = connector->dev;
struct amdgpu_device *adev = dev->dev_private;
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(connector_state->crtc);

return &adev->dm.mst_encoders[acrtc->crtc_id].base;
}

static int
Expand Down Expand Up @@ -306,31 +307,27 @@ static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = {
.destroy = amdgpu_dm_encoder_destroy,
};

static struct amdgpu_encoder *
dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector)
void
dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev)
{
struct drm_device *dev = connector->base.dev;
struct amdgpu_device *adev = dev->dev_private;
struct amdgpu_encoder *amdgpu_encoder;
struct drm_encoder *encoder;

amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL);
if (!amdgpu_encoder)
return NULL;
struct drm_device *dev = adev->ddev;
int i;

encoder = &amdgpu_encoder->base;
encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev);
for (i = 0; i < adev->dm.display_indexes_num; i++) {
struct amdgpu_encoder *amdgpu_encoder = &adev->dm.mst_encoders[i];
struct drm_encoder *encoder = &amdgpu_encoder->base;

drm_encoder_init(
dev,
&amdgpu_encoder->base,
&amdgpu_dm_encoder_funcs,
DRM_MODE_ENCODER_DPMST,
NULL);
encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev);

drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs);
drm_encoder_init(
dev,
&amdgpu_encoder->base,
&amdgpu_dm_encoder_funcs,
DRM_MODE_ENCODER_DPMST,
NULL);

return amdgpu_encoder;
drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs);
}
}

static struct drm_connector *
Expand All @@ -343,6 +340,7 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
struct amdgpu_device *adev = dev->dev_private;
struct amdgpu_dm_connector *aconnector;
struct drm_connector *connector;
int i;

aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL);
if (!aconnector)
Expand All @@ -369,9 +367,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
master->dc_link,
master->connector_id);

aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master);
drm_connector_attach_encoder(&aconnector->base,
&aconnector->mst_encoder->base);
for (i = 0; i < adev->dm.display_indexes_num; i++) {
drm_connector_attach_encoder(&aconnector->base,
&adev->dm.mst_encoders[i].base);
}

connector->max_bpc_property = master->base.max_bpc_property;
if (connector->max_bpc_property)
Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
struct amdgpu_dm_connector *aconnector,
int link_index);

void
dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev);

#if defined(CONFIG_DRM_AMD_DC_DCN)
bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
struct dc_state *dc_state);
Expand Down
19 changes: 16 additions & 3 deletions drivers/gpu/drm/amd/display/dc/core/dc_stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ void update_stream_signal(struct dc_stream_state *stream, struct dc_sink *sink)
}
}

static void dc_stream_construct(struct dc_stream_state *stream,
static bool dc_stream_construct(struct dc_stream_state *stream,
struct dc_sink *dc_sink_data)
{
uint32_t i = 0;
Expand Down Expand Up @@ -118,11 +118,17 @@ static void dc_stream_construct(struct dc_stream_state *stream,
update_stream_signal(stream, dc_sink_data);

stream->out_transfer_func = dc_create_transfer_func();
if (stream->out_transfer_func == NULL) {
dc_sink_release(dc_sink_data);
return false;
}
stream->out_transfer_func->type = TF_TYPE_BYPASS;
stream->out_transfer_func->ctx = stream->ctx;

stream->stream_id = stream->ctx->dc_stream_id_count;
stream->ctx->dc_stream_id_count++;

return true;
}

static void dc_stream_destruct(struct dc_stream_state *stream)
Expand Down Expand Up @@ -164,13 +170,20 @@ struct dc_stream_state *dc_create_stream_for_sink(

stream = kzalloc(sizeof(struct dc_stream_state), GFP_KERNEL);
if (stream == NULL)
return NULL;
goto alloc_fail;

dc_stream_construct(stream, sink);
if (dc_stream_construct(stream, sink) == false)
goto construct_fail;

kref_init(&stream->refcount);

return stream;

construct_fail:
kfree(stream);

alloc_fail:
return NULL;
}

struct dc_stream_state *dc_copy_stream(const struct dc_stream_state *stream)
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/amd/powerplay/renoir_ppt.c
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,7 @@ static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, u
return -EINVAL;
}

ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
ret = smu_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
1 << workload_type,
NULL);
if (ret) {
Expand Down
Loading

0 comments on commit 8882572

Please sign in to comment.