Skip to content

Commit

Permalink
Merge branch 'etnaviv/next' of https://git.pengutronix.de/git/lst/linux
Browse files Browse the repository at this point in the history
… into drm-next

please pull the following etnaviv changes for the next merge window.
Mostly some small workarounds to get new hardware support going. But
also more fixes to the softpin MMU handling and a nice addition from
Christian to make the kernel logs on hang detection more useful.

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Lucas Stach <l.stach@pengutronix.de>
Link: https://patchwork.freedesktop.org/patch/msgid/adcb1b3dec89a18d6c3c4ee6e179b9b2c9f25046.camel@pengutronix.de
  • Loading branch information
Dave Airlie committed Nov 22, 2022
2 parents 4302423 + a3b4c2f commit 819683a
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 37 deletions.
7 changes: 6 additions & 1 deletion drivers/gpu/drm/etnaviv/etnaviv_dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,15 @@ static void etnaviv_core_dump_registers(struct core_dump_iterator *iter,
{
struct etnaviv_dump_registers *reg = iter->data;
unsigned int i;
u32 read_addr;

for (i = 0; i < ARRAY_SIZE(etnaviv_dump_registers); i++, reg++) {
read_addr = etnaviv_dump_registers[i];
if (read_addr >= VIVS_PM_POWER_CONTROLS &&
read_addr <= VIVS_PM_PULSE_EATER)
read_addr = gpu_fix_power_address(gpu, read_addr);
reg->reg = cpu_to_le32(etnaviv_dump_registers[i]);
reg->value = cpu_to_le32(gpu_read(gpu, etnaviv_dump_registers[i]));
reg->value = cpu_to_le32(gpu_read(gpu, read_addr));
}

etnaviv_core_dump_header(iter, ETDUMP_BUF_REG, reg);
Expand Down
19 changes: 12 additions & 7 deletions drivers/gpu/drm/etnaviv/etnaviv_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ static int etnaviv_gem_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
{
pgprot_t vm_page_prot;

vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP;
vma->vm_flags |= VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;

vm_page_prot = vm_get_page_prot(vma->vm_flags);

Expand Down Expand Up @@ -165,7 +165,8 @@ static vm_fault_t etnaviv_gem_fault(struct vm_fault *vmf)
struct vm_area_struct *vma = vmf->vma;
struct drm_gem_object *obj = vma->vm_private_data;
struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
struct page **pages, *page;
struct page **pages;
unsigned long pfn;
pgoff_t pgoff;
int err;

Expand All @@ -189,12 +190,12 @@ static vm_fault_t etnaviv_gem_fault(struct vm_fault *vmf)
/* We don't use vmf->pgoff since that has the fake offset: */
pgoff = (vmf->address - vma->vm_start) >> PAGE_SHIFT;

page = pages[pgoff];
pfn = page_to_pfn(pages[pgoff]);

VERB("Inserting %p pfn %lx, pa %lx", (void *)vmf->address,
page_to_pfn(page), page_to_pfn(page) << PAGE_SHIFT);
pfn, pfn << PAGE_SHIFT);

return vmf_insert_page(vma, vmf->address, page);
return vmf_insert_pfn(vma, vmf->address, pfn);
}

int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset)
Expand Down Expand Up @@ -258,7 +259,12 @@ struct etnaviv_vram_mapping *etnaviv_gem_mapping_get(
if (mapping->use == 0) {
mutex_lock(&mmu_context->lock);
if (mapping->context == mmu_context)
mapping->use += 1;
if (va && mapping->iova != va) {
etnaviv_iommu_reap_mapping(mapping);
mapping = NULL;
} else {
mapping->use += 1;
}
else
mapping = NULL;
mutex_unlock(&mmu_context->lock);
Expand Down Expand Up @@ -504,7 +510,6 @@ void etnaviv_gem_free_object(struct drm_gem_object *obj)
kfree(mapping);
}

drm_gem_free_mmap_offset(obj);
etnaviv_obj->ops->release(etnaviv_obj);
drm_gem_object_release(obj);

Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/etnaviv/etnaviv_gem.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ struct etnaviv_gem_submit {
int out_fence_id;
struct list_head node; /* GPU active submit list */
struct etnaviv_cmdbuf cmdbuf;
struct pid *pid; /* submitting process */
bool runtime_resumed;
u32 exec_state;
u32 flags;
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,9 @@ static void submit_cleanup(struct kref *kref)
mutex_unlock(&submit->gpu->fence_lock);
dma_fence_put(submit->out_fence);
}

put_pid(submit->pid);

kfree(submit->pmrs);
kfree(submit);
}
Expand All @@ -422,6 +425,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
struct sync_file *sync_file = NULL;
struct ww_acquire_ctx ticket;
int out_fence_fd = -1;
struct pid *pid = get_pid(task_pid(current));
void *stream;
int ret;

