mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
Merge tag 'drm-misc-next-fixes-2026-02-05' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next
Several fixes for amdxdna around PM handling, error reporting and memory safety, a compilation fix for ilitek-ili9882t, a NULL pointer dereference fix for imx8qxp-pixel-combiner and several PTE fixes for nouveau Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maxime Ripard <mripard@redhat.com> Link: https://patch.msgid.link/20260205-refreshing-natural-vole-4c73af@houat
This commit is contained in:
@@ -47,17 +47,6 @@ static void aie2_job_put(struct amdxdna_sched_job *job)
|
||||
kref_put(&job->refcnt, aie2_job_release);
|
||||
}
|
||||
|
||||
static void aie2_hwctx_status_shift_stop(struct amdxdna_hwctx *hwctx)
|
||||
{
|
||||
hwctx->old_status = hwctx->status;
|
||||
hwctx->status = HWCTX_STAT_STOP;
|
||||
}
|
||||
|
||||
static void aie2_hwctx_status_restore(struct amdxdna_hwctx *hwctx)
|
||||
{
|
||||
hwctx->status = hwctx->old_status;
|
||||
}
|
||||
|
||||
/* The bad_job is used in aie2_sched_job_timedout, otherwise, set it to NULL */
|
||||
static void aie2_hwctx_stop(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hwctx,
|
||||
struct drm_sched_job *bad_job)
|
||||
@@ -84,11 +73,6 @@ static int aie2_hwctx_restart(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hw
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (hwctx->status != HWCTX_STAT_READY) {
|
||||
XDNA_DBG(xdna, "hwctx is not ready, status %d", hwctx->status);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = aie2_config_cu(hwctx, NULL);
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "Config cu failed, ret %d", ret);
|
||||
@@ -140,7 +124,6 @@ static int aie2_hwctx_suspend_cb(struct amdxdna_hwctx *hwctx, void *arg)
|
||||
|
||||
aie2_hwctx_wait_for_idle(hwctx);
|
||||
aie2_hwctx_stop(xdna, hwctx, NULL);
|
||||
aie2_hwctx_status_shift_stop(hwctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -162,7 +145,6 @@ static int aie2_hwctx_resume_cb(struct amdxdna_hwctx *hwctx, void *arg)
|
||||
{
|
||||
struct amdxdna_dev *xdna = hwctx->client->xdna;
|
||||
|
||||
aie2_hwctx_status_restore(hwctx);
|
||||
return aie2_hwctx_restart(xdna, hwctx);
|
||||
}
|
||||
|
||||
@@ -292,7 +274,7 @@ aie2_sched_cmdlist_resp_handler(void *handle, void __iomem *data, size_t size)
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
amdxdna_cmd_set_state(cmd_abo, fail_cmd_status);
|
||||
amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_ERROR);
|
||||
|
||||
if (amdxdna_cmd_get_op(cmd_abo) == ERT_CMD_CHAIN) {
|
||||
struct amdxdna_cmd_chain *cc = amdxdna_cmd_get_payload(cmd_abo, NULL);
|
||||
@@ -315,12 +297,19 @@ aie2_sched_job_run(struct drm_sched_job *sched_job)
|
||||
struct dma_fence *fence;
|
||||
int ret;
|
||||
|
||||
if (!hwctx->priv->mbox_chann)
|
||||
return NULL;
|
||||
|
||||
if (!mmget_not_zero(job->mm))
|
||||
return ERR_PTR(-ESRCH);
|
||||
|
||||
kref_get(&job->refcnt);
|
||||
fence = dma_fence_get(job->fence);
|
||||
|
||||
ret = amdxdna_pm_resume_get(hwctx->client->xdna);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (job->drv_cmd) {
|
||||
switch (job->drv_cmd->opcode) {
|
||||
case SYNC_DEBUG_BO:
|
||||
@@ -347,6 +336,7 @@ aie2_sched_job_run(struct drm_sched_job *sched_job)
|
||||
|
||||
out:
|
||||
if (ret) {
|
||||
amdxdna_pm_suspend_put(hwctx->client->xdna);
|
||||
dma_fence_put(job->fence);
|
||||
aie2_job_put(job);
|
||||
mmput(job->mm);
|
||||
@@ -663,7 +653,6 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
|
||||
}
|
||||
amdxdna_pm_suspend_put(xdna);
|
||||
|
||||
hwctx->status = HWCTX_STAT_INIT;
|
||||
init_waitqueue_head(&priv->job_free_wq);
|
||||
|
||||
XDNA_DBG(xdna, "hwctx %s init completed", hwctx->name);
|
||||
@@ -705,7 +694,9 @@ void aie2_hwctx_fini(struct amdxdna_hwctx *hwctx)
|
||||
aie2_hwctx_wait_for_idle(hwctx);
|
||||
|
||||
/* Request fw to destroy hwctx and cancel the rest pending requests */
|
||||
drm_sched_stop(&hwctx->priv->sched, NULL);
|
||||
aie2_release_resource(hwctx);
|
||||
drm_sched_start(&hwctx->priv->sched, 0);
|
||||
|
||||
mutex_unlock(&xdna->dev_lock);
|
||||
drm_sched_entity_destroy(&hwctx->priv->entity);
|
||||
@@ -749,7 +740,7 @@ static int aie2_hwctx_cu_config(struct amdxdna_hwctx *hwctx, void *buf, u32 size
|
||||
if (XDNA_MBZ_DBG(xdna, config->pad, sizeof(config->pad)))
|
||||
return -EINVAL;
|
||||
|
||||
if (hwctx->status != HWCTX_STAT_INIT) {
|
||||
if (hwctx->cus) {
|
||||
XDNA_ERR(xdna, "Not support re-config CU");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -780,7 +771,6 @@ static int aie2_hwctx_cu_config(struct amdxdna_hwctx *hwctx, void *buf, u32 size
|
||||
}
|
||||
|
||||
wmb(); /* To avoid locking in command submit when check status */
|
||||
hwctx->status = HWCTX_STAT_READY;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1003,15 +993,11 @@ int aie2_cmd_submit(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job,
|
||||
goto free_chain;
|
||||
}
|
||||
|
||||
ret = amdxdna_pm_resume_get(xdna);
|
||||
if (ret)
|
||||
goto cleanup_job;
|
||||
|
||||
retry:
|
||||
ret = drm_gem_lock_reservations(job->bos, job->bo_cnt, &acquire_ctx);
|
||||
if (ret) {
|
||||
XDNA_WARN(xdna, "Failed to lock BOs, ret %d", ret);
|
||||
goto suspend_put;
|
||||
goto cleanup_job;
|
||||
}
|
||||
|
||||
for (i = 0; i < job->bo_cnt; i++) {
|
||||
@@ -1019,7 +1005,7 @@ retry:
|
||||
if (ret) {
|
||||
XDNA_WARN(xdna, "Failed to reserve fences %d", ret);
|
||||
drm_gem_unlock_reservations(job->bos, job->bo_cnt, &acquire_ctx);
|
||||
goto suspend_put;
|
||||
goto cleanup_job;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1034,12 +1020,12 @@ retry:
|
||||
msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
|
||||
} else if (time_after(jiffies, timeout)) {
|
||||
ret = -ETIME;
|
||||
goto suspend_put;
|
||||
goto cleanup_job;
|
||||
}
|
||||
|
||||
ret = aie2_populate_range(abo);
|
||||
if (ret)
|
||||
goto suspend_put;
|
||||
goto cleanup_job;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
@@ -1065,8 +1051,6 @@ retry:
|
||||
|
||||
return 0;
|
||||
|
||||
suspend_put:
|
||||
amdxdna_pm_suspend_put(xdna);
|
||||
cleanup_job:
|
||||
drm_sched_job_cleanup(&job->base);
|
||||
free_chain:
|
||||
|
||||
@@ -493,6 +493,9 @@ int aie2_config_cu(struct amdxdna_hwctx *hwctx,
|
||||
if (!chann)
|
||||
return -ENODEV;
|
||||
|
||||
if (!hwctx->cus)
|
||||
return 0;
|
||||
|
||||
if (hwctx->cus->num_cus > MAX_NUM_CUS) {
|
||||
XDNA_DBG(xdna, "Exceed maximum CU %d", MAX_NUM_CUS);
|
||||
return -EINVAL;
|
||||
|
||||
@@ -36,6 +36,8 @@ int aie2_pm_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level)
|
||||
return ret;
|
||||
|
||||
ret = ndev->priv->hw_ops.set_dpm(ndev, dpm_level);
|
||||
if (!ret)
|
||||
ndev->dpm_level = dpm_level;
|
||||
amdxdna_pm_suspend_put(ndev->xdna);
|
||||
|
||||
return ret;
|
||||
@@ -65,6 +67,7 @@ int aie2_pm_init(struct amdxdna_dev_hdl *ndev)
|
||||
ret = ndev->priv->hw_ops.set_dpm(ndev, ndev->max_dpm_level);
|
||||
if (ret)
|
||||
return ret;
|
||||
ndev->dpm_level = ndev->max_dpm_level;
|
||||
|
||||
ret = aie2_pm_set_clk_gating(ndev, AIE2_CLK_GATING_ENABLE);
|
||||
if (ret)
|
||||
|
||||
@@ -84,7 +84,6 @@ int npu1_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level)
|
||||
}
|
||||
|
||||
ndev->hclk_freq = freq;
|
||||
ndev->dpm_level = dpm_level;
|
||||
ndev->max_tops = 2 * ndev->total_col;
|
||||
ndev->curr_tops = ndev->max_tops * freq / 1028;
|
||||
|
||||
@@ -114,7 +113,6 @@ int npu4_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level)
|
||||
|
||||
ndev->npuclk_freq = ndev->priv->dpm_clk_tbl[dpm_level].npuclk;
|
||||
ndev->hclk_freq = ndev->priv->dpm_clk_tbl[dpm_level].hclk;
|
||||
ndev->dpm_level = dpm_level;
|
||||
ndev->max_tops = NPU4_DPM_TOPS(ndev, ndev->max_dpm_level);
|
||||
ndev->curr_tops = NPU4_DPM_TOPS(ndev, dpm_level);
|
||||
|
||||
|
||||
@@ -99,11 +99,6 @@ struct amdxdna_hwctx {
|
||||
u32 start_col;
|
||||
u32 num_col;
|
||||
u32 num_unused_col;
|
||||
#define HWCTX_STAT_INIT 0
|
||||
#define HWCTX_STAT_READY 1
|
||||
#define HWCTX_STAT_STOP 2
|
||||
u32 status;
|
||||
u32 old_status;
|
||||
|
||||
struct amdxdna_qos_info qos;
|
||||
struct amdxdna_hwctx_param_config_cu *cus;
|
||||
|
||||
@@ -82,6 +82,8 @@ static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp)
|
||||
ret = -ENODEV;
|
||||
goto unbind_sva;
|
||||
}
|
||||
client->mm = current->mm;
|
||||
mmgrab(client->mm);
|
||||
init_srcu_struct(&client->hwctx_srcu);
|
||||
xa_init_flags(&client->hwctx_xa, XA_FLAGS_ALLOC);
|
||||
mutex_init(&client->mm_lock);
|
||||
@@ -116,6 +118,7 @@ static void amdxdna_client_cleanup(struct amdxdna_client *client)
|
||||
drm_gem_object_put(to_gobj(client->dev_heap));
|
||||
|
||||
iommu_sva_unbind_device(client->sva);
|
||||
mmdrop(client->mm);
|
||||
|
||||
kfree(client);
|
||||
}
|
||||
|
||||
@@ -130,6 +130,7 @@ struct amdxdna_client {
|
||||
|
||||
struct iommu_sva *sva;
|
||||
int pasid;
|
||||
struct mm_struct *mm;
|
||||
};
|
||||
|
||||
#define amdxdna_for_each_hwctx(client, hwctx_id, entry) \
|
||||
|
||||
@@ -34,15 +34,21 @@ static struct sg_table *amdxdna_ubuf_map(struct dma_buf_attachment *attach,
|
||||
ret = sg_alloc_table_from_pages(sg, ubuf->pages, ubuf->nr_pages, 0,
|
||||
ubuf->nr_pages << PAGE_SHIFT, GFP_KERNEL);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
goto err_free_sg;
|
||||
|
||||
if (ubuf->flags & AMDXDNA_UBUF_FLAG_MAP_DMA) {
|
||||
ret = dma_map_sgtable(attach->dev, sg, direction, 0);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
goto err_free_table;
|
||||
}
|
||||
|
||||
return sg;
|
||||
|
||||
err_free_table:
|
||||
sg_free_table(sg);
|
||||
err_free_sg:
|
||||
kfree(sg);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static void amdxdna_ubuf_unmap(struct dma_buf_attachment *attach,
|
||||
|
||||
@@ -348,7 +348,7 @@ static int imx8qxp_pc_bridge_probe(struct platform_device *pdev)
|
||||
free_child:
|
||||
of_node_put(child);
|
||||
|
||||
if (i == 1 && pc->ch[0]->bridge.next_bridge)
|
||||
if (i == 1 && pc->ch[0] && pc->ch[0]->bridge.next_bridge)
|
||||
drm_bridge_remove(&pc->ch[0]->bridge);
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#define DRIVER_MAJOR 1
|
||||
#define DRIVER_MINOR 4
|
||||
#define DRIVER_PATCHLEVEL 1
|
||||
#define DRIVER_PATCHLEVEL 2
|
||||
|
||||
/*
|
||||
* 1.1.1:
|
||||
@@ -37,6 +37,8 @@
|
||||
* - implemented limited ABI16/NVIF interop
|
||||
* 1.4.1:
|
||||
* - add variable page sizes and compression for Turing+
|
||||
* 1.4.2:
|
||||
* - tell userspace LPTE/SPTE races are fixed.
|
||||
*/
|
||||
|
||||
#include <linux/notifier.h>
|
||||
|
||||
@@ -53,7 +53,7 @@ nvkm_vmm_pt_new(const struct nvkm_vmm_desc *desc, bool sparse,
|
||||
}
|
||||
}
|
||||
|
||||
if (!(pgt = kzalloc(sizeof(*pgt) + lpte, GFP_KERNEL)))
|
||||
if (!(pgt = kzalloc(sizeof(*pgt) + (sizeof(pgt->pte[0]) * lpte), GFP_KERNEL)))
|
||||
return NULL;
|
||||
pgt->page = page ? page->shift : 0;
|
||||
pgt->sparse = sparse;
|
||||
@@ -208,7 +208,7 @@ nvkm_vmm_unref_sptes(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgt,
|
||||
*/
|
||||
for (lpti = ptei >> sptb; ptes; spti = 0, lpti++) {
|
||||
const u32 pten = min(sptn - spti, ptes);
|
||||
pgt->pte[lpti] -= pten;
|
||||
pgt->pte[lpti].s.sptes -= pten;
|
||||
ptes -= pten;
|
||||
}
|
||||
|
||||
@@ -218,9 +218,9 @@ nvkm_vmm_unref_sptes(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgt,
|
||||
|
||||
for (ptei = pteb = ptei >> sptb; ptei < lpti; pteb = ptei) {
|
||||
/* Skip over any LPTEs that still have valid SPTEs. */
|
||||
if (pgt->pte[pteb] & NVKM_VMM_PTE_SPTES) {
|
||||
if (pgt->pte[pteb].s.sptes) {
|
||||
for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) {
|
||||
if (!(pgt->pte[ptei] & NVKM_VMM_PTE_SPTES))
|
||||
if (!(pgt->pte[ptei].s.sptes))
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
@@ -232,24 +232,27 @@ nvkm_vmm_unref_sptes(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgt,
|
||||
*
|
||||
* Determine how many LPTEs need to transition state.
|
||||
*/
|
||||
pgt->pte[ptei] &= ~NVKM_VMM_PTE_VALID;
|
||||
pgt->pte[ptei].s.spte_valid = false;
|
||||
for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) {
|
||||
if (pgt->pte[ptei] & NVKM_VMM_PTE_SPTES)
|
||||
if (pgt->pte[ptei].s.sptes)
|
||||
break;
|
||||
pgt->pte[ptei] &= ~NVKM_VMM_PTE_VALID;
|
||||
pgt->pte[ptei].s.spte_valid = false;
|
||||
}
|
||||
|
||||
if (pgt->pte[pteb] & NVKM_VMM_PTE_SPARSE) {
|
||||
if (pgt->pte[pteb].s.sparse) {
|
||||
TRA(it, "LPTE %05x: U -> S %d PTEs", pteb, ptes);
|
||||
pair->func->sparse(vmm, pgt->pt[0], pteb, ptes);
|
||||
} else
|
||||
if (pair->func->invalid) {
|
||||
/* If the MMU supports it, restore the LPTE to the
|
||||
* INVALID state to tell the MMU there is no point
|
||||
* trying to fetch the corresponding SPTEs.
|
||||
*/
|
||||
TRA(it, "LPTE %05x: U -> I %d PTEs", pteb, ptes);
|
||||
pair->func->invalid(vmm, pgt->pt[0], pteb, ptes);
|
||||
} else if (!pgt->pte[pteb].s.lpte_valid) {
|
||||
if (pair->func->invalid) {
|
||||
/* If the MMU supports it, restore the LPTE to the
|
||||
* INVALID state to tell the MMU there is no point
|
||||
* trying to fetch the corresponding SPTEs.
|
||||
*/
|
||||
TRA(it, "LPTE %05x: U -> I %d PTEs", pteb, ptes);
|
||||
pair->func->invalid(vmm, pgt->pt[0], pteb, ptes);
|
||||
}
|
||||
} else {
|
||||
TRA(it, "LPTE %05x: V %d PTEs", pteb, ptes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -280,6 +283,15 @@ nvkm_vmm_unref_ptes(struct nvkm_vmm_iter *it, bool pfn, u32 ptei, u32 ptes)
|
||||
if (desc->type == SPT && (pgt->refs[0] || pgt->refs[1]))
|
||||
nvkm_vmm_unref_sptes(it, pgt, desc, ptei, ptes);
|
||||
|
||||
if (desc->type == LPT && (pgt->refs[0] || pgt->refs[1])) {
|
||||
for (u32 lpti = ptei; ptes; lpti++) {
|
||||
pgt->pte[lpti].s.lptes--;
|
||||
if (pgt->pte[lpti].s.lptes == 0)
|
||||
pgt->pte[lpti].s.lpte_valid = false;
|
||||
ptes--;
|
||||
}
|
||||
}
|
||||
|
||||
/* PT no longer needed? Destroy it. */
|
||||
if (!pgt->refs[type]) {
|
||||
it->lvl++;
|
||||
@@ -307,7 +319,7 @@ nvkm_vmm_ref_sptes(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgt,
|
||||
*/
|
||||
for (lpti = ptei >> sptb; ptes; spti = 0, lpti++) {
|
||||
const u32 pten = min(sptn - spti, ptes);
|
||||
pgt->pte[lpti] += pten;
|
||||
pgt->pte[lpti].s.sptes += pten;
|
||||
ptes -= pten;
|
||||
}
|
||||
|
||||
@@ -317,9 +329,9 @@ nvkm_vmm_ref_sptes(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgt,
|
||||
|
||||
for (ptei = pteb = ptei >> sptb; ptei < lpti; pteb = ptei) {
|
||||
/* Skip over any LPTEs that already have valid SPTEs. */
|
||||
if (pgt->pte[pteb] & NVKM_VMM_PTE_VALID) {
|
||||
if (pgt->pte[pteb].s.spte_valid) {
|
||||
for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) {
|
||||
if (!(pgt->pte[ptei] & NVKM_VMM_PTE_VALID))
|
||||
if (!pgt->pte[ptei].s.spte_valid)
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
@@ -331,14 +343,16 @@ nvkm_vmm_ref_sptes(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgt,
|
||||
*
|
||||
* Determine how many LPTEs need to transition state.
|
||||
*/
|
||||
pgt->pte[ptei] |= NVKM_VMM_PTE_VALID;
|
||||
pgt->pte[ptei].s.spte_valid = true;
|
||||
pgt->pte[ptei].s.lpte_valid = false;
|
||||
for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) {
|
||||
if (pgt->pte[ptei] & NVKM_VMM_PTE_VALID)
|
||||
if (pgt->pte[ptei].s.spte_valid)
|
||||
break;
|
||||
pgt->pte[ptei] |= NVKM_VMM_PTE_VALID;
|
||||
pgt->pte[ptei].s.spte_valid = true;
|
||||
pgt->pte[ptei].s.lpte_valid = false;
|
||||
}
|
||||
|
||||
if (pgt->pte[pteb] & NVKM_VMM_PTE_SPARSE) {
|
||||
if (pgt->pte[pteb].s.sparse) {
|
||||
const u32 spti = pteb * sptn;
|
||||
const u32 sptc = ptes * sptn;
|
||||
/* The entire LPTE is marked as sparse, we need
|
||||
@@ -374,6 +388,15 @@ nvkm_vmm_ref_ptes(struct nvkm_vmm_iter *it, bool pfn, u32 ptei, u32 ptes)
|
||||
if (desc->type == SPT)
|
||||
nvkm_vmm_ref_sptes(it, pgt, desc, ptei, ptes);
|
||||
|
||||
if (desc->type == LPT) {
|
||||
for (u32 lpti = ptei; ptes; lpti++) {
|
||||
pgt->pte[lpti].s.spte_valid = false;
|
||||
pgt->pte[lpti].s.lpte_valid = true;
|
||||
pgt->pte[lpti].s.lptes++;
|
||||
ptes--;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -386,7 +409,8 @@ nvkm_vmm_sparse_ptes(const struct nvkm_vmm_desc *desc,
|
||||
pgt->pde[ptei++] = NVKM_VMM_PDE_SPARSE;
|
||||
} else
|
||||
if (desc->type == LPT) {
|
||||
memset(&pgt->pte[ptei], NVKM_VMM_PTE_SPARSE, ptes);
|
||||
union nvkm_pte_tracker sparse = { .s.sparse = 1 };
|
||||
memset32(&pgt->pte[ptei].u, sparse.u, ptes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -398,7 +422,7 @@ nvkm_vmm_sparse_unref_ptes(struct nvkm_vmm_iter *it, bool pfn, u32 ptei, u32 pte
|
||||
memset(&pt->pde[ptei], 0x00, sizeof(pt->pde[0]) * ptes);
|
||||
else
|
||||
if (it->desc->type == LPT)
|
||||
memset(&pt->pte[ptei], 0x00, sizeof(pt->pte[0]) * ptes);
|
||||
memset32(&pt->pte[ptei].u, 0x00, ptes);
|
||||
return nvkm_vmm_unref_ptes(it, pfn, ptei, ptes);
|
||||
}
|
||||
|
||||
@@ -445,9 +469,9 @@ nvkm_vmm_ref_hwpt(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgd, u32 pdei)
|
||||
* the SPTEs on some GPUs.
|
||||
*/
|
||||
for (ptei = pteb = 0; ptei < pten; pteb = ptei) {
|
||||
bool spte = pgt->pte[ptei] & NVKM_VMM_PTE_SPTES;
|
||||
bool spte = !!pgt->pte[ptei].s.sptes;
|
||||
for (ptes = 1, ptei++; ptei < pten; ptes++, ptei++) {
|
||||
bool next = pgt->pte[ptei] & NVKM_VMM_PTE_SPTES;
|
||||
bool next = !!pgt->pte[ptei].s.sptes;
|
||||
if (spte != next)
|
||||
break;
|
||||
}
|
||||
@@ -457,11 +481,11 @@ nvkm_vmm_ref_hwpt(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgd, u32 pdei)
|
||||
desc->func->sparse(vmm, pt, pteb, ptes);
|
||||
else
|
||||
desc->func->invalid(vmm, pt, pteb, ptes);
|
||||
memset(&pgt->pte[pteb], 0x00, ptes);
|
||||
memset32(&pgt->pte[pteb].u, 0x00, ptes);
|
||||
} else {
|
||||
desc->func->unmap(vmm, pt, pteb, ptes);
|
||||
while (ptes--)
|
||||
pgt->pte[pteb++] |= NVKM_VMM_PTE_VALID;
|
||||
pgt->pte[pteb++].s.spte_valid = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -4,6 +4,17 @@
|
||||
#include <core/memory.h>
|
||||
enum nvkm_memory_target;
|
||||
|
||||
union nvkm_pte_tracker {
|
||||
u32 u;
|
||||
struct {
|
||||
u32 sparse:1;
|
||||
u32 spte_valid:1;
|
||||
u32 lpte_valid:1;
|
||||
u32 lptes:13;
|
||||
u32 sptes:16;
|
||||
} s;
|
||||
};
|
||||
|
||||
struct nvkm_vmm_pt {
|
||||
/* Some GPUs have a mapping level with a dual page tables to
|
||||
* support large and small pages in the same address-range.
|
||||
@@ -44,10 +55,7 @@ struct nvkm_vmm_pt {
|
||||
*
|
||||
* This information is used to manage LPTE state transitions.
|
||||
*/
|
||||
#define NVKM_VMM_PTE_SPARSE 0x80
|
||||
#define NVKM_VMM_PTE_VALID 0x40
|
||||
#define NVKM_VMM_PTE_SPTES 0x3f
|
||||
u8 pte[];
|
||||
union nvkm_pte_tracker pte[];
|
||||
};
|
||||
|
||||
typedef void (*nvkm_vmm_pxe_func)(struct nvkm_vmm *,
|
||||
|
||||
@@ -88,11 +88,9 @@ static const struct drm_dsc_config tianma_il79900a_dsc = {
|
||||
.native_422 = false,
|
||||
.simple_422 = false,
|
||||
.vbr_enable = false,
|
||||
.rc_model_size = DSC_RC_MODEL_SIZE_CONST,
|
||||
.pic_width = 1600,
|
||||
.pic_height = 2560,
|
||||
.convert_rgb = 0,
|
||||
.vbr_enable = 0,
|
||||
.rc_buf_thresh = {14, 28, 42, 56, 70, 84, 98, 105, 112, 119, 121, 123, 125, 126},
|
||||
.rc_model_size = DSC_RC_MODEL_SIZE_CONST,
|
||||
.rc_edge_factor = DSC_RC_EDGE_FACTOR_CONST,
|
||||
@@ -105,7 +103,6 @@ static const struct drm_dsc_config tianma_il79900a_dsc = {
|
||||
.initial_offset = 6144,
|
||||
.rc_quant_incr_limit0 = 11,
|
||||
.rc_quant_incr_limit1 = 11,
|
||||
.nfl_bpg_offset = 1402,
|
||||
.rc_range_params = {
|
||||
{ 0, 4, DSC_BPG_OFFSET(2)},
|
||||
{ 0, 4, DSC_BPG_OFFSET(0)},
|
||||
@@ -123,7 +120,6 @@ static const struct drm_dsc_config tianma_il79900a_dsc = {
|
||||
{ 9, 12, DSC_BPG_OFFSET(-12)},
|
||||
{12, 13, DSC_BPG_OFFSET(-12)},
|
||||
},
|
||||
.initial_scale_value = 32,
|
||||
.slice_chunk_size = 800,
|
||||
.initial_dec_delay = 657,
|
||||
.final_offset = 4320,
|
||||
|
||||
Reference in New Issue
Block a user