Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 19 additions & 20 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
*/
#include "amdgpu_ids.h"

#include <linux/idr.h>
#include <linux/xarray.h>
#include <linux/dma-fence-array.h>


Expand All @@ -40,8 +40,8 @@
* VMs are looked up from the PASID per amdgpu_device.
*/

static DEFINE_IDR(amdgpu_pasid_idr);
static DEFINE_SPINLOCK(amdgpu_pasid_idr_lock);
static DEFINE_XARRAY_FLAGS(amdgpu_pasid_xa, XA_FLAGS_LOCK_IRQ | XA_FLAGS_ALLOC1);
static u32 amdgpu_pasid_xa_next;

/* Helper to free pasid from a fence callback */
struct amdgpu_pasid_cb {
Expand All @@ -62,36 +62,37 @@ struct amdgpu_pasid_cb {
*/
int amdgpu_pasid_alloc(unsigned int bits)
{
int pasid;
u32 pasid;
int r;

if (bits == 0)
return -EINVAL;

spin_lock(&amdgpu_pasid_idr_lock);
/* TODO: Need to replace the idr with an xarry, and then
* handle the internal locking with ATOMIC safe paths.
*/
pasid = idr_alloc_cyclic(&amdgpu_pasid_idr, NULL, 1,
1U << bits, GFP_ATOMIC);
spin_unlock(&amdgpu_pasid_idr_lock);

if (pasid >= 0)
trace_amdgpu_pasid_allocated(pasid);
r = xa_alloc_cyclic_irq(&amdgpu_pasid_xa, &pasid, xa_mk_value(0),
XA_LIMIT(1, (1U << bits) - 1),
&amdgpu_pasid_xa_next, GFP_KERNEL);
if (r < 0)
return r;

trace_amdgpu_pasid_allocated(pasid);
return pasid;
}

/**
* amdgpu_pasid_free - Free a PASID
* @pasid: PASID to free
*
* Called in IRQ context.
*/
void amdgpu_pasid_free(u32 pasid)
{
unsigned long flags;

trace_amdgpu_pasid_freed(pasid);

spin_lock(&amdgpu_pasid_idr_lock);
idr_remove(&amdgpu_pasid_idr, pasid);
spin_unlock(&amdgpu_pasid_idr_lock);
xa_lock_irqsave(&amdgpu_pasid_xa, flags);
__xa_erase(&amdgpu_pasid_xa, pasid);
xa_unlock_irqrestore(&amdgpu_pasid_xa, flags);
}

static void amdgpu_pasid_free_cb(struct dma_fence *fence,
Expand Down Expand Up @@ -634,7 +635,5 @@ void amdgpu_vmid_mgr_fini(struct amdgpu_device *adev)
*/
void amdgpu_pasid_mgr_cleanup(void)
{
spin_lock(&amdgpu_pasid_idr_lock);
idr_destroy(&amdgpu_pasid_idr);
spin_unlock(&amdgpu_pasid_idr_lock);
xa_destroy(&amdgpu_pasid_xa);
}
29 changes: 21 additions & 8 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -552,8 +552,9 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,
size_t size, loff_t *pos)
{
struct amdgpu_ring *ring = file_inode(f)->i_private;
uint32_t value, result, early[3];
u32 value, result, early[3] = { 0 };
uint64_t p;
u32 avail_dw, start_dw, read_dw;
loff_t i;
int r;

Expand All @@ -565,10 +566,10 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,

result = 0;

if (*pos < 12) {
if (ring->funcs->type == AMDGPU_RING_TYPE_CPER)
mutex_lock(&ring->adev->cper.ring_lock);
if (ring->funcs->type == AMDGPU_RING_TYPE_CPER)
mutex_lock(&ring->adev->cper.ring_lock);

if (*pos < 12) {
early[0] = amdgpu_ring_get_rptr(ring) & ring->buf_mask;
early[1] = amdgpu_ring_get_wptr(ring) & ring->buf_mask;
early[2] = ring->wptr & ring->buf_mask;
Expand Down Expand Up @@ -600,13 +601,24 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,
*pos += 4;
}
} else {
early[0] = amdgpu_ring_get_rptr(ring) & ring->buf_mask;
early[1] = amdgpu_ring_get_wptr(ring) & ring->buf_mask;

p = early[0];
if (early[0] <= early[1])
size = (early[1] - early[0]);
avail_dw = early[1] - early[0];
else
size = ring->ring_size - (early[0] - early[1]);
avail_dw = ring->buf_mask + 1 - (early[0] - early[1]);

while (size) {
start_dw = (*pos > 12) ? ((*pos - 12) >> 2) : 0;
if (start_dw >= avail_dw)
goto out;

p = (p + start_dw) & ring->ptr_mask;
avail_dw -= start_dw;
read_dw = min_t(u32, avail_dw, size >> 2);

while (read_dw) {
if (p == early[1])
goto out;

Expand All @@ -619,9 +631,10 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,

buf += 4;
result += 4;
size--;
read_dw--;
p++;
p &= ring->ptr_mask;
*pos += 4;
}
}

Expand Down
53 changes: 52 additions & 1 deletion drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
Original file line number Diff line number Diff line change
Expand Up @@ -10896,7 +10896,58 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state,
dm_enable_per_frame_crtc_master_sync(dc_state);
mutex_lock(&dm->dc_lock);
dc_exit_ips_for_hw_access(dm->dc);
WARN_ON(!dc_commit_streams(dm->dc, &params));

/* if commit_status isn't DC_OK, the cable has been pushed to its limits */
enum dc_status commit_status = dc_commit_streams(dm->dc, &params);

if (commit_status != DC_OK) {
struct drm_plane *plane;
struct drm_plane_state *new_plane_state;

drm_err(dev, "Display Core failed to commit streams due to link failure! Rolling back pinned framebuffers.\n");
WARN_ON(1);

/* release planes, unpin GTT memory */
for_each_new_plane_in_state(state, plane, new_plane_state, i) {
const struct drm_plane_helper_funcs *funcs = plane->helper_private;

if (funcs && funcs->cleanup_fb && new_plane_state->fb) {
drm_dbg_atomic(dev,
"Manually freeing stranded plane framebuffer allocation [ID: %d]\n",
plane->base.id);
funcs->cleanup_fb(plane, new_plane_state);
}
}

/* release streams and vram */
for (i = 0; i < state->num_connector; i++) {
struct drm_connector_state *new_con_state = state->connectors[i].new_state;

if (new_con_state && new_con_state->crtc) {
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_con_state->crtc);
struct dm_crtc_state *dm_new_state = to_dm_crtc_state(
drm_atomic_get_new_crtc_state(state, &acrtc->base)
);

if (dm_new_state && dm_new_state->stream) {
dc_stream_release(dm_new_state->stream);
dm_new_state->stream = NULL;
}
}
}

/* release dc state */
struct dm_atomic_state *dm_state = dm_atomic_get_new_state(state);

if (dm_state && dm_state->context) {
dc_state_release(dm_state->context);
dm_state->context = NULL;
}

/* Release the engine lock safely and abandon the rest of the configuration */
mutex_unlock(&dm->dc_lock);
return;
}

/* Allow idle optimization when vblank count is 0 for display off */
if ((dm->active_vblank_irq_count == 0) && amdgpu_dm_is_headless(dm->adev))
Expand Down
5 changes: 5 additions & 0 deletions drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,10 @@ int smu_v13_0_6_get_metrics_table(struct smu_context *smu, void *metrics_table,
amdgpu_hdp_invalidate(smu->adev, NULL);
memcpy(smu_table->metrics_table, table->cpu_addr, table_size);

if (!memchr_inv(smu_table->metrics_table, 0xff,
min(16, table_size)))
return -EHWPOISON;

smu_table->metrics_time = jiffies;
}

Expand Down Expand Up @@ -1284,6 +1288,7 @@ static int smu_v13_0_6_set_default_dpm_table(struct smu_context *smu)
/* gfxclk dpm table setup */
dpm_table = &dpm_context->dpm_tables.gfx_table;
dpm_table->clk_type = SMU_GFXCLK;
dpm_table->flags = SMU_DPM_TABLE_FINE_GRAINED;
if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
/* In the case of gfxclk, only fine-grained dpm is honored.
* Get min/max values from FW.
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
Original file line number Diff line number Diff line change
Expand Up @@ -1349,7 +1349,7 @@ int smu_cmn_print_dpm_clk_levels(struct smu_context *smu,
level_index = 1;
}

if (!is_fine_grained) {
if (!is_fine_grained || count == 1) {
for (i = 0; i < count; i++) {
freq_match = !is_deep_sleep &&
smu_cmn_freqs_match(
Expand Down