Expand Down Expand Up @@ -519,6 +523,8 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
goto err_submit_ww_acquire;
}

submit->pid = pid;

ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &submit->cmdbuf,
ALIGN(args->stream_size, 8) + 8);
if (ret)
Expand Down
58 changes: 41 additions & 17 deletions drivers/gpu/drm/etnaviv/etnaviv_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,12 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
if (gpu->identity.model == chipModel_GC700)
gpu->identity.features &= ~chipFeatures_FAST_CLEAR;

/* These models/revisions don't have the 2D pipe bit */
if ((gpu->identity.model == chipModel_GC500 &&
gpu->identity.revision <= 2) ||
gpu->identity.model == chipModel_GC300)
gpu->identity.features |= chipFeatures_PIPE_2D;

if ((gpu->identity.model == chipModel_GC500 &&
gpu->identity.revision < 2) ||
(gpu->identity.model == chipModel_GC300 &&
Expand Down Expand Up @@ -449,8 +455,9 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_5);
}

/* GC600 idle register reports zero bits where modules aren't present */
if (gpu->identity.model == chipModel_GC600)
/* GC600/300 idle register reports zero bits where modules aren't present */
if (gpu->identity.model == chipModel_GC600 ||
gpu->identity.model == chipModel_GC300)
gpu->idle_mask = VIVS_HI_IDLE_STATE_TX |
VIVS_HI_IDLE_STATE_RA |
VIVS_HI_IDLE_STATE_SE |
Expand Down Expand Up @@ -583,17 +590,17 @@ static void etnaviv_gpu_enable_mlcg(struct etnaviv_gpu *gpu)
u32 pmc, ppc;

/* enable clock gating */
ppc = gpu_read(gpu, VIVS_PM_POWER_CONTROLS);
ppc = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS);
ppc |= VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;

/* Disable stall module clock gating for 4.3.0.1 and 4.3.0.2 revs */
if (gpu->identity.revision == 0x4301 ||
gpu->identity.revision == 0x4302)
ppc |= VIVS_PM_POWER_CONTROLS_DISABLE_STALL_MODULE_CLOCK_GATING;

gpu_write(gpu, VIVS_PM_POWER_CONTROLS, ppc);
gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, ppc);

pmc = gpu_read(gpu, VIVS_PM_MODULE_CONTROLS);
pmc = gpu_read_power(gpu, VIVS_PM_MODULE_CONTROLS);

/* Disable PA clock gating for GC400+ without bugfix except for GC420 */
if (gpu->identity.model >= chipModel_GC400 &&
Expand All @@ -616,19 +623,20 @@ static void etnaviv_gpu_enable_mlcg(struct etnaviv_gpu *gpu)

/* Disable TX clock gating on affected core revisions. */
if (etnaviv_is_model_rev(gpu, GC4000, 0x5222) ||
etnaviv_is_model_rev(gpu, GC2000, 0x5108))
etnaviv_is_model_rev(gpu, GC2000, 0x5108) ||
etnaviv_is_model_rev(gpu, GC2000, 0x6202) ||
etnaviv_is_model_rev(gpu, GC2000, 0x6203))
pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_TX;

/* Disable SE, RA and TX clock gating on affected core revisions. */
/* Disable SE and RA clock gating on affected core revisions. */
if (etnaviv_is_model_rev(gpu, GC7000, 0x6202))
pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_SE |
VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA |
VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_TX;
VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA;

pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_HZ;
pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_EZ;

gpu_write(gpu, VIVS_PM_MODULE_CONTROLS, pmc);
gpu_write_power(gpu, VIVS_PM_MODULE_CONTROLS, pmc);
}

void etnaviv_gpu_start_fe(struct etnaviv_gpu *gpu, u32 address, u16 prefetch)
Expand Down Expand Up @@ -688,11 +696,11 @@ static void etnaviv_gpu_setup_pulse_eater(struct etnaviv_gpu *gpu)
(gpu->identity.features & chipFeatures_PIPE_3D))
{
/* Performance fix: disable internal DFS */
pulse_eater = gpu_read(gpu, VIVS_PM_PULSE_EATER);
pulse_eater = gpu_read_power(gpu, VIVS_PM_PULSE_EATER);
pulse_eater |= BIT(18);
}

gpu_write(gpu, VIVS_PM_PULSE_EATER, pulse_eater);
gpu_write_power(gpu, VIVS_PM_PULSE_EATER, pulse_eater);
}

static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
Expand Down Expand Up @@ -1045,12 +1053,28 @@ int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m)
}
#endif

void etnaviv_gpu_recover_hang(struct etnaviv_gpu *gpu)
void etnaviv_gpu_recover_hang(struct etnaviv_gem_submit *submit)
{
struct etnaviv_gpu *gpu = submit->gpu;
char *comm = NULL, *cmd = NULL;
struct task_struct *task;
unsigned int i;

dev_err(gpu->dev, "recover hung GPU!\n");

task = get_pid_task(submit->pid, PIDTYPE_PID);
if (task) {
comm = kstrdup(task->comm, GFP_KERNEL);
cmd = kstrdup_quotable_cmdline(task, GFP_KERNEL);
put_task_struct(task);
}

if (comm && cmd)
dev_err(gpu->dev, "offending task: %s (%s)\n", comm, cmd);

kfree(cmd);
kfree(comm);

if (pm_runtime_get_sync(gpu->dev) < 0)
goto pm_put;

Expand Down Expand Up @@ -1294,9 +1318,9 @@ static void sync_point_perfmon_sample_pre(struct etnaviv_gpu *gpu,
u32 val;

/* disable clock gating */
val = gpu_read(gpu, VIVS_PM_POWER_CONTROLS);
val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS);
val &= ~VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
gpu_write(gpu, VIVS_PM_POWER_CONTROLS, val);
gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, val);

/* enable debug register */
val = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
Expand Down Expand Up @@ -1327,9 +1351,9 @@ static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu,
gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, val);

/* enable clock gating */
val = gpu_read(gpu, VIVS_PM_POWER_CONTROLS);
val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS);
val |= VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
gpu_write(gpu, VIVS_PM_POWER_CONTROLS, val);
gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, val);
}


Expand Down
23 changes: 22 additions & 1 deletion drivers/gpu/drm/etnaviv/etnaviv_gpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "etnaviv_gem.h"
#include "etnaviv_mmu.h"
#include "etnaviv_drv.h"
#include "common.xml.h"

struct etnaviv_gem_submit;
struct etnaviv_vram_mapping;
Expand Down Expand Up @@ -159,6 +160,26 @@ static inline u32 gpu_read(struct etnaviv_gpu *gpu, u32 reg)
return readl(gpu->mmio + reg);
}

static inline u32 gpu_fix_power_address(struct etnaviv_gpu *gpu, u32 reg)
{
/* Power registers in GC300 < 2.0 are offset by 0x100 */
if (gpu->identity.model == chipModel_GC300 &&
gpu->identity.revision < 0x2000)
reg += 0x100;

return reg;
}

static inline void gpu_write_power(struct etnaviv_gpu *gpu, u32 reg, u32 data)
{
writel(data, gpu->mmio + gpu_fix_power_address(gpu, reg));
}

static inline u32 gpu_read_power(struct etnaviv_gpu *gpu, u32 reg)
{
return readl(gpu->mmio + gpu_fix_power_address(gpu, reg));
}

int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value);

int etnaviv_gpu_init(struct etnaviv_gpu *gpu);
Expand All @@ -168,7 +189,7 @@ bool etnaviv_fill_identity_from_hwdb(struct etnaviv_gpu *gpu);
int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m);
#endif

void etnaviv_gpu_recover_hang(struct etnaviv_gpu *gpu);
void etnaviv_gpu_recover_hang(struct etnaviv_gem_submit *submit);
void etnaviv_gpu_retire(struct etnaviv_gpu *gpu);
int etnaviv_gpu_wait_fence_interruptible(struct etnaviv_gpu *gpu,
u32 fence, struct drm_etnaviv_timespec *timeout);
Expand Down
31 changes: 31 additions & 0 deletions drivers/gpu/drm/etnaviv/etnaviv_hwdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,37 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
.minor_features10 = 0x00004040,
.minor_features11 = 0x00000024,
},
{
.model = 0x7000,
.revision = 0x6203,
.product_id = 0x70003,
.customer_id = 0x4,
.eco_id = 0,
.stream_count = 16,
.register_max = 64,
.thread_count = 512,
.shader_core_count = 2,
.vertex_cache_size = 16,
.vertex_output_buffer_size = 1024,
.pixel_pipes = 1,
.instruction_count = 512,
.num_constants = 320,
.buffer_size = 0,
.varyings_count = 16,
.features = 0xe0287c8d,
.minor_features0 = 0xc1589eff,
.minor_features1 = 0xfefbfad9,
.minor_features2 = 0xeb9d4fbf,
.minor_features3 = 0xedfffced,
.minor_features4 = 0xdb0dafc7,
.minor_features5 = 0x3b5ac333,
.minor_features6 = 0xfcce6000,
.minor_features7 = 0xfffbfa6f,
.minor_features8 = 0x00e10ef3,
.minor_features9 = 0x00c8003c,
.minor_features10 = 0x00004040,
.minor_features11 = 0x00000024,
},
{
.model = 0x7000,
.revision = 0x6204,
Expand Down
27 changes: 17 additions & 10 deletions drivers/gpu/drm/etnaviv/etnaviv_mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ static int etnaviv_iommu_map(struct etnaviv_iommu_context *context, u32 iova,
return -EINVAL;

for_each_sgtable_dma_sg(sgt, sg, i) {
u32 pa = sg_dma_address(sg) - sg->offset;
phys_addr_t pa = sg_dma_address(sg) - sg->offset;
size_t bytes = sg_dma_len(sg) + sg->offset;

VERB("map[%d]: %08x %08x(%zx)", i, iova, pa, bytes);
VERB("map[%d]: %08x %pap(%zx)", i, iova, &pa, bytes);

ret = etnaviv_context_map(context, da, pa, bytes, prot);
if (ret)
Expand Down Expand Up @@ -135,6 +135,19 @@ static void etnaviv_iommu_remove_mapping(struct etnaviv_iommu_context *context,
drm_mm_remove_node(&mapping->vram_node);
}

void etnaviv_iommu_reap_mapping(struct etnaviv_vram_mapping *mapping)
{
struct etnaviv_iommu_context *context = mapping->context;

lockdep_assert_held(&context->lock);
WARN_ON(mapping->use);

etnaviv_iommu_remove_mapping(context, mapping);
etnaviv_iommu_context_put(mapping->context);
mapping->context = NULL;
list_del_init(&mapping->mmu_node);
}

static int etnaviv_iommu_find_iova(struct etnaviv_iommu_context *context,
struct drm_mm_node *node, size_t size)
{
Expand Down Expand Up @@ -202,10 +215,7 @@ static int etnaviv_iommu_find_iova(struct etnaviv_iommu_context *context,
* this mapping.
*/
list_for_each_entry_safe(m, n, &list, scan_node) {
etnaviv_iommu_remove_mapping(context, m);
etnaviv_iommu_context_put(m->context);
m->context = NULL;
list_del_init(&m->mmu_node);
etnaviv_iommu_reap_mapping(m);
list_del_init(&m->scan_node);
}

Expand Down Expand Up @@ -257,10 +267,7 @@ static int etnaviv_iommu_insert_exact(struct etnaviv_iommu_context *context,
}

list_for_each_entry_safe(m, n, &scan_list, scan_node) {
etnaviv_iommu_remove_mapping(context, m);
etnaviv_iommu_context_put(m->context);
m->context = NULL;
list_del_init(&m->mmu_node);
etnaviv_iommu_reap_mapping(m);
list_del_init(&m->scan_node);
}

Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/etnaviv/etnaviv_mmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu_context *context,
struct etnaviv_vram_mapping *mapping, u64 va);
void etnaviv_iommu_unmap_gem(struct etnaviv_iommu_context *context,
struct etnaviv_vram_mapping *mapping);
void etnaviv_iommu_reap_mapping(struct etnaviv_vram_mapping *mapping);

int etnaviv_iommu_get_suballoc_va(struct etnaviv_iommu_context *ctx,
struct etnaviv_vram_mapping *mapping,
Expand Down
Loading

0 comments on commit 819683a

Please sign in to comment.