Pull drm fixes from Dave Airlie:
 "Weekly fixes for drm. This is large for rc2 but it's just a lot of
  small fixes across a bunch of drivers, xe, amdgpu as usual, plus some
  sashiko-inspired fixes for panthor, and some dma-fence updates.

  core:
   - kernel doc fix
   - include types.h in drm_ras.h

  dma-fence:
   - fix NULL ptr dereference
   - use correct callback
   - make dma_fence_dedup_array more robust

  dp:
   - handle torn down topology gracefully
   - fix kernel doc

  i915:
   - Input validation fixes for BIOS and EDID
   - Fix HDCP code buffer overflow and seq_num_v monotonic increase check
   - Fix near-NULL deref in i915_active during GFP_ATOMIC exhaustion

  xe:
   - Wedge from the timeout handler only after releasing the queue
   - Fix a NULL pointer dereference
   - Remove redundant exec_queue_suspended
   - RTP / OA whitelist fixes
   - Return error on non-migratable faults requiring devmem
   - Skip FORCE_WC and vm_bound check for external dma-bufs
   - Hold notifier lock for write on inject test path
   - Drop bogus static from finish in force_invalidate
   - Fix double-free of managed BO in error path
   - Don't attempt to process FAST_REQ or EVENT relays
   - Fix NPD in bo_meminfo
   - Prevent invalid cursor access for purged BOs
   - Fix offset alignment for MERT WHITELST_OA_MERT_MMIO_TRG

  amdgpu:
   - Soc24 aborted suspend fix
   - Drop unecessary BUG() and BUG_ON() from error paths
   - SCPM fix
   - Power reporting fix
   - DCE HDR fix
   - UVD boundary checks
   - VCN boundary checks
   - VCE boundary checks
   - DCN 4.2 fixes
   - Large stack allocation fixes
   - Fix aperture mapping leak
   - UserQ fixes
   - Ignore_damage_clips fix
   - ACP fixes
   - DC boundary checks
   - GPUVM fixes
   - JPEG idle check fixes
   - Userptr fix
   - GC 11.7 updates
   - Non-4K page fix
   - SMU 13 fixes
   - DP alt mode fix

  amdkfd:
   - Boundary checks
   - CRIU fixes

  amdxdna:
   - fix device removal issues
   - fix use after free in debug BO

  imagination:
   - fix double call to scheduler fini
   - fix ioctl return values
   - fix user array stride

  virtio:
   - handle EDIDs better

  panthor:
   - irq safe fence lock fix
   - reset work fix
   - fix invalid pointer
   - fix iomem access in suspended state
   - sched resume fix
   - unplug suspend fix
   - drop needless check
   - eviction leak fix
   - bail on group start/resume fix
   - keep irqs masked

  malidp:
   - use clock bulk API

  komeda:
   - clock prepare fixes"

* tag 'drm-fixes-2026-07-04' of https://gitlab.freedesktop.org/drm/kernel: (105 commits)
  drm/xe/oa: Fix offset alignment for MERT WHITELIST_OA_MERT_MMIO_TRG
  drm/xe/pt: prevent invalid cursor access for purged BOs
  drm/xe: fix NPD in bo_meminfo()
  drm/xe/pf: Don't attempt to process FAST_REQ or EVENT relays
  drm/xe/hw_engine: Fix double-free of managed BO in error path
  drm/xe/userptr: Drop bogus static from finish in force_invalidate
  drm/xe/userptr: Hold notifier_lock for write on inject test path
  drm/xe/display: skip FORCE_WC and vm_bound check for external dma-bufs
  drm/xe: Return error on non-migratable faults requiring devmem
  drm/xe/rtp: Ensure locking/ref counting for OA whitelists
  drm/xe/oa: (De-)whitelist OA registers on OA stream open/release
  drm/xe/rtp: (De-)whitelist OA registers for all hwe's for a gt
  drm/xe/rtp: Toggle 'deny' bit to (de-)whitelist OA regs
  drm/xe/rtp: Save OA nonpriv registers to register save/restore lists
  drm/xe/rtp: Generalize whitelist_apply_to_hwe
  drm/xe/rtp: Keep track of non-OA nonpriv slots
  drm/xe/rtp: Maintain OA whitelists separately
  drm/xe/rtp: Fix build error with clang < 21 and non-const initializers
  drm/imagination: Fix user array stride in pvr_set_uobj_array()
  drm/imagination: Fix returned size for DRM_IOCTL_PVR_DEV_QUERY
  ...
This commit is contained in:
Linus Torvalds
2026-07-03 15:42:20 -10:00
115 changed files with 1228 additions and 643 deletions

View File

@@ -59,6 +59,18 @@ static bool aie2_tdr_detect(struct amdxdna_dev *xdna)
return false;
}
static void aie2_cmd_release(struct kref *ref)
{
struct amdxdna_drv_cmd *drv_cmd = container_of(ref, struct amdxdna_drv_cmd, refcnt);
kfree(drv_cmd);
}
static void aie2_cmd_put(struct amdxdna_drv_cmd *drv_cmd)
{
kref_put(&drv_cmd->refcnt, aie2_cmd_release);
}
static void aie2_job_release(struct kref *ref)
{
struct amdxdna_sched_job *job;
@@ -70,6 +82,8 @@ static void aie2_job_release(struct kref *ref)
wake_up(&job->hwctx->priv->job_free_wq);
if (job->out_fence)
dma_fence_put(job->out_fence);
if (job->drv_cmd)
aie2_cmd_put(job->drv_cmd);
kfree(job->aie2_job_health);
kfree(job);
}
@@ -901,7 +915,7 @@ static int aie2_hwctx_cfg_debug_bo(struct amdxdna_hwctx *hwctx, u32 bo_hdl,
{
struct amdxdna_client *client = hwctx->client;
struct amdxdna_dev *xdna = client->xdna;
struct amdxdna_drv_cmd cmd = { 0 };
struct amdxdna_drv_cmd *cmd;
struct amdxdna_gem_obj *abo;
u64 seq;
int ret;
@@ -912,32 +926,39 @@ static int aie2_hwctx_cfg_debug_bo(struct amdxdna_hwctx *hwctx, u32 bo_hdl,
return -EINVAL;
}
cmd = kzalloc_obj(*cmd);
if (!cmd) {
ret = -ENOMEM;
goto put_obj;
}
kref_init(&cmd->refcnt);
if (attach) {
if (abo->assigned_hwctx != AMDXDNA_INVALID_CTX_HANDLE) {
ret = -EBUSY;
goto put_obj;
goto put_cmd;
}
cmd.opcode = ATTACH_DEBUG_BO;
cmd->opcode = ATTACH_DEBUG_BO;
} else {
if (abo->assigned_hwctx != hwctx->id) {
ret = -EINVAL;
goto put_obj;
goto put_cmd;
}
cmd.opcode = DETACH_DEBUG_BO;
cmd->opcode = DETACH_DEBUG_BO;
}
ret = amdxdna_cmd_submit(client, &cmd, AMDXDNA_INVALID_BO_HANDLE,
ret = amdxdna_cmd_submit(client, cmd, AMDXDNA_INVALID_BO_HANDLE,
&bo_hdl, 1, hwctx->id, &seq);
if (ret) {
XDNA_ERR(xdna, "Submit command failed");
goto put_obj;
goto put_cmd;
}
aie2_cmd_wait(hwctx, seq);
if (cmd.result) {
XDNA_ERR(xdna, "Response failure 0x%x", cmd.result);
if (cmd->result) {
XDNA_ERR(xdna, "Response failure 0x%x", cmd->result);
ret = -EINVAL;
goto put_obj;
goto put_cmd;
}
if (attach)
@@ -947,6 +968,8 @@ static int aie2_hwctx_cfg_debug_bo(struct amdxdna_hwctx *hwctx, u32 bo_hdl,
XDNA_DBG(xdna, "Config debug BO %d to %s", bo_hdl, hwctx->name);
put_cmd:
aie2_cmd_put(cmd);
put_obj:
amdxdna_gem_put_obj(abo);
return ret;
@@ -974,25 +997,32 @@ int aie2_hwctx_sync_debug_bo(struct amdxdna_hwctx *hwctx, u32 debug_bo_hdl)
{
struct amdxdna_client *client = hwctx->client;
struct amdxdna_dev *xdna = client->xdna;
struct amdxdna_drv_cmd cmd = { 0 };
struct amdxdna_drv_cmd *cmd;
u64 seq;
int ret;
cmd.opcode = SYNC_DEBUG_BO;
ret = amdxdna_cmd_submit(client, &cmd, AMDXDNA_INVALID_BO_HANDLE,
cmd = kzalloc_obj(*cmd);
if (!cmd)
return -ENOMEM;
kref_init(&cmd->refcnt);
cmd->opcode = SYNC_DEBUG_BO;
ret = amdxdna_cmd_submit(client, cmd, AMDXDNA_INVALID_BO_HANDLE,
&debug_bo_hdl, 1, hwctx->id, &seq);
if (ret) {
XDNA_ERR(xdna, "Submit command failed");
return ret;
goto put_cmd;
}
aie2_cmd_wait(hwctx, seq);
if (cmd.result) {
XDNA_ERR(xdna, "Response failure 0x%x", cmd.result);
return -EINVAL;
if (cmd->result) {
XDNA_ERR(xdna, "Response failure 0x%x", cmd->result);
ret = -EINVAL;
}
return 0;
put_cmd:
aie2_cmd_put(cmd);
return ret;
}
static int aie2_populate_range(struct amdxdna_gem_obj *abo)
@@ -1142,6 +1172,8 @@ int aie2_cmd_submit(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job,
dma_resv_add_fence(job->bos[i]->resv, job->out_fence, DMA_RESV_USAGE_WRITE);
job->seq = hwctx->priv->seq++;
kref_get(&job->refcnt);
if (job->drv_cmd)
kref_get(&job->drv_cmd->refcnt);
drm_sched_entity_push_job(&job->base);
*seq = job->seq;

View File

@@ -132,6 +132,7 @@ enum amdxdna_job_opcode {
struct amdxdna_drv_cmd {
enum amdxdna_job_opcode opcode;
u32 result;
struct kref refcnt;
};
struct app_health_report;

View File

@@ -4,6 +4,7 @@
*/
#include <drm/amdxdna_accel.h>
#include <drm/drm_managed.h>
#include <linux/iommu.h>
#include <linux/iova.h>
@@ -153,10 +154,30 @@ void amdxdna_iommu_free(struct amdxdna_dev *xdna, size_t size,
free_pages((unsigned long)cpu_addr, get_order(size));
}
static void amdxdna_cleanup_force_iova(struct drm_device *dev, void *res)
{
struct amdxdna_dev *xdna = to_xdna_dev(dev);
if (xdna->domain) {
iommu_detach_group(xdna->domain, xdna->group);
put_iova_domain(&xdna->iovad);
iova_cache_put();
iommu_domain_free(xdna->domain);
}
iommu_group_put(xdna->group);
}
void amdxdna_iommu_fini(struct amdxdna_dev *xdna)
{
if (xdna->group && !xdna->domain)
iommu_group_put(xdna->group);
}
int amdxdna_iommu_init(struct amdxdna_dev *xdna)
{
unsigned long order;
int ret;
int ret = 0;
xdna->group = iommu_group_get(xdna->ddev.dev);
if (!xdna->group || !force_iova)
@@ -182,8 +203,14 @@ int amdxdna_iommu_init(struct amdxdna_dev *xdna)
if (ret)
goto put_iova;
ret = drmm_add_action(&xdna->ddev, amdxdna_cleanup_force_iova, NULL);
if (ret)
goto detach_group;
return 0;
detach_group:
iommu_detach_group(xdna->domain, xdna->group);
put_iova:
put_iova_domain(&xdna->iovad);
iova_cache_put();
@@ -191,20 +218,8 @@ int amdxdna_iommu_init(struct amdxdna_dev *xdna)
iommu_domain_free(xdna->domain);
put_group:
iommu_group_put(xdna->group);
xdna->group = NULL;
xdna->domain = NULL;
return ret;
}
void amdxdna_iommu_fini(struct amdxdna_dev *xdna)
{
if (xdna->domain) {
iommu_detach_group(xdna->domain, xdna->group);
put_iova_domain(&xdna->iovad);
iova_cache_put();
iommu_domain_free(xdna->domain);
}
if (xdna->group)
iommu_group_put(xdna->group);
}

View File

@@ -138,9 +138,11 @@ static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp)
xdna->dev_info->dev_heap_max_size);
mutex_init(&client->mm_lock);
mutex_lock(&xdna->client_lock);
mutex_lock(&xdna->dev_lock);
list_add_tail(&client->node, &xdna->client_list);
mutex_unlock(&xdna->dev_lock);
mutex_unlock(&xdna->client_lock);
filp->driver_priv = client;
client->filp = filp;
@@ -174,18 +176,14 @@ static void amdxdna_drm_close(struct drm_device *ddev, struct drm_file *filp)
{
struct amdxdna_client *client = filp->driver_priv;
struct amdxdna_dev *xdna = to_xdna_dev(ddev);
int idx;
XDNA_DBG(xdna, "closing pid %d", client->pid);
if (!drm_dev_enter(&xdna->ddev, &idx))
return;
mutex_lock(&xdna->client_lock);
mutex_lock(&xdna->dev_lock);
amdxdna_client_cleanup(client);
mutex_unlock(&xdna->dev_lock);
drm_dev_exit(idx);
mutex_unlock(&xdna->client_lock);
}
static int amdxdna_drm_get_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
@@ -371,6 +369,10 @@ static int amdxdna_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (!xdna->dev_info)
return -ENODEV;
ret = drmm_mutex_init(ddev, &xdna->client_lock);
if (ret)
return ret;
drmm_mutex_init(ddev, &xdna->dev_lock);
init_rwsem(&xdna->notifier_lock);
INIT_LIST_HEAD(&xdna->client_list);
@@ -390,9 +392,9 @@ static int amdxdna_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
return ret;
xdna->notifier_wq = alloc_ordered_workqueue("notifier_wq", WQ_MEM_RECLAIM);
if (!xdna->notifier_wq) {
ret = -ENOMEM;
xdna->notifier_wq = drmm_alloc_ordered_workqueue(ddev, "notifier_wq", WQ_MEM_RECLAIM);
if (IS_ERR(xdna->notifier_wq)) {
ret = PTR_ERR(xdna->notifier_wq);
goto iommu_fini;
}
@@ -401,7 +403,7 @@ static int amdxdna_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mutex_unlock(&xdna->dev_lock);
if (ret) {
XDNA_ERR(xdna, "Hardware init failed, ret %d", ret);
goto destroy_notifier_wq;
goto iommu_fini;
}
ret = amdxdna_sysfs_init(xdna);
@@ -425,8 +427,6 @@ static int amdxdna_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mutex_lock(&xdna->dev_lock);
xdna->dev_info->ops->fini(xdna);
mutex_unlock(&xdna->dev_lock);
destroy_notifier_wq:
destroy_workqueue(xdna->notifier_wq);
iommu_fini:
amdxdna_iommu_fini(xdna);
return ret;
@@ -437,23 +437,19 @@ static void amdxdna_remove(struct pci_dev *pdev)
struct amdxdna_dev *xdna = pci_get_drvdata(pdev);
struct amdxdna_client *client;
destroy_workqueue(xdna->notifier_wq);
drm_dev_unplug(&xdna->ddev);
amdxdna_sysfs_fini(xdna);
mutex_lock(&xdna->client_lock);
mutex_lock(&xdna->dev_lock);
client = list_first_entry_or_null(&xdna->client_list,
struct amdxdna_client, node);
while (client) {
amdxdna_client_cleanup(client);
client = list_first_entry_or_null(&xdna->client_list,
struct amdxdna_client, node);
list_for_each_entry(client, &xdna->client_list, node) {
amdxdna_hwctx_remove_all(client);
amdxdna_sva_fini(client);
}
xdna->dev_info->ops->fini(xdna);
mutex_unlock(&xdna->dev_lock);
mutex_unlock(&xdna->client_lock);
amdxdna_iommu_fini(xdna);
}

View File

@@ -120,6 +120,7 @@ struct amdxdna_dev {
struct mutex dev_lock; /* per device lock */
struct list_head client_list;
struct mutex client_lock; /* client_list */
struct amdxdna_fw_ver fw_ver;
struct rw_semaphore notifier_lock; /* for mmu notifier*/
struct workqueue_struct *notifier_wq;

View File

@@ -97,6 +97,9 @@ int dma_fence_dedup_array(struct dma_fence **fences, int num_fences)
{
int i, j;
if (!num_fences)
return 0;
sort(fences, num_fences, sizeof(*fences), fence_cmp, NULL);
/*

View File

@@ -1168,7 +1168,7 @@ const char __rcu *dma_fence_driver_name(struct dma_fence *fence)
/* RCU protection is required for safe access to returned string */
ops = rcu_dereference(fence->ops);
if (!dma_fence_test_signaled_flag(fence))
if (ops)
return (const char __rcu *)ops->get_driver_name(fence);
else
return (const char __rcu *)"detached-driver";
@@ -1201,8 +1201,8 @@ const char __rcu *dma_fence_timeline_name(struct dma_fence *fence)
/* RCU protection is required for safe access to returned string */
ops = rcu_dereference(fence->ops);
if (!dma_fence_test_signaled_flag(fence))
return (const char __rcu *)ops->get_driver_name(fence);
if (ops)
return (const char __rcu *)ops->get_timeline_name(fence);
else
return (const char __rcu *)"signaled-timeline";
}

View File

@@ -508,6 +508,7 @@ static int acp_hw_fini(struct amdgpu_ip_block *ip_block)
u32 val = 0;
u32 count = 0;
struct amdgpu_device *adev = ip_block->adev;
int ret = 0;
/* return early if no ACP */
if (!adev->acp.acp_genpd) {
@@ -529,7 +530,8 @@ static int acp_hw_fini(struct amdgpu_ip_block *ip_block)
break;
if (--count == 0) {
dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
return -ETIMEDOUT;
ret = -ETIMEDOUT;
goto out;
}
udelay(100);
}
@@ -546,21 +548,24 @@ static int acp_hw_fini(struct amdgpu_ip_block *ip_block)
break;
if (--count == 0) {
dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
return -ETIMEDOUT;
ret = -ETIMEDOUT;
goto out;
}
udelay(100);
}
out:
device_for_each_child(adev->acp.parent, NULL,
acp_genpd_remove_device);
mfd_remove_devices(adev->acp.parent);
kfree(adev->acp.i2s_pdata);
kfree(adev->acp.acp_res);
pm_genpd_remove(&adev->acp.acp_genpd->gpd);
kfree(adev->acp.acp_genpd);
adev->acp.acp_genpd = NULL;
kfree(adev->acp.acp_cell);
return 0;
return ret;
}
static int acp_suspend(struct amdgpu_ip_block *ip_block)

View File

@@ -1322,7 +1322,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
e->range = NULL;
}
if (r || !list_empty(&vm->individual.moved)) {
if (r || !list_empty(&vm->individual.needs_update)) {
r = -EAGAIN;
mutex_unlock(&p->adev->notifier_lock);
return r;

View File

@@ -4184,8 +4184,6 @@ static void amdgpu_device_unmap_mmio(struct amdgpu_device *adev)
iounmap(adev->rmmio);
adev->rmmio = NULL;
if (adev->mman.aper_base_kaddr)
iounmap(adev->mman.aper_base_kaddr);
adev->mman.aper_base_kaddr = NULL;
/* Memory manager related */

View File

@@ -2119,6 +2119,8 @@ static int amdgpu_discovery_set_common_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 5, 3):
case IP_VERSION(11, 5, 4):
case IP_VERSION(11, 5, 6):
case IP_VERSION(11, 7, 0):
case IP_VERSION(11, 7, 1):
amdgpu_device_ip_block_add(adev, &soc21_common_ip_block);
break;
case IP_VERSION(12, 0, 0):
@@ -2180,6 +2182,8 @@ static int amdgpu_discovery_set_gmc_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 5, 3):
case IP_VERSION(11, 5, 4):
case IP_VERSION(11, 5, 6):
case IP_VERSION(11, 7, 0):
case IP_VERSION(11, 7, 1):
amdgpu_device_ip_block_add(adev, &gmc_v11_0_ip_block);
break;
case IP_VERSION(12, 0, 0):
@@ -2506,6 +2510,8 @@ static int amdgpu_discovery_set_gc_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 5, 3):
case IP_VERSION(11, 5, 4):
case IP_VERSION(11, 5, 6):
case IP_VERSION(11, 7, 0):
case IP_VERSION(11, 7, 1):
amdgpu_device_ip_block_add(adev, &gfx_v11_0_ip_block);
break;
case IP_VERSION(12, 0, 0):
@@ -2719,6 +2725,8 @@ static int amdgpu_discovery_set_mes_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 5, 3):
case IP_VERSION(11, 5, 4):
case IP_VERSION(11, 5, 6):
case IP_VERSION(11, 7, 0):
case IP_VERSION(11, 7, 1):
amdgpu_device_ip_block_add(adev, &mes_v11_0_ip_block);
adev->enable_mes = true;
adev->enable_mes_kiq = true;
@@ -3127,6 +3135,8 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 5, 3):
case IP_VERSION(11, 5, 4):
case IP_VERSION(11, 5, 6):
case IP_VERSION(11, 7, 0):
case IP_VERSION(11, 7, 1):
adev->family = AMDGPU_FAMILY_GC_11_5_0;
break;
case IP_VERSION(12, 0, 0):
@@ -3156,6 +3166,8 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 5, 3):
case IP_VERSION(11, 5, 4):
case IP_VERSION(11, 5, 6):
case IP_VERSION(11, 7, 0):
case IP_VERSION(11, 7, 1):
adev->flags |= AMD_IS_APU;
break;
default:

View File

@@ -3196,6 +3196,14 @@ static void __exit amdgpu_exit(void)
amdgpu_sync_fini();
mmu_notifier_synchronize();
amdgpu_xcp_drv_release();
/*
* Flush outstanding call_rcu() callbacks before the
* module text is freed. Otherwise a grace period elapsing after
* unload invokes a callback in already-freed module memory and
* faults in rcu_do_batch().
*/
rcu_barrier();
}
module_init(amdgpu_init);

View File

@@ -535,6 +535,7 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data,
bo = gem_to_amdgpu_bo(gobj);
bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
bo->parent = amdgpu_bo_ref(fpriv->vm.root.bo);
r = amdgpu_ttm_tt_set_userptr(&bo->tbo, args->addr, args->flags);
if (r)
goto release_object;

View File

@@ -977,6 +977,8 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev)
case IP_VERSION(11, 5, 3):
case IP_VERSION(11, 5, 4):
case IP_VERSION(11, 5, 6):
case IP_VERSION(11, 7, 0):
case IP_VERSION(11, 7, 1):
/* Don't enable it by default yet.
*/
if (amdgpu_tmz < 1) {

View File

@@ -67,7 +67,6 @@ static bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni,
{
struct amdgpu_bo *bo = container_of(mni, struct amdgpu_bo, notifier);
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
struct amdgpu_bo *vm_root = bo->vm_bo->vm->root.bo;
long r;
if (!mmu_notifier_range_blockable(range))
@@ -78,7 +77,7 @@ static bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni,
mmu_interval_set_seq(mni, cur_seq);
amdgpu_vm_bo_invalidate(bo, false);
r = dma_resv_wait_timeout(vm_root->tbo.base.resv,
r = dma_resv_wait_timeout(bo->parent->tbo.base.resv,
DMA_RESV_USAGE_BOOKKEEP, false,
MAX_SCHEDULE_TIMEOUT);
mutex_unlock(&adev->notifier_lock);

View File

@@ -302,12 +302,14 @@ struct mes_suspend_gang_input {
uint64_t gang_context_addr;
uint64_t suspend_fence_addr;
uint32_t suspend_fence_value;
uint32_t doorbell_offset;
};
struct mes_resume_gang_input {
uint32_t xcc_id;
bool resume_all_gangs;
uint64_t gang_context_addr;
uint32_t doorbell_offset;
};
struct mes_reset_queue_input {

View File

@@ -208,9 +208,10 @@ static int amdgpu_ttm_map_buffer(struct amdgpu_ttm_buffer_entity *entity,
void *cpu_addr;
uint64_t flags;
int r;
const u64 GTT_MAX_PAGES = (AMDGPU_GTT_MAX_TRANSFER_SIZE >> PAGE_SHIFT);
BUG_ON(adev->mman.buffer_funcs->copy_max_bytes <
AMDGPU_GTT_MAX_TRANSFER_SIZE * 8);
GTT_MAX_PAGES * AMDGPU_GPU_PAGES_IN_CPU_PAGE * 8);
if (WARN_ON(mem->mem_type == AMDGPU_PL_PREEMPT))
return -EINVAL;
@@ -230,7 +231,7 @@ static int amdgpu_ttm_map_buffer(struct amdgpu_ttm_buffer_entity *entity,
offset = mm_cur->start & ~PAGE_MASK;
num_pages = PFN_UP(*size + offset);
num_pages = min_t(uint32_t, num_pages, AMDGPU_GTT_MAX_TRANSFER_SIZE);
num_pages = min_t(uint32_t, num_pages, GTT_MAX_PAGES);
*size = min(*size, (uint64_t)num_pages * PAGE_SIZE - offset);
@@ -2033,6 +2034,7 @@ static int amdgpu_ttm_buffer_entity_init(struct amdgpu_gtt_mgr *mgr,
u32 num_gart_windows)
{
int i, r, num_pages;
const u64 GTT_MAX_PAGES = (AMDGPU_GTT_MAX_TRANSFER_SIZE >> PAGE_SHIFT);
r = drm_sched_entity_init(&entity->base, prio, scheds, num_schedulers, NULL);
if (r)
@@ -2045,7 +2047,7 @@ static int amdgpu_ttm_buffer_entity_init(struct amdgpu_gtt_mgr *mgr,
if (num_gart_windows == 0)
return 0;
num_pages = num_gart_windows * AMDGPU_GTT_MAX_TRANSFER_SIZE;
num_pages = num_gart_windows * GTT_MAX_PAGES;
r = amdgpu_gtt_mgr_alloc_entries(mgr, &entity->gart_node, num_pages,
DRM_MM_INSERT_BEST);
if (r) {
@@ -2056,7 +2058,7 @@ static int amdgpu_ttm_buffer_entity_init(struct amdgpu_gtt_mgr *mgr,
for (i = 0; i < num_gart_windows; i++) {
entity->gart_window_offs[i] =
amdgpu_gtt_node_to_byte_offset(&entity->gart_node) +
i * AMDGPU_GTT_MAX_TRANSFER_SIZE * PAGE_SIZE;
i * GTT_MAX_PAGES * PAGE_SIZE;
}
return 0;
@@ -2118,18 +2120,23 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
/* Change the size here instead of the init above so only lpfn is affected */
amdgpu_ttm_disable_buffer_funcs(adev);
#ifdef CONFIG_64BIT
#ifdef CONFIG_X86
if (adev->gmc.xgmi.connected_to_cpu)
adev->mman.aper_base_kaddr = ioremap_cache(adev->gmc.aper_base,
adev->gmc.visible_vram_size);
else if (adev->gmc.is_app_apu)
if (adev->gmc.xgmi.connected_to_cpu) {
void *kaddr = devm_memremap(adev->dev, adev->gmc.aper_base,
adev->gmc.visible_vram_size,
MEMREMAP_WB);
if (IS_ERR(kaddr))
return PTR_ERR(kaddr);
adev->mman.aper_base_kaddr = (__force void __iomem *)kaddr;
} else if (adev->gmc.is_app_apu) {
DRM_DEBUG_DRIVER(
"No need to ioremap when real vram size is 0\n");
else
#endif
adev->mman.aper_base_kaddr = ioremap_wc(adev->gmc.aper_base,
adev->gmc.visible_vram_size);
} else {
adev->mman.aper_base_kaddr = devm_ioremap_wc(adev->dev,
adev->gmc.aper_base,
adev->gmc.visible_vram_size);
if (!adev->mman.aper_base_kaddr)
return -ENOMEM;
}
#endif
amdgpu_ttm_init_vram_resv_regions(adev);
@@ -2246,8 +2253,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
*/
void amdgpu_ttm_fini(struct amdgpu_device *adev)
{
int idx;
if (!adev->mman.initialized)
return;
@@ -2270,14 +2275,7 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_FW_VRAM_USAGE);
amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_DRV_VRAM_USAGE);
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
if (adev->mman.aper_base_kaddr)
iounmap(adev->mman.aper_base_kaddr);
adev->mman.aper_base_kaddr = NULL;
drm_dev_exit(idx);
}
adev->mman.aper_base_kaddr = NULL;
if (!adev->gmc.is_app_apu)
amdgpu_vram_mgr_fini(adev);

View File

@@ -39,7 +39,7 @@
#define AMDGPU_PL_MMIO_REMAP (TTM_PL_PRIV + 5)
#define __AMDGPU_PL_NUM (TTM_PL_PRIV + 6)
#define AMDGPU_GTT_MAX_TRANSFER_SIZE 1024
#define AMDGPU_GTT_MAX_TRANSFER_SIZE (1ULL << 22)
extern const struct attribute_group amdgpu_vram_mgr_attr_group;
extern const struct attribute_group amdgpu_gtt_mgr_attr_group;

View File

@@ -680,8 +680,8 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
/* Update VM owner at userq submit-time for page-fault attribution. */
amdgpu_vm_set_task_info(&fpriv->vm);
r = xa_err(xa_store_irq(&adev->userq_doorbell_xa, index, queue,
GFP_KERNEL));
r = xa_insert_irq(&adev->userq_doorbell_xa, index, queue,
GFP_KERNEL);
if (r)
goto clean_mqd;

View File

@@ -655,6 +655,14 @@ static int amdgpu_uvd_cs_msg_decode(struct amdgpu_device *adev, uint32_t *msg,
unsigned int image_size, tmp, min_dpb_size, num_dpb_buffer;
unsigned int min_ctx_size = ~0;
/* Reject invalid dimensions to prevent division by zero */
if (width < 16 || height < 16) {
dev_WARN_ONCE(adev->dev, 1,
"Invalid UVD decoding dimensions (%dx%d)!\n",
width, height);
return -EINVAL;
}
image_size = width * height;
image_size += image_size / 2;
image_size = ALIGN(image_size, 1024);

View File

@@ -877,9 +877,20 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p,
goto out;
}
*size = amdgpu_ib_get_value(ib, idx + 8) *
amdgpu_ib_get_value(ib, idx + 10) *
8 * 3 / 2;
uint32_t width, height;
width = amdgpu_ib_get_value(ib, idx + 8);
height = amdgpu_ib_get_value(ib, idx + 10);
if (width == 0 || height == 0 ||
width > 4096 || height > 2304) {
DRM_ERROR("invalid VCE image size: %ux%u\n",
width, height);
r = -EINVAL;
goto out;
}
*size = width * height * 8 * 3 / 2;
break;
case 0x04000001: /* config extension */

View File

@@ -142,7 +142,7 @@ static void amdgpu_vm_assert_locked(struct amdgpu_vm *vm)
static void amdgpu_vm_bo_status_init(struct amdgpu_vm_bo_status *lists)
{
INIT_LIST_HEAD(&lists->evicted);
INIT_LIST_HEAD(&lists->moved);
INIT_LIST_HEAD(&lists->needs_update);
INIT_LIST_HEAD(&lists->idle);
}
@@ -211,14 +211,14 @@ static void amdgpu_vm_bo_evicted(struct amdgpu_vm_bo_base *vm_bo)
amdgpu_vm_bo_unlock_lists(vm_bo);
}
/**
* amdgpu_vm_bo_moved - vm_bo is moved
* amdgpu_vm_bo_needs_update - vm_bo needs pagetable update
*
* @vm_bo: vm_bo which is moved
* @vm_bo: vm_bo which is out of date
*
* State for vm_bo objects meaning the underlying BO was moved but the new
* location not yet reflected in the page tables.
* State for vm_bo objects meaning the underlying BO had mapping changes (move, PRT bind/unbind)
* but the new location is not yet reflected in the page tables.
*/
static void amdgpu_vm_bo_moved(struct amdgpu_vm_bo_base *vm_bo)
static void amdgpu_vm_bo_needs_update(struct amdgpu_vm_bo_base *vm_bo)
{
struct amdgpu_vm_bo_status *lists;
struct amdgpu_bo *bo = vm_bo->bo;
@@ -232,8 +232,7 @@ static void amdgpu_vm_bo_moved(struct amdgpu_vm_bo_base *vm_bo)
vm_bo->moved = false;
list_move(&vm_bo->vm_status, &lists->idle);
} else {
vm_bo->moved = true;
list_move(&vm_bo->vm_status, &lists->moved);
list_move(&vm_bo->vm_status, &lists->needs_update);
}
amdgpu_vm_bo_unlock_lists(vm_bo);
}
@@ -274,14 +273,14 @@ static void amdgpu_vm_bo_reset_state_machine(struct amdgpu_vm *vm)
*/
amdgpu_vm_assert_locked(vm);
list_for_each_entry_safe(vm_bo, tmp, &vm->kernel.idle, vm_status)
amdgpu_vm_bo_moved(vm_bo);
amdgpu_vm_bo_needs_update(vm_bo);
list_for_each_entry_safe(vm_bo, tmp, &vm->always_valid.idle, vm_status)
amdgpu_vm_bo_moved(vm_bo);
amdgpu_vm_bo_needs_update(vm_bo);
spin_lock(&vm->individual_lock);
list_for_each_entry_safe(vm_bo, tmp, &vm->individual.idle, vm_status) {
vm_bo->moved = true;
list_move(&vm_bo->vm_status, &vm->individual.moved);
list_move(&vm_bo->vm_status, &vm->individual.needs_update);
}
spin_unlock(&vm->individual_lock);
}
@@ -436,7 +435,7 @@ void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base,
*/
if (bo->preferred_domains &
amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type))
amdgpu_vm_bo_moved(base);
amdgpu_vm_bo_needs_update(base);
else
amdgpu_vm_bo_evicted(base);
}
@@ -608,7 +607,8 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
return r;
vm->update_funcs->map_table(to_amdgpu_bo_vm(bo_base->bo));
amdgpu_vm_bo_moved(bo_base);
bo_base->moved = true;
amdgpu_vm_bo_needs_update(bo_base);
}
/*
@@ -625,7 +625,8 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
if (r)
return r;
amdgpu_vm_bo_moved(bo_base);
bo_base->moved = true;
amdgpu_vm_bo_needs_update(bo_base);
}
if (!ticket)
@@ -645,7 +646,8 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
if (r)
return r;
amdgpu_vm_bo_moved(bo_base);
bo_base->moved = true;
amdgpu_vm_bo_needs_update(bo_base);
/* It's a bit inefficient to always jump back to the start, but
* we would need to re-structure the KFD for properly fixing
@@ -979,7 +981,7 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
amdgpu_vm_assert_locked(vm);
if (list_empty(&vm->kernel.moved))
if (list_empty(&vm->kernel.needs_update))
return 0;
if (!drm_dev_enter(adev_to_drm(adev), &idx))
@@ -995,7 +997,7 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
if (r)
goto error;
list_for_each_entry(entry, &vm->kernel.moved, vm_status) {
list_for_each_entry(entry, &vm->kernel.needs_update, vm_status) {
/* vm_flush_needed after updating moved PDEs */
flush_tlb_needed |= entry->moved;
@@ -1011,7 +1013,8 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
if (flush_tlb_needed)
atomic64_inc(&vm->tlb_seq);
list_for_each_entry_safe(entry, tmp, &vm->kernel.moved, vm_status)
list_for_each_entry_safe(entry, tmp, &vm->kernel.needs_update,
vm_status)
amdgpu_vm_bo_idle(entry);
error:
@@ -1615,7 +1618,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
bool clear, unlock;
int r;
list_for_each_entry_safe(bo_va, tmp, &vm->always_valid.moved,
list_for_each_entry_safe(bo_va, tmp, &vm->always_valid.needs_update,
base.vm_status) {
/* Per VM BOs never need to bo cleared in the page tables */
r = amdgpu_vm_bo_update(adev, bo_va, false);
@@ -1624,8 +1627,8 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
}
spin_lock(&vm->individual_lock);
while (!list_empty(&vm->individual.moved)) {
bo_va = list_first_entry(&vm->individual.moved,
while (!list_empty(&vm->individual.needs_update)) {
bo_va = list_first_entry(&vm->individual.needs_update,
typeof(*bo_va), base.vm_status);
bo = bo_va->base.bo;
resv = bo->tbo.base.resv;
@@ -1786,7 +1789,7 @@ static void amdgpu_vm_bo_insert_map(struct amdgpu_device *adev,
amdgpu_vm_prt_get(adev);
if (amdgpu_vm_is_bo_always_valid(vm, bo) && !bo_va->base.moved)
amdgpu_vm_bo_moved(&bo_va->base);
amdgpu_vm_bo_needs_update(&bo_va->base);
trace_amdgpu_vm_bo_map(bo_va, mapping);
}
@@ -2095,7 +2098,7 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev,
if (amdgpu_vm_is_bo_always_valid(vm, bo) &&
!before->bo_va->base.moved)
amdgpu_vm_bo_moved(&before->bo_va->base);
amdgpu_vm_bo_needs_update(&before->bo_va->base);
} else {
kfree(before);
}
@@ -2110,7 +2113,7 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev,
if (amdgpu_vm_is_bo_always_valid(vm, bo) &&
!after->bo_va->base.moved)
amdgpu_vm_bo_moved(&after->bo_va->base);
amdgpu_vm_bo_needs_update(&after->bo_va->base);
} else {
kfree(after);
}
@@ -2284,7 +2287,8 @@ void amdgpu_vm_bo_invalidate(struct amdgpu_bo *bo, bool evicted)
if (bo_base->moved)
continue;
amdgpu_vm_bo_moved(bo_base);
bo_base->moved = true;
amdgpu_vm_bo_needs_update(bo_base);
}
}
@@ -3098,7 +3102,7 @@ static void amdgpu_debugfs_vm_bo_status_info(struct seq_file *m,
id = 0;
seq_puts(m, "\tMoved BOs:\n");
list_for_each_entry(base, &lists->moved, vm_status) {
list_for_each_entry(base, &lists->needs_update, vm_status) {
if (!base->bo)
continue;
@@ -3107,7 +3111,7 @@ static void amdgpu_debugfs_vm_bo_status_info(struct seq_file *m,
id = 0;
seq_puts(m, "\tIdle BOs:\n");
list_for_each_entry(base, &lists->moved, vm_status) {
list_for_each_entry(base, &lists->needs_update, vm_status) {
if (!base->bo)
continue;

View File

@@ -212,7 +212,8 @@ struct amdgpu_vm_bo_base {
* protected by vm BO being reserved */
bool shared;
/* protected by the BO being reserved */
/* if the BO was moved and all mappings are invalid
* protected by the BO being reserved */
bool moved;
};
@@ -220,14 +221,14 @@ struct amdgpu_vm_bo_base {
* The following status lists contain amdgpu_vm_bo_base objects for
* either PD/PTs, per VM BOs or BOs with individual resv object.
*
* The state transits are: evicted -> moved -> idle
* The state transits are: evicted -> needs_update -> idle
*/
struct amdgpu_vm_bo_status {
/* BOs evicted which need to move into place again */
struct list_head evicted;
/* BOs which moved but new location hasn't been updated in the PDs/PTs */
struct list_head moved;
/* BOs whose mappings changed but PDs/PTs haven't been updated */
struct list_head needs_update;
/* BOs done with the state machine and need no further action */
struct list_head idle;

View File

@@ -4022,7 +4022,7 @@ static void gfx_v10_0_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
WAIT_REG_MEM_ENGINE(eng_sel)));
if (mem_space)
BUG_ON(addr0 & 0x3); /* Dword align */
WARN_ON(addr0 & 0x3); /* Dword align */
amdgpu_ring_write(ring, addr0);
amdgpu_ring_write(ring, addr1);
amdgpu_ring_write(ring, ref);
@@ -8658,7 +8658,7 @@ static void gfx_v10_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
}
amdgpu_ring_write(ring, header);
BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -8693,7 +8693,7 @@ static void gfx_v10_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
}
amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -8726,9 +8726,9 @@ static void gfx_v10_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
* aligned if only send 32bit data low (discard data high)
*/
if (write64bit)
BUG_ON(addr & 0x7);
WARN_ON(addr & 0x7);
else
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -8776,9 +8776,6 @@ static void gfx_v10_0_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
{
struct amdgpu_device *adev = ring->adev;
/* we only allocate 32bit for each seq wb address */
BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
/* write fence seq to the "addr" */
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |

View File

@@ -133,6 +133,14 @@ MODULE_FIRMWARE("amdgpu/gc_11_5_6_pfp.bin");
MODULE_FIRMWARE("amdgpu/gc_11_5_6_me.bin");
MODULE_FIRMWARE("amdgpu/gc_11_5_6_mec.bin");
MODULE_FIRMWARE("amdgpu/gc_11_5_6_rlc.bin");
MODULE_FIRMWARE("amdgpu/gc_11_7_0_pfp.bin");
MODULE_FIRMWARE("amdgpu/gc_11_7_0_me.bin");
MODULE_FIRMWARE("amdgpu/gc_11_7_0_mec.bin");
MODULE_FIRMWARE("amdgpu/gc_11_7_0_rlc.bin");
MODULE_FIRMWARE("amdgpu/gc_11_7_1_pfp.bin");
MODULE_FIRMWARE("amdgpu/gc_11_7_1_me.bin");
MODULE_FIRMWARE("amdgpu/gc_11_7_1_mec.bin");
MODULE_FIRMWARE("amdgpu/gc_11_7_1_rlc.bin");
static const struct amdgpu_hwip_reg_entry gc_reg_list_11_0[] = {
SOC15_REG_ENTRY_STR(GC, 0, regGRBM_STATUS),
@@ -546,7 +554,7 @@ static void gfx_v11_0_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
WAIT_REG_MEM_ENGINE(eng_sel)));
if (mem_space)
BUG_ON(addr0 & 0x3); /* Dword align */
WARN_ON(addr0 & 0x3); /* Dword align */
amdgpu_ring_write(ring, addr0);
amdgpu_ring_write(ring, addr1);
amdgpu_ring_write(ring, ref);
@@ -1128,6 +1136,8 @@ static int gfx_v11_0_gpu_early_init(struct amdgpu_device *adev)
case IP_VERSION(11, 5, 3):
case IP_VERSION(11, 5, 4):
case IP_VERSION(11, 5, 6):
case IP_VERSION(11, 7, 0):
case IP_VERSION(11, 7, 1):
adev->gfx.config.max_hw_contexts = 8;
adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
@@ -1612,6 +1622,8 @@ static int gfx_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
case IP_VERSION(11, 5, 3):
case IP_VERSION(11, 5, 4):
case IP_VERSION(11, 5, 6):
case IP_VERSION(11, 7, 0):
case IP_VERSION(11, 7, 1):
adev->gfx.me.num_me = 1;
adev->gfx.me.num_pipe_per_me = 1;
adev->gfx.me.num_queue_per_pipe = 2;
@@ -3085,7 +3097,9 @@ static int gfx_v11_0_wait_for_rlc_autoload_complete(struct amdgpu_device *adev)
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 2) ||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 3) ||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 4) ||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 6))
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 5, 6) ||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 7, 0) ||
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(11, 7, 1))
bootload_status = RREG32_SOC15(GC, 0,
regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1);
else
@@ -5758,6 +5772,8 @@ static void gfx_v11_cntl_power_gating(struct amdgpu_device *adev, bool enable)
case IP_VERSION(11, 5, 3):
case IP_VERSION(11, 5, 4):
case IP_VERSION(11, 5, 6):
case IP_VERSION(11, 7, 0):
case IP_VERSION(11, 7, 1):
WREG32_SOC15(GC, 0, regRLC_PG_DELAY_3, RLC_PG_DELAY_3_DEFAULT_GC_11_0_1);
break;
default:
@@ -5798,6 +5814,8 @@ static int gfx_v11_0_set_powergating_state(struct amdgpu_ip_block *ip_block,
case IP_VERSION(11, 5, 3):
case IP_VERSION(11, 5, 4):
case IP_VERSION(11, 5, 6):
case IP_VERSION(11, 7, 0):
case IP_VERSION(11, 7, 1):
if (!enable)
amdgpu_gfx_off_ctrl(adev, false);
@@ -5834,6 +5852,8 @@ static int gfx_v11_0_set_clockgating_state(struct amdgpu_ip_block *ip_block,
case IP_VERSION(11, 5, 3):
case IP_VERSION(11, 5, 4):
case IP_VERSION(11, 5, 6):
case IP_VERSION(11, 7, 0):
case IP_VERSION(11, 7, 1):
gfx_v11_0_update_gfx_clock_gating(adev,
state == AMD_CG_STATE_GATE);
break;
@@ -5997,7 +6017,7 @@ static void gfx_v11_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
}
amdgpu_ring_write(ring, header);
BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -6032,7 +6052,7 @@ static void gfx_v11_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
}
amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -6065,9 +6085,9 @@ static void gfx_v11_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
* aligned if only send 32bit data low (discard data high)
*/
if (write64bit)
BUG_ON(addr & 0x7);
WARN_ON(addr & 0x7);
else
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -6121,9 +6141,6 @@ static void gfx_v11_0_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
{
struct amdgpu_device *adev = ring->adev;
/* we only allocate 32bit for each seq wb address */
BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
/* write fence seq to the "addr" */
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
@@ -6510,25 +6527,33 @@ static int gfx_v11_0_eop_irq(struct amdgpu_device *adev,
struct amdgpu_iv_entry *entry)
{
u32 doorbell_offset = entry->src_data[0];
u8 me_id, pipe_id, queue_id;
struct amdgpu_ring *ring;
int i;
DRM_DEBUG("IH: CP EOP\n");
if (adev->enable_mes && doorbell_offset) {
amdgpu_userq_process_fence_irq(adev, doorbell_offset);
} else {
me_id = (entry->ring_id & 0x0c) >> 2;
pipe_id = (entry->ring_id & 0x03) >> 0;
queue_id = (entry->ring_id & 0x70) >> 4;
if (!adev->gfx.disable_kq) {
u8 me_id = (entry->ring_id & 0x0c) >> 2;
u8 pipe_id = (entry->ring_id & 0x03) >> 0;
u8 queue_id = (entry->ring_id & 0x70) >> 4;
struct amdgpu_ring *ring;
int i;
switch (me_id) {
case 0:
if (pipe_id == 0)
amdgpu_fence_process(&adev->gfx.gfx_ring[0]);
else
amdgpu_fence_process(&adev->gfx.gfx_ring[1]);
/*
* MES splits gfx HQDs per (me,pipe): KGQ owns queue=0,
* userq gfx owns queue>=1 (see amdgpu_mes_get_hqd_mask).
* Require a strict (me,pipe,queue) match so userq gfx
* EOPs fall through to amdgpu_userq_process_fence_irq().
*/
for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
ring = &adev->gfx.gfx_ring[i];
if ((ring->me == me_id) &&
(ring->pipe == pipe_id) &&
(ring->queue == queue_id)) {
amdgpu_fence_process(ring);
return 0;
}
}
break;
case 1:
case 2:
@@ -6540,13 +6565,20 @@ static int gfx_v11_0_eop_irq(struct amdgpu_device *adev,
*/
if ((ring->me == me_id) &&
(ring->pipe == pipe_id) &&
(ring->queue == queue_id))
(ring->queue == queue_id)) {
amdgpu_fence_process(ring);
return 0;
}
}
break;
default:
break;
}
}
if (adev->enable_mes && doorbell_offset)
amdgpu_userq_process_fence_irq(adev, doorbell_offset);
return 0;
}

View File

@@ -440,7 +440,7 @@ static void gfx_v12_0_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
WAIT_REG_MEM_ENGINE(eng_sel)));
if (mem_space)
BUG_ON(addr0 & 0x3); /* Dword align */
WARN_ON(addr0 & 0x3); /* Dword align */
amdgpu_ring_write(ring, addr0);
amdgpu_ring_write(ring, addr1);
amdgpu_ring_write(ring, ref);
@@ -3519,10 +3519,19 @@ static int gfx_v12_0_cp_resume(struct amdgpu_device *adev)
gfx_v12_0_cp_gfx_enable(adev, true);
}
if (adev->enable_mes_kiq && adev->mes.kiq_hw_init)
if (adev->enable_mes_kiq && adev->mes.kiq_hw_init) {
r = amdgpu_mes_kiq_hw_init(adev, 0);
else
/*
* With MES, GFX KIQ ring is owned by the MES and is never
* initialized/used directly by the driver, so it must
* not be left flagged as ready. mes_v12_0_hw_init() clears
* but clear here if MES init fails
*/
if (r)
adev->gfx.kiq[0].ring.sched.ready = false;
} else {
r = gfx_v12_0_kiq_resume(adev);
}
if (r)
return r;
@@ -4493,7 +4502,7 @@ static void gfx_v12_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
control |= ib->length_dw | (vmid << 24);
amdgpu_ring_write(ring, header);
BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -4512,7 +4521,7 @@ static void gfx_v12_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
u32 control = INDIRECT_BUFFER_VALID | ib->length_dw | (vmid << 24);
amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -4543,9 +4552,9 @@ static void gfx_v12_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
* aligned if only send 32bit data low (discard data high)
*/
if (write64bit)
BUG_ON(addr & 0x7);
WARN_ON(addr & 0x7);
else
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -4593,9 +4602,6 @@ static void gfx_v12_0_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
{
struct amdgpu_device *adev = ring->adev;
/* we only allocate 32bit for each seq wb address */
BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
/* write fence seq to the "addr" */
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
@@ -4838,25 +4844,33 @@ static int gfx_v12_0_eop_irq(struct amdgpu_device *adev,
struct amdgpu_iv_entry *entry)
{
u32 doorbell_offset = entry->src_data[0];
u8 me_id, pipe_id, queue_id;
struct amdgpu_ring *ring;
int i;
DRM_DEBUG("IH: CP EOP\n");
if (adev->enable_mes && doorbell_offset) {
amdgpu_userq_process_fence_irq(adev, doorbell_offset);
} else {
me_id = (entry->ring_id & 0x0c) >> 2;
pipe_id = (entry->ring_id & 0x03) >> 0;
queue_id = (entry->ring_id & 0x70) >> 4;
if (!adev->gfx.disable_kq) {
u8 me_id = (entry->ring_id & 0x0c) >> 2;
u8 pipe_id = (entry->ring_id & 0x03) >> 0;
u8 queue_id = (entry->ring_id & 0x70) >> 4;
struct amdgpu_ring *ring;
int i;
switch (me_id) {
case 0:
if (pipe_id == 0)
amdgpu_fence_process(&adev->gfx.gfx_ring[0]);
else
amdgpu_fence_process(&adev->gfx.gfx_ring[1]);
/*
* MES splits gfx HQDs per (me,pipe): KGQ owns queue=0,
* userq gfx owns queue>=1 (see amdgpu_mes_get_hqd_mask).
* Require a strict (me,pipe,queue) match so userq gfx
* EOPs fall through to amdgpu_userq_process_fence_irq().
*/
for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
ring = &adev->gfx.gfx_ring[i];
if ((ring->me == me_id) &&
(ring->pipe == pipe_id) &&
(ring->queue == queue_id)) {
amdgpu_fence_process(ring);
return 0;
}
}
break;
case 1:
case 2:
@@ -4868,13 +4882,20 @@ static int gfx_v12_0_eop_irq(struct amdgpu_device *adev,
*/
if ((ring->me == me_id) &&
(ring->pipe == pipe_id) &&
(ring->queue == queue_id))
(ring->queue == queue_id)) {
amdgpu_fence_process(ring);
return 0;
}
}
break;
default:
break;
}
}
if (adev->enable_mes && doorbell_offset)
amdgpu_userq_process_fence_irq(adev, doorbell_offset);
return 0;
}

View File

@@ -248,7 +248,7 @@ static void gfx_v12_1_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
PACKET3_WAIT_REG_MEM__FUNCTION(3))); /* equal */
if (mem_space)
BUG_ON(addr0 & 0x3); /* Dword align */
WARN_ON(addr0 & 0x3); /* Dword align */
amdgpu_ring_write(ring, addr0);
amdgpu_ring_write(ring, addr1);
amdgpu_ring_write(ring, ref);
@@ -2547,10 +2547,19 @@ static int gfx_v12_1_xcc_cp_resume(struct amdgpu_device *adev, uint16_t xcc_mask
gfx_v12_1_xcc_cp_compute_enable(adev, true, xcc_id);
if (adev->enable_mes_kiq && adev->mes.kiq_hw_init)
if (adev->enable_mes_kiq && adev->mes.kiq_hw_init) {
r = amdgpu_mes_kiq_hw_init(adev, xcc_id);
else
/*
* With MES, GFX KIQ ring is owned by the MES and is never
* initialized/used directly by the driver, so it must
* not be left flagged as ready. mes_v12_0_hw_init() clears
* but clear here if MES init fails
*/
if (r)
adev->gfx.kiq[xcc_id].ring.sched.ready = false;
} else {
r = gfx_v12_1_xcc_kiq_resume(adev, xcc_id);
}
if (r)
return r;
@@ -3433,7 +3442,7 @@ static void gfx_v12_1_ring_emit_ib_compute(struct amdgpu_ring *ring,
}
amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -3466,9 +3475,9 @@ static void gfx_v12_1_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
* aligned if only send 32bit data low (discard data high)
*/
if (write64bit)
BUG_ON(addr & 0x7);
WARN_ON(addr & 0x7);
else
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -3515,9 +3524,6 @@ static void gfx_v12_1_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
{
struct amdgpu_device *adev = ring->adev;
/* we only allocate 32bit for each seq wb address */
BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
/* write fence seq to the "addr" */
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, (PACKET3_WRITE_DATA__DST_SEL(5) | PACKET3_WRITE_DATA__WR_CONFIRM(1)));

View File

@@ -6256,9 +6256,6 @@ static void gfx_v8_0_ring_emit_fence_compute(struct amdgpu_ring *ring,
static void gfx_v8_0_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
u64 seq, unsigned int flags)
{
/* we only allocate 32bit for each seq wb address */
BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
/* write fence seq to the "addr" */
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |

View File

@@ -1183,7 +1183,7 @@ static void gfx_v9_0_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
WAIT_REG_MEM_ENGINE(eng_sel)));
if (mem_space)
BUG_ON(addr0 & 0x3); /* Dword align */
WARN_ON(addr0 & 0x3); /* Dword align */
amdgpu_ring_write(ring, addr0);
amdgpu_ring_write(ring, addr1);
amdgpu_ring_write(ring, ref);
@@ -5474,7 +5474,7 @@ static void gfx_v9_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
}
amdgpu_ring_write(ring, header);
BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -5570,7 +5570,7 @@ static void gfx_v9_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
}
amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -5611,9 +5611,9 @@ static void gfx_v9_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
* aligned if only send 32bit data low (discard data high)
*/
if (write64bit)
BUG_ON(addr & 0x7);
WARN_ON(addr & 0x7);
else
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));

View File

@@ -405,7 +405,7 @@ static void gfx_v9_4_3_wait_reg_mem(struct amdgpu_ring *ring, int eng_sel,
WAIT_REG_MEM_ENGINE(eng_sel)));
if (mem_space)
BUG_ON(addr0 & 0x3); /* Dword align */
WARN_ON(addr0 & 0x3); /* Dword align */
amdgpu_ring_write(ring, addr0);
amdgpu_ring_write(ring, addr1);
amdgpu_ring_write(ring, ref);
@@ -2944,7 +2944,7 @@ static void gfx_v9_4_3_ring_emit_ib_compute(struct amdgpu_ring *ring,
}
amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -2978,9 +2978,9 @@ static void gfx_v9_4_3_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
* aligned if only send 32bit data low (discard data high)
*/
if (write64bit)
BUG_ON(addr & 0x7);
WARN_ON(addr & 0x7);
else
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -3040,9 +3040,6 @@ static void gfx_v9_4_3_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
{
struct amdgpu_device *adev = ring->adev;
/* we only allocate 32bit for each seq wb address */
BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
/* write fence seq to the "addr" */
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |

View File

@@ -606,6 +606,8 @@ static void gmc_v11_0_set_gfxhub_funcs(struct amdgpu_device *adev)
case IP_VERSION(11, 5, 3):
case IP_VERSION(11, 5, 4):
case IP_VERSION(11, 5, 6):
case IP_VERSION(11, 7, 0):
case IP_VERSION(11, 7, 1):
adev->gfxhub.funcs = &gfxhub_v11_5_0_funcs;
break;
default:
@@ -781,6 +783,8 @@ static int gmc_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
case IP_VERSION(11, 5, 3):
case IP_VERSION(11, 5, 4):
case IP_VERSION(11, 5, 6):
case IP_VERSION(11, 7, 0):
case IP_VERSION(11, 7, 1):
set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask);
set_bit(AMDGPU_MMHUB0(0), adev->vmhubs_mask);
/*

View File

@@ -43,6 +43,8 @@ MODULE_FIRMWARE("amdgpu/gc_11_5_2_imu.bin");
MODULE_FIRMWARE("amdgpu/gc_11_5_3_imu.bin");
MODULE_FIRMWARE("amdgpu/gc_11_5_4_imu.bin");
MODULE_FIRMWARE("amdgpu/gc_11_5_6_imu.bin");
MODULE_FIRMWARE("amdgpu/gc_11_7_0_imu.bin");
MODULE_FIRMWARE("amdgpu/gc_11_7_1_imu.bin");
static int imu_v11_0_init_microcode(struct amdgpu_device *adev)
{

View File

@@ -1010,7 +1010,7 @@ void jpeg_v4_0_3_dec_ring_nop(struct amdgpu_ring *ring, uint32_t count)
static bool jpeg_v4_0_3_is_idle(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
bool ret = false;
bool ret = true;
int i, j;
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {

View File

@@ -657,7 +657,7 @@ static void jpeg_v5_0_1_dec_ring_set_wptr(struct amdgpu_ring *ring)
static bool jpeg_v5_0_1_is_idle(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
bool ret = false;
bool ret = true;
int i, j;
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {

View File

@@ -60,6 +60,10 @@ MODULE_FIRMWARE("amdgpu/gc_11_5_4_mes_2.bin");
MODULE_FIRMWARE("amdgpu/gc_11_5_4_mes1.bin");
MODULE_FIRMWARE("amdgpu/gc_11_5_6_mes_2.bin");
MODULE_FIRMWARE("amdgpu/gc_11_5_6_mes1.bin");
MODULE_FIRMWARE("amdgpu/gc_11_7_0_mes_2.bin");
MODULE_FIRMWARE("amdgpu/gc_11_7_0_mes1.bin");
MODULE_FIRMWARE("amdgpu/gc_11_7_1_mes_2.bin");
MODULE_FIRMWARE("amdgpu/gc_11_7_1_mes1.bin");
static int mes_v11_0_hw_init(struct amdgpu_ip_block *ip_block);
static int mes_v11_0_hw_fini(struct amdgpu_ip_block *ip_block);
@@ -559,6 +563,7 @@ static int mes_v11_0_suspend_gang(struct amdgpu_mes *mes,
mes_suspend_gang_pkt.gang_context_addr = input->gang_context_addr;
mes_suspend_gang_pkt.suspend_fence_addr = input->suspend_fence_addr;
mes_suspend_gang_pkt.suspend_fence_value = input->suspend_fence_value;
mes_suspend_gang_pkt.doorbell_offset = input->doorbell_offset;
return mes_v11_0_submit_pkt_and_poll_completion(mes,
&mes_suspend_gang_pkt, sizeof(mes_suspend_gang_pkt),
@@ -578,6 +583,7 @@ static int mes_v11_0_resume_gang(struct amdgpu_mes *mes,
mes_resume_gang_pkt.resume_all_gangs = input->resume_all_gangs;
mes_resume_gang_pkt.gang_context_addr = input->gang_context_addr;
mes_resume_gang_pkt.doorbell_offset = input->doorbell_offset;
return mes_v11_0_submit_pkt_and_poll_completion(mes,
&mes_resume_gang_pkt, sizeof(mes_resume_gang_pkt),

View File

@@ -592,6 +592,7 @@ static int mes_v12_0_suspend_gang(struct amdgpu_mes *mes,
mes_suspend_gang_pkt.gang_context_addr = input->gang_context_addr;
mes_suspend_gang_pkt.suspend_fence_addr = input->suspend_fence_addr;
mes_suspend_gang_pkt.suspend_fence_value = input->suspend_fence_value;
mes_suspend_gang_pkt.doorbell_offset = input->doorbell_offset;
return mes_v12_0_submit_pkt_and_poll_completion(mes, AMDGPU_MES_SCHED_PIPE,
&mes_suspend_gang_pkt, sizeof(mes_suspend_gang_pkt),
@@ -611,6 +612,7 @@ static int mes_v12_0_resume_gang(struct amdgpu_mes *mes,
mes_resume_gang_pkt.resume_all_gangs = input->resume_all_gangs;
mes_resume_gang_pkt.gang_context_addr = input->gang_context_addr;
mes_resume_gang_pkt.doorbell_offset = input->doorbell_offset;
return mes_v12_0_submit_pkt_and_poll_completion(mes, AMDGPU_MES_SCHED_PIPE,
&mes_resume_gang_pkt, sizeof(mes_resume_gang_pkt),

View File

@@ -484,6 +484,7 @@ static int mes_v12_1_suspend_gang(struct amdgpu_mes *mes,
mes_suspend_gang_pkt.gang_context_addr = input->gang_context_addr;
mes_suspend_gang_pkt.suspend_fence_addr = input->suspend_fence_addr;
mes_suspend_gang_pkt.suspend_fence_value = input->suspend_fence_value;
mes_suspend_gang_pkt.doorbell_offset = input->doorbell_offset;
/* Suspend gang is handled by master MES */
return mes_v12_1_submit_pkt_and_poll_completion(mes, input->xcc_id, AMDGPU_MES_SCHED_PIPE,
@@ -504,6 +505,7 @@ static int mes_v12_1_resume_gang(struct amdgpu_mes *mes,
mes_resume_gang_pkt.resume_all_gangs = input->resume_all_gangs;
mes_resume_gang_pkt.gang_context_addr = input->gang_context_addr;
mes_resume_gang_pkt.doorbell_offset = input->doorbell_offset;
/* Resume gang is handled by master MES */
return mes_v12_1_submit_pkt_and_poll_completion(mes, input->xcc_id, AMDGPU_MES_SCHED_PIPE,

View File

@@ -33,6 +33,8 @@
MODULE_FIRMWARE("amdgpu/psp_15_0_0_toc.bin");
MODULE_FIRMWARE("amdgpu/psp_15_0_0_ta.bin");
MODULE_FIRMWARE("amdgpu/psp_15_0_9_toc.bin");
MODULE_FIRMWARE("amdgpu/psp_15_0_9_ta.bin");
static int psp_v15_0_0_init_microcode(struct psp_context *psp)
{

View File

@@ -457,7 +457,7 @@ static void sdma_v4_4_2_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64
/* write the fence */
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
/* zero in first two bits */
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -467,7 +467,7 @@ static void sdma_v4_4_2_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64
addr += 4;
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
/* zero in first two bits */
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(seq));

View File

@@ -527,7 +527,7 @@ static void sdma_v5_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3)); /* Ucached(UC) */
/* zero in first two bits */
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -538,7 +538,7 @@ static void sdma_v5_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3));
/* zero in first two bits */
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(seq));

View File

@@ -377,7 +377,7 @@ static void sdma_v5_2_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3)); /* Ucached(UC) */
/* zero in first two bits */
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -388,7 +388,7 @@ static void sdma_v5_2_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3));
/* zero in first two bits */
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(seq));

View File

@@ -361,7 +361,7 @@ static void sdma_v6_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
amdgpu_ring_write(ring, SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3)); /* Ucached(UC) */
/* zero in first two bits */
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -372,7 +372,7 @@ static void sdma_v6_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
amdgpu_ring_write(ring, SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3));
/* zero in first two bits */
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(seq));

View File

@@ -363,7 +363,7 @@ static void sdma_v7_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
amdgpu_ring_write(ring, SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3)); /* Ucached(UC) */
/* zero in first two bits */
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -374,7 +374,7 @@ static void sdma_v7_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
amdgpu_ring_write(ring, SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3));
/* zero in first two bits */
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(seq));

View File

@@ -331,7 +331,7 @@ static void sdma_v7_1_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
amdgpu_ring_write(ring, SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3)); /* Ucached(UC) */
/* zero in first two bits */
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -342,7 +342,7 @@ static void sdma_v7_1_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
amdgpu_ring_write(ring, SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3));
/* zero in first two bits */
BUG_ON(addr & 0x3);
WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(seq));

View File

@@ -838,6 +838,62 @@ static int soc21_common_early_init(struct amdgpu_ip_block *ip_block)
adev->pg_flags = 0;
adev->external_rev_id = adev->rev_id + 0xd0;
break;
case IP_VERSION(11, 7, 0):
adev->cg_flags = AMD_CG_SUPPORT_VCN_MGCG |
AMD_CG_SUPPORT_JPEG_MGCG |
AMD_CG_SUPPORT_GFX_CGCG |
AMD_CG_SUPPORT_GFX_CGLS |
AMD_CG_SUPPORT_GFX_MGCG |
AMD_CG_SUPPORT_GFX_FGCG |
AMD_CG_SUPPORT_REPEATER_FGCG |
AMD_CG_SUPPORT_GFX_PERF_CLK |
AMD_CG_SUPPORT_GFX_3D_CGCG |
AMD_CG_SUPPORT_GFX_3D_CGLS |
AMD_CG_SUPPORT_MC_MGCG |
AMD_CG_SUPPORT_MC_LS |
AMD_CG_SUPPORT_HDP_LS |
AMD_CG_SUPPORT_HDP_DS |
AMD_CG_SUPPORT_HDP_SD |
AMD_CG_SUPPORT_ATHUB_MGCG |
AMD_CG_SUPPORT_ATHUB_LS |
AMD_CG_SUPPORT_IH_CG |
AMD_CG_SUPPORT_BIF_MGCG |
AMD_CG_SUPPORT_BIF_LS;
adev->pg_flags = AMD_PG_SUPPORT_VCN_DPG |
AMD_PG_SUPPORT_VCN |
AMD_PG_SUPPORT_JPEG_DPG |
AMD_PG_SUPPORT_JPEG |
AMD_PG_SUPPORT_GFX_PG;
adev->external_rev_id = adev->rev_id + 0xF;
break;
case IP_VERSION(11, 7, 1):
adev->cg_flags = AMD_CG_SUPPORT_VCN_MGCG |
AMD_CG_SUPPORT_JPEG_MGCG |
AMD_CG_SUPPORT_GFX_CGCG |
AMD_CG_SUPPORT_GFX_CGLS |
AMD_CG_SUPPORT_GFX_MGCG |
AMD_CG_SUPPORT_GFX_FGCG |
AMD_CG_SUPPORT_REPEATER_FGCG |
AMD_CG_SUPPORT_GFX_PERF_CLK |
AMD_CG_SUPPORT_GFX_3D_CGCG |
AMD_CG_SUPPORT_GFX_3D_CGLS |
AMD_CG_SUPPORT_MC_MGCG |
AMD_CG_SUPPORT_MC_LS |
AMD_CG_SUPPORT_HDP_LS |
AMD_CG_SUPPORT_HDP_DS |
AMD_CG_SUPPORT_HDP_SD |
AMD_CG_SUPPORT_ATHUB_MGCG |
AMD_CG_SUPPORT_ATHUB_LS |
AMD_CG_SUPPORT_IH_CG |
AMD_CG_SUPPORT_BIF_MGCG |
AMD_CG_SUPPORT_BIF_LS;
adev->pg_flags = AMD_PG_SUPPORT_VCN_DPG |
AMD_PG_SUPPORT_VCN |
AMD_PG_SUPPORT_JPEG_DPG |
AMD_PG_SUPPORT_JPEG |
AMD_PG_SUPPORT_GFX_PG;
adev->external_rev_id = adev->rev_id + 0x40;
break;
default:
/* FIXME: not supported yet */
return -EINVAL;

View File

@@ -496,8 +496,36 @@ static int soc24_common_suspend(struct amdgpu_ip_block *ip_block)
return soc24_common_hw_fini(ip_block);
}
static bool soc24_need_reset_on_resume(struct amdgpu_device *adev)
{
u32 sol_reg1, sol_reg2;
/* Will reset for the following suspend abort cases.
* 1) Only reset dGPU side.
* 2) S3 suspend got aborted and TOS is active.
* As for dGPU suspend abort cases the SOL value
* will be kept as zero at this resume point.
*/
if (!(adev->flags & AMD_IS_APU) && adev->in_s3) {
sol_reg1 = RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_81);
msleep(100);
sol_reg2 = RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_81);
return (sol_reg1 != sol_reg2);
}
return false;
}
static int soc24_common_resume(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
if (soc24_need_reset_on_resume(adev)) {
dev_info(adev->dev, "S3 suspend aborted, resetting...");
soc24_asic_reset(adev);
}
return soc24_common_hw_init(ip_block);
}

View File

@@ -1927,14 +1927,17 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
#define RENCODE_IB_PARAM_SESSION_INIT 0x00000003
/* return the offset in ib if id is found, -1 otherwise */
static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start)
static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start, uint32_t *length)
{
int i;
uint32_t len;
for (i = start; (len = amdgpu_ib_get_value(ib, i)) >= 8; i += len / 4) {
if (amdgpu_ib_get_value(ib, i + 1) == id)
if (amdgpu_ib_get_value(ib, i + 1) == id) {
if (length)
*length = len;
return i;
}
}
return -1;
}
@@ -1944,14 +1947,14 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
struct amdgpu_ib *ib)
{
struct amdgpu_ring *ring = amdgpu_job_ring(job);
uint32_t val;
uint32_t val, len;
int idx = 0, sidx;
/* The first instance can decode anything */
if (!ring->me)
return 0;
while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) {
while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx, &len)) >= 0) {
val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
uint32_t valid_buf_flag = amdgpu_ib_get_value(ib, idx + 6);
@@ -1964,12 +1967,12 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
amdgpu_ib_get_value(ib, idx + 8);
return vcn_v4_0_dec_msg(p, job, msg_buffer_addr);
} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx);
sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx, NULL);
if (sidx >= 0 &&
amdgpu_ib_get_value(ib, sidx + 2) == RENCODE_ENCODE_STANDARD_AV1)
return vcn_v4_0_limit_sched(p, job);
}
idx += amdgpu_ib_get_value(ib, idx) / 4;
idx += len / 4;
}
return 0;
}

View File

@@ -1914,13 +1914,13 @@ static int criu_checkpoint_devices(struct kfd_process *p,
struct kfd_criu_device_bucket *device_buckets = NULL;
int ret = 0, i;
device_buckets = kvzalloc(num_devices * sizeof(*device_buckets), GFP_KERNEL);
device_buckets = kvcalloc(num_devices, sizeof(*device_buckets), GFP_KERNEL);
if (!device_buckets) {
ret = -ENOMEM;
goto exit;
}
device_priv = kvzalloc(num_devices * sizeof(*device_priv), GFP_KERNEL);
device_priv = kvcalloc(num_devices, sizeof(*device_priv), GFP_KERNEL);
if (!device_priv) {
ret = -ENOMEM;
goto exit;
@@ -2040,17 +2040,17 @@ static int criu_checkpoint_bos(struct kfd_process *p,
int ret = 0, pdd_index, bo_index = 0, id;
void *mem;
bo_buckets = kvzalloc(num_bos * sizeof(*bo_buckets), GFP_KERNEL);
bo_buckets = kvcalloc(num_bos, sizeof(*bo_buckets), GFP_KERNEL);
if (!bo_buckets)
return -ENOMEM;
bo_privs = kvzalloc(num_bos * sizeof(*bo_privs), GFP_KERNEL);
bo_privs = kvcalloc(num_bos, sizeof(*bo_privs), GFP_KERNEL);
if (!bo_privs) {
ret = -ENOMEM;
goto exit;
}
files = kvzalloc(num_bos * sizeof(struct file *), GFP_KERNEL);
files = kvcalloc(num_bos, sizeof(struct file *), GFP_KERNEL);
if (!files) {
ret = -ENOMEM;
goto exit;
@@ -2581,7 +2581,7 @@ static int criu_restore_bos(struct kfd_process *p,
if (!bo_buckets)
return -ENOMEM;
files = kvzalloc(args->num_bos * sizeof(struct file *), GFP_KERNEL);
files = kvcalloc(args->num_bos, sizeof(struct file *), GFP_KERNEL);
if (!files) {
ret = -ENOMEM;
goto exit;

View File

@@ -1715,6 +1715,8 @@ int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pc
case IP_VERSION(11, 5, 3):
case IP_VERSION(11, 5, 4):
case IP_VERSION(11, 5, 6):
case IP_VERSION(11, 7, 0):
case IP_VERSION(11, 7, 1):
/* Cacheline size not available in IP discovery for gc11.
* kfd_fill_gpu_cache_info_from_gfx_config to hard code it
*/

View File

@@ -169,6 +169,8 @@ static void kfd_device_info_set_event_interrupt_class(struct kfd_dev *kfd)
case IP_VERSION(11, 5, 3):
case IP_VERSION(11, 5, 4):
case IP_VERSION(11, 5, 6):
case IP_VERSION(11, 7, 0):
case IP_VERSION(11, 7, 1):
kfd->device_info.event_interrupt_class = &event_interrupt_class_v11;
break;
case IP_VERSION(12, 0, 0):
@@ -451,6 +453,14 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
gfx_target_version = 110504;
f2g = &gfx_v11_kfd2kgd;
break;
case IP_VERSION(11, 7, 0):
gfx_target_version = 110700;
f2g = &gfx_v11_kfd2kgd;
break;
case IP_VERSION(11, 7, 1):
gfx_target_version = 110701;
f2g = &gfx_v11_kfd2kgd;
break;
case IP_VERSION(12, 0, 0):
gfx_target_version = 120000;
f2g = &gfx_v12_kfd2kgd;

View File

@@ -128,7 +128,7 @@ svm_migrate_copy_memory_gart(struct amdgpu_device *adev, dma_addr_t *sys,
enum MIGRATION_COPY_DIR direction,
struct dma_fence **mfence)
{
const u64 GTT_MAX_PAGES = AMDGPU_GTT_MAX_TRANSFER_SIZE;
const u64 GTT_MAX_PAGES = (AMDGPU_GTT_MAX_TRANSFER_SIZE >> PAGE_SHIFT);
struct amdgpu_ring *ring;
struct amdgpu_ttm_buffer_entity *entity;
u64 gart_s, gart_d;

View File

@@ -127,6 +127,7 @@ struct mqd_manager {
struct mutex mqd_mutex;
struct kfd_node *dev;
uint32_t mqd_size;
uint32_t ctl_stack_size;
};
struct mqd_user_context_save_area_header {

View File

@@ -203,8 +203,8 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
* more than (EOP entry count - 1) so a queue size of 0x800 dwords
* is safe, giving a maximum field value of 0xA.
*/
m->cp_hqd_eop_control = min(0xA,
ffs(q->eop_ring_buffer_size / sizeof(unsigned int)) - 1 - 1);
m->cp_hqd_eop_control = q->eop_ring_buffer_size ? min(0xA,
ffs(q->eop_ring_buffer_size / sizeof(unsigned int)) - 1 - 1) : 0;
m->cp_hqd_eop_base_addr_lo =
lower_32_bits(q->eop_ring_buffer_address >> 8);
m->cp_hqd_eop_base_addr_hi =

View File

@@ -241,8 +241,8 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
* more than (EOP entry count - 1) so a queue size of 0x800 dwords
* is safe, giving a maximum field value of 0xA.
*/
m->cp_hqd_eop_control = min(0xA,
ffs(q->eop_ring_buffer_size / sizeof(unsigned int)) - 1 - 1);
m->cp_hqd_eop_control = q->eop_ring_buffer_size ? min(0xA,
ffs(q->eop_ring_buffer_size / sizeof(unsigned int)) - 1 - 1) : 0;
m->cp_hqd_eop_base_addr_lo =
lower_32_bits(q->eop_ring_buffer_address >> 8);
m->cp_hqd_eop_base_addr_hi =

View File

@@ -216,8 +216,8 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
* more than (EOP entry count - 1) so a queue size of 0x800 dwords
* is safe, giving a maximum field value of 0xA.
*/
m->cp_hqd_eop_control = min(0xA,
ffs(q->eop_ring_buffer_size / sizeof(unsigned int)) - 1 - 1);
m->cp_hqd_eop_control = q->eop_ring_buffer_size ? min(0xA,
ffs(q->eop_ring_buffer_size / sizeof(unsigned int)) - 1 - 1) : 0;
m->cp_hqd_eop_base_addr_lo =
lower_32_bits(q->eop_ring_buffer_address >> 8);
m->cp_hqd_eop_base_addr_hi =

View File

@@ -294,8 +294,8 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
* more than (EOP entry count - 1) so a queue size of 0x800 dwords
* is safe, giving a maximum field value of 0xA.
*/
m->cp_hqd_eop_control = min(0xA,
ffs(q->eop_ring_buffer_size / sizeof(unsigned int)) - 1 - 1);
m->cp_hqd_eop_control = q->eop_ring_buffer_size ? min(0xA,
ffs(q->eop_ring_buffer_size / sizeof(unsigned int)) - 1 - 1) : 0;
m->cp_hqd_eop_base_addr_lo =
lower_32_bits(q->eop_ring_buffer_address >> 8);
m->cp_hqd_eop_base_addr_hi =

View File

@@ -27,6 +27,7 @@
#include <linux/uaccess.h>
#include "kfd_priv.h"
#include "kfd_mqd_manager.h"
#include "kfd_topology.h"
#include "v9_structs.h"
#include "gc/gc_9_0_offset.h"
#include "gc/gc_9_0_sh_mask.h"
@@ -411,8 +412,11 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd,
static int get_checkpoint_info(struct mqd_manager *mm, void *mqd, u32 *ctl_stack_size)
{
struct v9_mqd *m = get_mqd(mqd);
u32 per_xcc_size;
if (check_mul_overflow(m->cp_hqd_cntl_stack_size, NUM_XCC(mm->dev->xcc_mask), ctl_stack_size))
per_xcc_size = min_t(u32, m->cp_hqd_cntl_stack_size, mm->ctl_stack_size);
if (check_mul_overflow(per_xcc_size, NUM_XCC(mm->dev->xcc_mask), ctl_stack_size))
return -EINVAL;
return 0;
@@ -421,13 +425,15 @@ static int get_checkpoint_info(struct mqd_manager *mm, void *mqd, u32 *ctl_stack
static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, void *ctl_stack_dst)
{
struct v9_mqd *m;
u32 ctl_stack_copy_size;
/* Control stack is located one page after MQD. */
void *ctl_stack = (void *)((uintptr_t)mqd + AMDGPU_GPU_PAGE_SIZE);
m = get_mqd(mqd);
ctl_stack_copy_size = min_t(u32, m->cp_hqd_cntl_stack_size, mm->ctl_stack_size);
memcpy(mqd_dst, m, sizeof(struct v9_mqd));
memcpy(ctl_stack_dst, ctl_stack, m->cp_hqd_cntl_stack_size);
memcpy(ctl_stack_dst, ctl_stack, ctl_stack_copy_size);
}
static void checkpoint_mqd_v9_4_3(struct mqd_manager *mm,
@@ -436,15 +442,19 @@ static void checkpoint_mqd_v9_4_3(struct mqd_manager *mm,
void *ctl_stack_dst)
{
struct v9_mqd *m;
u32 ctl_stack_stride;
int xcc;
uint64_t size = get_mqd(mqd)->cp_mqd_stride_size;
ctl_stack_stride = min_t(u32, get_mqd(mqd)->cp_hqd_cntl_stack_size,
mm->ctl_stack_size);
for (xcc = 0; xcc < NUM_XCC(mm->dev->xcc_mask); xcc++) {
m = get_mqd(mqd + size * xcc);
checkpoint_mqd(mm, m,
(uint8_t *)mqd_dst + sizeof(*m) * xcc,
(uint8_t *)ctl_stack_dst + m->cp_hqd_cntl_stack_size * xcc);
(uint8_t *)ctl_stack_dst + ctl_stack_stride * xcc);
}
}
@@ -998,6 +1008,15 @@ struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type,
mqd->is_occupied = kfd_is_occupied_cp;
mqd->get_checkpoint_info = get_checkpoint_info;
mqd->mqd_size = sizeof(struct v9_mqd);
if (dev->kfd->cwsr_enabled) {
struct kfd_topology_device *topo_dev;
topo_dev = kfd_topology_device_by_id(dev->id);
if (topo_dev)
mqd->ctl_stack_size =
ALIGN(topo_dev->node_props.ctl_stack_size,
AMDGPU_GPU_PAGE_SIZE);
}
mqd->mqd_stride = mqd_stride_v9;
#if defined(CONFIG_DEBUG_FS)
mqd->debugfs_show_mqd = debugfs_show_mqd;

View File

@@ -214,8 +214,8 @@ static void __update_mqd(struct mqd_manager *mm, void *mqd,
* more than (EOP entry count - 1) so a queue size of 0x800 dwords
* is safe, giving a maximum field value of 0xA.
*/
m->cp_hqd_eop_control |= min(0xA,
order_base_2(q->eop_ring_buffer_size / 4) - 1);
m->cp_hqd_eop_control |= q->eop_ring_buffer_size ? min(0xA,
order_base_2(q->eop_ring_buffer_size / 4) - 1) : 0;
m->cp_hqd_eop_base_addr_lo =
lower_32_bits(q->eop_ring_buffer_address >> 8);
m->cp_hqd_eop_base_addr_hi =

View File

@@ -6614,8 +6614,8 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
{
struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state);
struct rect *dirty_rects = flip_addrs->dirty_rects;
u32 num_clips;
struct drm_mode_rect *clips;
u32 num_clips = 0;
struct drm_mode_rect *clips = NULL;
bool bb_changed;
bool fb_changed;
u32 i = 0;
@@ -6631,8 +6631,10 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
if (new_plane_state->rotation != DRM_MODE_ROTATE_0)
goto ffu;
num_clips = drm_plane_get_damage_clips_count(new_plane_state);
clips = drm_plane_get_damage_clips(new_plane_state);
if (!new_plane_state->ignore_damage_clips) {
num_clips = drm_plane_get_damage_clips_count(new_plane_state);
clips = drm_plane_get_damage_clips(new_plane_state);
}
if (num_clips && (!amdgpu_damage_clips || (amdgpu_damage_clips < 0 &&
is_psr_su)))

View File

@@ -1509,7 +1509,7 @@ static void disable_vbios_mode_if_required(
struct dc *dc_create(const struct dc_init_data *init_params)
{
struct dc *dc = kzalloc_obj(*dc);
struct dc *dc = kvzalloc_obj(*dc);
unsigned int full_pipe_count;
if (!dc)
@@ -1557,7 +1557,7 @@ struct dc *dc_create(const struct dc_init_data *init_params)
destruct_dc:
dc_destruct(dc);
kfree(dc);
kvfree(dc);
return NULL;
}
@@ -1606,7 +1606,7 @@ void dc_deinit_callbacks(struct dc *dc)
void dc_destroy(struct dc **dc)
{
dc_destruct(*dc);
kfree(*dc);
kvfree(*dc);
*dc = NULL;
}
@@ -4077,8 +4077,6 @@ static void commit_planes_do_stream_update_sequence(struct dc *dc,
{
int j;
struct block_sequence_state seq_state = { .steps = block_sequence, .num_steps = num_steps };
struct dsc_config dsc_cfgs[MAX_PIPES];
struct dsc_optc_config dsc_optc_cfgs[MAX_PIPES];
unsigned int dsc_cfg_index = 0;
*num_steps = 0; // Initialize to 0
@@ -4150,11 +4148,13 @@ static void commit_planes_do_stream_update_sequence(struct dc *dc,
if (stream_update->dsc_config)
if (dsc_cfg_index < MAX_PIPES) {
struct dsc_config dsc_cfg;
struct dsc_optc_config dsc_optc_cfg;
add_link_update_dsc_config_sequence(&seq_state,
pipe_ctx,
&dsc_cfgs[dsc_cfg_index],
&dsc_optc_cfgs[dsc_cfg_index]);
dsc_cfg_index++;
&dsc_cfg,
&dsc_optc_cfg);
}
if (stream_update->mst_bw_update) {

View File

@@ -46,6 +46,7 @@
DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DCCG_FIFO_ERRDET_STATE, mask_sh),\
DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DCCG_FIFO_ERRDET_OVR_EN, mask_sh),\
DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_CHG_FWD_CORR_DISABLE, mask_sh),\
DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, RESYNC_FIFO_LEVEL_ADJUST_EN, mask_sh),\
DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_PHASE, mask_sh),\
DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_MODULO, mask_sh),\
DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_EN, mask_sh),\
@@ -56,34 +57,24 @@
DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_SRC_SEL, mask_sh),\
DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_EN, mask_sh),\
DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_SRC_SEL, mask_sh),\
DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_EN, mask_sh),\
DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_SRC_SEL, mask_sh),\
DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK0_EN, mask_sh),\
DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK1_EN, mask_sh),\
DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK2_EN, mask_sh),\
DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK3_EN, mask_sh),\
DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK0_SRC_SEL, mask_sh),\
DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK1_SRC_SEL, mask_sh),\
DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK2_SRC_SEL, mask_sh),\
DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK3_SRC_SEL, mask_sh),\
DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_EN, mask_sh),\
DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE0_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE1_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE2_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE3_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE0_EN, mask_sh),\
DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE1_EN, mask_sh),\
DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE2_EN, mask_sh),\
DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE3_EN, mask_sh),\
DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE0_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE1_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE2_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE3_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE0_EN, mask_sh),\
DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE1_EN, mask_sh),\
DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE2_EN, mask_sh),\
DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE3_EN, mask_sh),\
DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 0, mask_sh),\
DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 1, mask_sh),\
DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 2, mask_sh),\
@@ -121,7 +112,6 @@
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GLOBAL_FGCG_REP_CNTL, DCCG_GLOBAL_FGCG_REP_DIS, mask_sh),\
DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 0, mask_sh),\
DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 1, mask_sh),\
@@ -134,7 +124,6 @@
DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK0_EN, mask_sh),\
DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK1_EN, mask_sh),\
DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK2_EN, mask_sh),\
DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK3_EN, mask_sh),\
DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_PHASE, mask_sh),\
DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_MODULO, mask_sh),\
DCCG_SF(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_PHASE, mask_sh),\
@@ -147,36 +136,26 @@
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKA_FE_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKB_FE_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKC_FE_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKD_FE_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKA_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKB_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKC_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKD_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE0_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE1_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE2_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE3_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE0_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE1_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE2_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE3_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE0_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE1_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE2_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE3_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE0_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE1_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE2_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE3_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL4, HDMICHARCLK0_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYA_REFCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYB_REFCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYC_REFCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYD_REFCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, mask_sh),\
@@ -184,19 +163,15 @@
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK0_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK1_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK2_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK0_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK1_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK2_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, mask_sh),\
@@ -208,26 +183,38 @@
DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, mask_sh),\
DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, mask_sh),\
DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, mask_sh),\
DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, mask_sh),\
DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, mask_sh),\
DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, mask_sh),\
DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, mask_sh),\
DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, mask_sh),\
DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_SRC_SEL, mask_sh)
DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_SRC_SEL, mask_sh)
#define DCCG_MASK_SH_LIST_DCN42(mask_sh) \
DCCG_MASK_SH_LIST_DCN42_COMMON(mask_sh),\
DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_EN, mask_sh),\
DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_SRC_SEL, mask_sh),\
DCCG_SF(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_EN, mask_sh),\
DCCG_SF(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_SRC_SEL, mask_sh),\
DCCG_SF(HDMISTREAMCLK0_DTO_PARAM, HDMISTREAMCLK0_DTO_PHASE, mask_sh),\
DCCG_SF(HDMISTREAMCLK0_DTO_PARAM, HDMISTREAMCLK0_DTO_MODULO, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKD_FE_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKD_GATE_DISABLE, mask_sh),\
DCCG_SF(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_PHASE, mask_sh),\
DCCG_SF(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_MODULO, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE3_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE2_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE3_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE3_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE2_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE3_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYD_REFCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYE_REFCLK_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, mask_sh),\
DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_ROOT_GATE_DISABLE, mask_sh),\
@@ -236,11 +223,22 @@
DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, mask_sh),\
DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, mask_sh),\
DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_CLOCK_ENABLE, mask_sh),\
DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_EN, mask_sh),\
DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_SRC_SEL, mask_sh),\
DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, RESYNC_FIFO_LEVEL_ADJUST_EN, mask_sh)
DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE3_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE3_EN, mask_sh),\
DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE2_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE3_SRC_SEL, mask_sh),\
DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE2_EN, mask_sh),\
DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE3_EN, mask_sh),\
DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK3_EN, mask_sh),\
DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK3_SRC_SEL, mask_sh),\
DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK3_EN, mask_sh)
void dccg42_otg_add_pixel(struct dccg *dccg,

View File

@@ -271,7 +271,6 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
bool use_vsc_sdp_for_colorimetry,
uint32_t enable_sdp_splitting)
{
(void)use_vsc_sdp_for_colorimetry;
(void)enable_sdp_splitting;
uint32_t h_active_start;
uint32_t v_active_start;
@@ -334,6 +333,16 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
if (REG(DP_MSA_MISC))
misc1 = REG_READ(DP_MSA_MISC);
/* For YCbCr420 and BT2020 Colorimetry Formats, VSC SDP shall be used.
* When MISC1, bit 6, is Set to 1, a Source device uses a VSC SDP to indicate the
* Pixel Encoding/Colorimetry Format and that a Sink device shall ignore MISC1, bit 7,
* and MISC0, bits 7:1 (MISC1, bit 7, and MISC0, bits 7:1, become "don't care").
*/
if (use_vsc_sdp_for_colorimetry)
misc1 = misc1 | 0x40;
else
misc1 = misc1 & ~0x40;
/* set color depth */
switch (hw_crtc_timing.display_color_depth) {
@@ -499,6 +508,10 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
hw_crtc_timing.h_addressable + hw_crtc_timing.h_border_right,
DP_MSA_VHEIGHT, hw_crtc_timing.v_border_top +
hw_crtc_timing.v_addressable + hw_crtc_timing.v_border_bottom);
} else {
/* DCE-only path */
if (REG(DP_MSA_MISC))
REG_WRITE(DP_MSA_MISC, misc1); /* MSA_MISC1 */
}
}

View File

@@ -96,7 +96,8 @@
#define SE_COMMON_REG_LIST(id)\
SE_COMMON_REG_LIST_DCE_BASE(id), \
SRI(AFMT_CNTL, DIG, id)
SRI(AFMT_CNTL, DIG, id), \
SRI(DP_MSA_MISC, DP, id)
#define SE_DCN_REG_LIST(id)\
SE_COMMON_REG_LIST_BASE(id),\

View File

@@ -1164,8 +1164,11 @@ static bool detect_link_and_local_sink(struct dc_link *link,
link->link_enc->features.flags.bits.DP_IS_USB_C == 1) {
/* if alt mode times out, return false */
if (!wait_for_entering_dp_alt_mode(link))
if (!wait_for_entering_dp_alt_mode(link)) {
if (prev_sink)
dc_sink_release(prev_sink);
return false;
}
}
if (!detect_dp(link, &sink_caps, reason)) {

View File

@@ -33,22 +33,28 @@ void mod_hdcp_dump_binary_message(uint8_t *msg, uint32_t msg_size,
byte_size = 3,
newline_size = 1,
terminator_size = 1;
uint32_t line_count = msg_size / bytes_per_line,
trailing_bytes = msg_size % bytes_per_line;
uint32_t target_size = (byte_size * bytes_per_line + newline_size) * line_count +
byte_size * trailing_bytes + newline_size + terminator_size;
uint32_t buf_pos = 0;
uint32_t i = 0;
if (buf_size >= target_size) {
for (i = 0; i < msg_size; i++) {
if (i % bytes_per_line == 0)
buf[buf_pos++] = '\n';
sprintf((char *)&buf[buf_pos], "%02X ", msg[i]);
buf_pos += byte_size;
}
buf[buf_pos++] = '\0';
/* Need room for at least the terminator. */
if (buf_size < terminator_size)
return;
for (i = 0; i < msg_size; i++) {
uint32_t needed = byte_size + terminator_size;
if (i % bytes_per_line == 0)
needed += newline_size;
if (buf_pos + needed > buf_size)
break;
if (i % bytes_per_line == 0)
buf[buf_pos++] = '\n';
sprintf((char *)&buf[buf_pos], "%02X ", msg[i]);
buf_pos += byte_size;
}
buf[buf_pos++] = '\0';
}
void mod_hdcp_log_ddc_trace(struct mod_hdcp *hdcp)

View File

@@ -427,6 +427,7 @@ union MESAPI__SUSPEND {
uint32_t suspend_fence_value;
struct MES_API_STATUS api_status;
uint32_t doorbell_offset;
};
uint32_t max_dwords_in_api[API_FRAME_SIZE_IN_DWORDS];
@@ -444,6 +445,7 @@ union MESAPI__RESUME {
uint64_t gang_context_addr;
struct MES_API_STATUS api_status;
uint32_t doorbell_offset;
};
uint32_t max_dwords_in_api[API_FRAME_SIZE_IN_DWORDS];

View File

@@ -41,6 +41,8 @@
#define DEVICE_ATTR_IS(_name) (attr_id == device_attr_id__##_name)
#define power_2_mwatt(power) (((power) >> 8) * 1000 + ((power) & 0xff))
struct od_attribute {
struct kobj_attribute attribute;
struct list_head entry;
@@ -2696,6 +2698,11 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_
gc_ver != IP_VERSION(9, 4, 3)) ||
gc_ver < IP_VERSION(9, 0, 0))
*states = ATTR_STATE_UNSUPPORTED;
if (adev->scpm_enabled) {
dev_attr->attr.mode &= ~S_IWUGO;
dev_attr->store = NULL;
}
} else if (DEVICE_ATTR_IS(gpu_metrics)) {
if (gc_ver < IP_VERSION(9, 1, 0))
*states = ATTR_STATE_UNSUPPORTED;
@@ -3349,7 +3356,6 @@ static int amdgpu_hwmon_get_power(struct device *dev,
enum amd_pp_sensors sensor)
{
struct amdgpu_device *adev = dev_get_drvdata(dev);
unsigned int uw;
u32 query = 0;
int r;
@@ -3358,9 +3364,7 @@ static int amdgpu_hwmon_get_power(struct device *dev,
return r;
/* convert to microwatts */
uw = (query >> 8) * 1000000 + (query & 0xff) * 1000;
return uw;
return power_2_mwatt(query) * 1000;
}
static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev,
@@ -4903,7 +4907,7 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a
{
uint32_t mp1_ver = amdgpu_ip_version(adev, MP1_HWIP, 0);
uint32_t gc_ver = amdgpu_ip_version(adev, GC_HWIP, 0);
uint32_t value;
uint32_t value, mwatt, centiwatt;
uint64_t value64 = 0;
uint32_t query = 0;
int size;
@@ -4928,17 +4932,21 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a
seq_printf(m, "\t%u mV (VDDNB)\n", value);
size = sizeof(uint32_t);
if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_AVG_POWER, (void *)&query, &size)) {
mwatt = power_2_mwatt(query);
centiwatt = DIV_ROUND_CLOSEST(mwatt, 10);
if (adev->flags & AMD_IS_APU)
seq_printf(m, "\t%u.%02u W (average SoC including CPU)\n", query >> 8, query & 0xff);
seq_printf(m, "\t%u.%02u W (average SoC including CPU)\n", centiwatt / 100, centiwatt % 100);
else
seq_printf(m, "\t%u.%02u W (average SoC)\n", query >> 8, query & 0xff);
seq_printf(m, "\t%u.%02u W (average SoC)\n", centiwatt / 100, centiwatt % 100);
}
size = sizeof(uint32_t);
if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_INPUT_POWER, (void *)&query, &size)) {
mwatt = power_2_mwatt(query);
centiwatt = DIV_ROUND_CLOSEST(mwatt, 10);
if (adev->flags & AMD_IS_APU)
seq_printf(m, "\t%u.%02u W (current SoC including CPU)\n", query >> 8, query & 0xff);
seq_printf(m, "\t%u.%02u W (current SoC including CPU)\n", centiwatt / 100, centiwatt % 100);
else
seq_printf(m, "\t%u.%02u W (current SoC)\n", query >> 8, query & 0xff);
seq_printf(m, "\t%u.%02u W (current SoC)\n", centiwatt / 100, centiwatt % 100);
}
size = sizeof(value);
seq_printf(m, "\n");

View File

@@ -2403,11 +2403,14 @@ static int smu_v13_0_0_get_power_limit(struct smu_context *smu,
uint32_t pp_limit = smu->adev->pm.ac_power ?
skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
uint32_t power_limit = 0, od_percent_upper = 0, od_percent_lower = 0;
uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
uint32_t min_limit = min_t(uint32_t, pp_limit, msg_limit);
uint32_t max_limit = max_t(uint32_t, pp_limit, msg_limit);
uint32_t od_percent_upper = 0, od_percent_lower = 0;
int ret;
if (current_power_limit) {
ret = smu_v13_0_get_current_power_limit(smu, &power_limit);
ret = smu_v13_0_get_current_power_limit(smu, current_power_limit);
if (ret)
*current_power_limit = pp_limit;
}
@@ -2430,12 +2433,12 @@ static int smu_v13_0_0_get_power_limit(struct smu_context *smu,
od_percent_upper, od_percent_lower, pp_limit);
if (max_power_limit) {
*max_power_limit = pp_limit * (100 + od_percent_upper);
*max_power_limit = max_limit * (100 + od_percent_upper);
*max_power_limit /= 100;
}
if (min_power_limit) {
*min_power_limit = pp_limit * (100 - od_percent_lower);
*min_power_limit = min_limit * (100 - od_percent_lower);
*min_power_limit /= 100;
}

View File

@@ -2385,15 +2385,16 @@ static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
uint32_t pp_limit = smu->adev->pm.ac_power ?
skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
uint32_t power_limit = 0, od_percent_upper = 0, od_percent_lower = 0;
uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
uint32_t min_limit = min_t(uint32_t, pp_limit, msg_limit);
uint32_t max_limit = max_t(uint32_t, pp_limit, msg_limit);
uint32_t od_percent_upper = 0, od_percent_lower = 0;
int ret;
if (current_power_limit) {
ret = smu_v13_0_get_current_power_limit(smu, &power_limit);
ret = smu_v13_0_get_current_power_limit(smu, current_power_limit);
if (ret)
power_limit = pp_limit;
*current_power_limit = power_limit;
*current_power_limit = pp_limit;
}
if (default_power_limit)
@@ -2414,12 +2415,12 @@ static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
od_percent_upper, od_percent_lower, pp_limit);
if (max_power_limit) {
*max_power_limit = pp_limit * (100 + od_percent_upper);
*max_power_limit = max_limit * (100 + od_percent_upper);
*max_power_limit /= 100;
}
if (min_power_limit) {
*min_power_limit = pp_limit * (100 - od_percent_lower);
*min_power_limit = min_limit * (100 - od_percent_lower);
*min_power_limit /= 100;
}

View File

@@ -313,7 +313,11 @@ void komeda_dev_destroy(struct komeda_dev *mdev)
int komeda_dev_resume(struct komeda_dev *mdev)
{
clk_prepare_enable(mdev->aclk);
int err;
err = clk_prepare_enable(mdev->aclk);
if (err)
return err;
mdev->funcs->enable_irq(mdev);

View File

@@ -74,8 +74,11 @@ static int komeda_platform_probe(struct platform_device *pdev)
}
pm_runtime_enable(dev);
if (!pm_runtime_enabled(dev))
komeda_dev_resume(mdrv->mdev);
if (!pm_runtime_enabled(dev)) {
err = komeda_dev_resume(mdrv->mdev);
if (err)
goto err_destroy_mdev;
}
mdrv->kms = komeda_kms_attach(mdrv->mdev);
if (IS_ERR(mdrv->kms)) {
@@ -93,7 +96,7 @@ static int komeda_platform_probe(struct platform_device *pdev)
pm_runtime_disable(dev);
else
komeda_dev_suspend(mdrv->mdev);
err_destroy_mdev:
komeda_dev_destroy(mdrv->mdev);
free_mdrv:
@@ -140,11 +143,12 @@ static int __maybe_unused komeda_pm_suspend(struct device *dev)
static int __maybe_unused komeda_pm_resume(struct device *dev)
{
struct komeda_drv *mdrv = dev_get_drvdata(dev);
int err = 0;
if (!pm_runtime_status_suspended(dev))
komeda_dev_resume(mdrv->mdev);
err = komeda_dev_resume(mdrv->mdev);
return drm_mode_config_helper_resume(&mdrv->kms->base);
return err ? err : drm_mode_config_helper_resume(&mdrv->kms->base);
}
static const struct dev_pm_ops komeda_pm_ops = {

View File

@@ -670,6 +670,11 @@ static int malidp_runtime_pm_suspend(struct device *dev)
struct drm_device *drm = dev_get_drvdata(dev);
struct malidp_drm *malidp = drm_to_malidp(drm);
struct malidp_hw_device *hwdev = malidp->dev;
struct clk_bulk_data clks[] = {
{ .clk = hwdev->pclk },
{ .clk = hwdev->aclk },
{ .clk = hwdev->mclk },
};
/* we can only suspend if the hardware is in config mode */
WARN_ON(!hwdev->hw->in_config_mode(hwdev));
@@ -677,9 +682,7 @@ static int malidp_runtime_pm_suspend(struct device *dev)
malidp_se_irq_fini(hwdev);
malidp_de_irq_fini(hwdev);
hwdev->pm_suspended = true;
clk_disable_unprepare(hwdev->mclk);
clk_disable_unprepare(hwdev->aclk);
clk_disable_unprepare(hwdev->pclk);
clk_bulk_disable_unprepare(ARRAY_SIZE(clks), clks);
return 0;
}
@@ -689,10 +692,17 @@ static int malidp_runtime_pm_resume(struct device *dev)
struct drm_device *drm = dev_get_drvdata(dev);
struct malidp_drm *malidp = drm_to_malidp(drm);
struct malidp_hw_device *hwdev = malidp->dev;
struct clk_bulk_data clks[] = {
{ .clk = hwdev->pclk },
{ .clk = hwdev->aclk },
{ .clk = hwdev->mclk },
};
int err;
err = clk_bulk_prepare_enable(ARRAY_SIZE(clks), clks);
if (err)
return err;
clk_prepare_enable(hwdev->pclk);
clk_prepare_enable(hwdev->aclk);
clk_prepare_enable(hwdev->mclk);
hwdev->pm_suspended = false;
malidp_de_irq_hw_init(hwdev);
malidp_se_irq_hw_init(hwdev);

View File

@@ -3740,8 +3740,10 @@ void drm_dp_mst_topology_queue_probe(struct drm_dp_mst_topology_mgr *mgr)
{
mutex_lock(&mgr->lock);
if (drm_WARN_ON(mgr->dev, !mgr->mst_state || !mgr->mst_primary))
if (!mgr->mst_state || !mgr->mst_primary) {
drm_dbg_kms(mgr->dev, "queue_probe skipped: topology torn down\n");
goto out_unlock;
}
drm_dp_mst_topology_mgr_invalidate_mstb(mgr->mst_primary);
drm_dp_mst_queue_probe_work(mgr);

View File

@@ -623,6 +623,21 @@ get_lfp_data_tail(const struct bdb_lfp_data *data,
return NULL;
}
static bool is_panel_type_valid(int panel_type)
{
return panel_type >= 0 && panel_type < 16;
}
static bool is_panel_type_pnp(int panel_type)
{
return panel_type == 0xff;
}
static bool is_panel_type_valid_or_pnp(int panel_type)
{
return is_panel_type_valid(panel_type) || is_panel_type_pnp(panel_type);
}
static int opregion_get_panel_type(struct intel_display *display,
const struct intel_bios_encoder_data *devdata,
const struct drm_edid *drm_edid, bool use_fallback)
@@ -640,15 +655,21 @@ static int vbt_get_panel_type(struct intel_display *display,
if (!lfp_options)
return -1;
if (lfp_options->panel_type > 0xf &&
lfp_options->panel_type != 0xff) {
if (!is_panel_type_valid_or_pnp(lfp_options->panel_type)) {
drm_dbg_kms(display->drm, "Invalid VBT panel type 0x%x\n",
lfp_options->panel_type);
return -1;
}
if (devdata && devdata->child.handle == DEVICE_HANDLE_LFP2)
if (devdata && devdata->child.handle == DEVICE_HANDLE_LFP2) {
if (!is_panel_type_valid_or_pnp(lfp_options->panel_type2)) {
drm_dbg_kms(display->drm, "Invalid VBT panel type 2 0x%x\n",
lfp_options->panel_type2);
return -1;
}
return lfp_options->panel_type2;
}
drm_WARN_ON(display->drm,
devdata && devdata->child.handle != DEVICE_HANDLE_LFP1);
@@ -762,13 +783,12 @@ static int get_panel_type(struct intel_display *display,
panel_types[i].name, panel_types[i].panel_type);
}
if (panel_types[PANEL_TYPE_OPREGION].panel_type >= 0)
if (is_panel_type_valid(panel_types[PANEL_TYPE_OPREGION].panel_type))
i = PANEL_TYPE_OPREGION;
else if (panel_types[PANEL_TYPE_VBT].panel_type == 0xff &&
panel_types[PANEL_TYPE_PNPID].panel_type >= 0)
else if (is_panel_type_pnp(panel_types[PANEL_TYPE_VBT].panel_type) &&
is_panel_type_valid(panel_types[PANEL_TYPE_PNPID].panel_type))
i = PANEL_TYPE_PNPID;
else if (panel_types[PANEL_TYPE_VBT].panel_type != 0xff &&
panel_types[PANEL_TYPE_VBT].panel_type >= 0)
else if (is_panel_type_valid(panel_types[PANEL_TYPE_VBT].panel_type))
i = PANEL_TYPE_VBT;
else
i = PANEL_TYPE_FALLBACK;

View File

@@ -145,6 +145,9 @@ intel_hdcp_required_content_stream(struct intel_atomic_state *state,
if (!new_conn_state || !new_conn_state->crtc)
continue;
if (drm_WARN_ON(display->drm, data->k >= INTEL_NUM_PIPES(display)))
return -EINVAL;
data->streams[data->k].stream_id =
intel_conn_to_vcpi(state, connector);
data->k++;
@@ -155,7 +158,7 @@ intel_hdcp_required_content_stream(struct intel_atomic_state *state,
}
drm_connector_list_iter_end(&conn_iter);
if (drm_WARN_ON(display->drm, data->k > INTEL_NUM_PIPES(display) || data->k == 0))
if (drm_WARN_ON(display->drm, !data->k))
return -EINVAL;
/*
@@ -1798,9 +1801,10 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
return -EINVAL;
}
if (seq_num_v < hdcp->seq_num_v) {
/* Roll over of the seq_num_v from repeater. Reauthenticate. */
drm_dbg_kms(display->drm, "Seq_num_v roll over.\n");
if (hdcp->hdcp2_encrypted && seq_num_v <= hdcp->seq_num_v) {
/* Reauthenticate on Seq_num_v repeat or rollover */
drm_dbg_kms(display->drm, "Seq_num_v %s\n",
seq_num_v == hdcp->seq_num_v ? "repeat" : "rollover");
return -EINVAL;
}

View File

@@ -74,6 +74,10 @@ bool intel_vrr_is_capable(struct intel_connector *connector)
return false;
}
if (!info->monitor_range.min_vfreq || !info->monitor_range.max_vfreq ||
info->monitor_range.min_vfreq > info->monitor_range.max_vfreq)
return false;
return info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10;
}

View File

@@ -318,7 +318,7 @@ active_instance(struct i915_active *ref, u64 idx)
*/
node = kmem_cache_alloc(slab_cache, GFP_ATOMIC);
if (!node)
goto out;
goto err;
__i915_active_fence_init(&node->base, NULL, node_retire);
node->ref = ref;
@@ -332,6 +332,11 @@ active_instance(struct i915_active *ref, u64 idx)
spin_unlock_irq(&ref->tree_lock);
return &node->base;
err:
spin_unlock_irq(&ref->tree_lock);
return NULL;
}
void __i915_active_init(struct i915_active *ref,

View File

@@ -161,22 +161,24 @@ ctx_fw_data_init(void *cpu_ptr, void *priv)
/**
* pvr_context_destroy_queues() - Destroy all queues attached to a context.
* @ctx: Context to destroy queues on.
* @cleanup_queue_entity: Whether to cleanup the queue entity e.g. context
* creation failure path.
*
* Should be called when the last reference to a context object is dropped.
* It releases all resources attached to the queues bound to this context.
*/
static void pvr_context_destroy_queues(struct pvr_context *ctx)
static void pvr_context_destroy_queues(struct pvr_context *ctx, bool cleanup_queue_entity)
{
switch (ctx->type) {
case DRM_PVR_CTX_TYPE_RENDER:
pvr_queue_destroy(ctx->queues.fragment);
pvr_queue_destroy(ctx->queues.geometry);
pvr_queue_destroy(ctx->queues.fragment, cleanup_queue_entity);
pvr_queue_destroy(ctx->queues.geometry, cleanup_queue_entity);
break;
case DRM_PVR_CTX_TYPE_COMPUTE:
pvr_queue_destroy(ctx->queues.compute);
pvr_queue_destroy(ctx->queues.compute, cleanup_queue_entity);
break;
case DRM_PVR_CTX_TYPE_TRANSFER_FRAG:
pvr_queue_destroy(ctx->queues.transfer);
pvr_queue_destroy(ctx->queues.transfer, cleanup_queue_entity);
break;
}
}
@@ -240,7 +242,7 @@ static int pvr_context_create_queues(struct pvr_context *ctx,
return -EINVAL;
err_destroy_queues:
pvr_context_destroy_queues(ctx);
pvr_context_destroy_queues(ctx, true);
return err;
}
@@ -349,7 +351,7 @@ int pvr_context_create(struct pvr_file *pvr_file, struct drm_pvr_ioctl_create_co
pvr_fw_object_destroy(ctx->fw_obj);
err_destroy_queues:
pvr_context_destroy_queues(ctx);
pvr_context_destroy_queues(ctx, true);
err_free_ctx_id:
/*
@@ -384,7 +386,7 @@ pvr_context_release(struct kref *ref_count)
spin_unlock(&pvr_dev->ctx_list_lock);
xa_erase(&pvr_dev->ctx_ids, ctx->ctx_id);
pvr_context_destroy_queues(ctx);
pvr_context_destroy_queues(ctx, false);
pvr_fw_object_destroy(ctx->fw_obj);
kfree(ctx->data);
pvr_vm_context_put(ctx->vm_ctx);

View File

@@ -514,7 +514,8 @@ pvr_dev_query_quirks_get(struct pvr_device *pvr_dev,
if (err < 0)
return err;
args->size = sizeof(query);
if (args->size > sizeof(query))
args->size = sizeof(query);
return 0;
}
@@ -595,7 +596,8 @@ pvr_dev_query_enhancements_get(struct pvr_device *pvr_dev,
if (err < 0)
return err;
args->size = sizeof(query);
if (args->size > sizeof(query))
args->size = sizeof(query);
return 0;
}
@@ -1254,14 +1256,13 @@ pvr_set_uobj_array(const struct drm_pvr_obj_array *out, u32 min_stride, u32 obj_
if (copy_to_user(out_ptr, in_ptr, cpy_elem_size))
return -EFAULT;
out_ptr += obj_size;
in_ptr += out->stride;
}
if (out->stride > obj_size &&
clear_user(out_ptr + cpy_elem_size, out->stride - obj_size)) {
return -EFAULT;
}
if (out->stride > obj_size &&
clear_user(u64_to_user_ptr(out->array + obj_size),
out->stride - obj_size)) {
return -EFAULT;
out_ptr += out->stride;
in_ptr += obj_size;
}
}

View File

@@ -1439,11 +1439,12 @@ void pvr_queue_kill(struct pvr_queue *queue)
/**
* pvr_queue_destroy() - Destroy a queue.
* @queue: The queue to destroy.
* @cleanup_queue_entity: Whether to cleanup the queue entity.
*
* Cleanup the queue and free the resources attached to it. Should be
* called from the context release function.
*/
void pvr_queue_destroy(struct pvr_queue *queue)
void pvr_queue_destroy(struct pvr_queue *queue, bool cleanup_queue_entity)
{
if (!queue)
return;
@@ -1453,7 +1454,8 @@ void pvr_queue_destroy(struct pvr_queue *queue)
mutex_unlock(&queue->ctx->pvr_dev->queues.lock);
drm_sched_fini(&queue->scheduler);
drm_sched_entity_fini(&queue->entity);
if (cleanup_queue_entity)
drm_sched_entity_fini(&queue->entity);
if (WARN_ON(queue->last_queued_job_scheduled_fence))
dma_fence_put(queue->last_queued_job_scheduled_fence);

View File

@@ -158,7 +158,7 @@ struct pvr_queue *pvr_queue_create(struct pvr_context *ctx,
void pvr_queue_kill(struct pvr_queue *queue);
void pvr_queue_destroy(struct pvr_queue *queue);
void pvr_queue_destroy(struct pvr_queue *queue, bool cleanup_queue_entity);
void pvr_queue_process(struct pvr_queue *queue);

View File

@@ -1019,7 +1019,8 @@ pvr_static_data_areas_get(const struct pvr_device *pvr_dev,
if (err < 0)
return err;
args->size = sizeof(query);
if (args->size > sizeof(query))
args->size = sizeof(query);
return 0;
}
@@ -1069,7 +1070,8 @@ pvr_heap_info_get(const struct pvr_device *pvr_dev,
if (err < 0)
return err;
args->size = sizeof(query);
if (args->size > sizeof(query))
args->size = sizeof(query);
return 0;
}

View File

@@ -207,6 +207,7 @@ int panthor_device_init(struct panthor_device *ptdev)
*dummy_page_virt = 1;
INIT_WORK(&ptdev->reset.work, panthor_device_reset_work);
disable_work(&ptdev->reset.work);
ptdev->reset.wq = alloc_ordered_workqueue("panthor-reset-wq", 0);
if (!ptdev->reset.wq)
return -ENOMEM;
@@ -285,6 +286,9 @@ int panthor_device_init(struct panthor_device *ptdev)
panthor_gem_init(ptdev);
/* Now that everything is initialized, we can enable the reset work. */
enable_work(&ptdev->reset.work);
/* ~3 frames */
pm_runtime_set_autosuspend_delay(ptdev->base.dev, 50);
pm_runtime_use_autosuspend(ptdev->base.dev);

View File

@@ -509,9 +509,6 @@ static irqreturn_t panthor_ ## __name ## _irq_raw_handler(int irq, void *data)
struct panthor_irq *pirq = data; \
enum panthor_irq_state old_state; \
\
if (!gpu_read(pirq->iomem, INT_STAT)) \
return IRQ_NONE; \
\
guard(spinlock_irqsave)(&pirq->mask_lock); \
old_state = atomic_cmpxchg(&pirq->state, \
PANTHOR_IRQ_STATE_ACTIVE, \
@@ -519,6 +516,13 @@ static irqreturn_t panthor_ ## __name ## _irq_raw_handler(int irq, void *data)
if (old_state != PANTHOR_IRQ_STATE_ACTIVE) \
return IRQ_NONE; \
\
if (!gpu_read(pirq->iomem, INT_STAT)) { \
atomic_cmpxchg(&pirq->state, \
PANTHOR_IRQ_STATE_PROCESSING, \
PANTHOR_IRQ_STATE_ACTIVE); \
return IRQ_NONE; \
} \
\
gpu_write(pirq->iomem, INT_MASK, 0); \
return IRQ_WAKE_THREAD; \
} \
@@ -581,14 +585,15 @@ static inline void panthor_ ## __name ## _irq_resume(struct panthor_irq *pirq)
\
static int panthor_request_ ## __name ## _irq(struct panthor_device *ptdev, \
struct panthor_irq *pirq, \
int irq, u32 mask, void __iomem *iomem) \
int irq, void __iomem *iomem) \
{ \
pirq->ptdev = ptdev; \
pirq->irq = irq; \
pirq->mask = mask; \
pirq->mask = 0; \
pirq->iomem = iomem; \
spin_lock_init(&pirq->mask_lock); \
panthor_ ## __name ## _irq_resume(pirq); \
atomic_set(&pirq->state, PANTHOR_IRQ_STATE_SUSPENDED); \
gpu_write(pirq->iomem, INT_MASK, 0); \
\
return devm_request_threaded_irq(ptdev->base.dev, irq, \
panthor_ ## __name ## _irq_raw_handler, \

View File

@@ -1279,9 +1279,7 @@ void panthor_fw_unplug(struct panthor_device *ptdev)
if (!IS_ENABLED(CONFIG_PM) || pm_runtime_active(ptdev->base.dev)) {
/* Make sure the IRQ handler cannot be called after that point. */
if (ptdev->fw->irq.irq)
panthor_job_irq_suspend(&ptdev->fw->irq);
panthor_job_irq_suspend(&ptdev->fw->irq);
panthor_fw_stop(ptdev);
}
@@ -1476,7 +1474,7 @@ int panthor_fw_init(struct panthor_device *ptdev)
if (irq <= 0)
return -ENODEV;
ret = panthor_request_job_irq(ptdev, &fw->irq, irq, 0,
ret = panthor_request_job_irq(ptdev, &fw->irq, irq,
ptdev->iomem + JOB_INT_BASE);
if (ret) {
drm_err(&ptdev->base, "failed to request job irq");

View File

@@ -170,11 +170,12 @@ int panthor_gpu_init(struct panthor_device *ptdev)
return irq;
ret = panthor_request_gpu_irq(ptdev, &ptdev->gpu->irq, irq,
GPU_INTERRUPTS_MASK,
ptdev->iomem + GPU_INT_BASE);
if (ret)
return ret;
panthor_gpu_irq_enable_events(&ptdev->gpu->irq, GPU_INTERRUPTS_MASK);
panthor_gpu_irq_resume(&ptdev->gpu->irq);
return 0;
}

View File

@@ -3262,7 +3262,6 @@ int panthor_mmu_init(struct panthor_device *ptdev)
return -ENODEV;
ret = panthor_request_mmu_irq(ptdev, &mmu->irq, irq,
panthor_mmu_fault_mask(ptdev, ~0),
ptdev->iomem + MMU_INT_BASE);
if (ret)
return ret;
@@ -3280,7 +3279,13 @@ int panthor_mmu_init(struct panthor_device *ptdev)
ptdev->gpu_info.mmu_features |= BITS_PER_LONG;
}
return drmm_add_action_or_reset(&ptdev->base, panthor_mmu_release_wq, mmu->vm.wq);
ret = drmm_add_action_or_reset(&ptdev->base, panthor_mmu_release_wq, mmu->vm.wq);
if (ret)
return ret;
panthor_mmu_irq_enable_events(&mmu->irq, panthor_mmu_fault_mask(ptdev, ~0));
panthor_mmu_irq_resume(&mmu->irq);
return 0;
}
#ifdef CONFIG_DEBUG_FS

View File

@@ -453,7 +453,8 @@ void panthor_pwr_unplug(struct panthor_device *ptdev)
return;
/* Make sure the IRQ handler is not running after that point. */
panthor_pwr_irq_suspend(&ptdev->pwr->irq);
if (!IS_ENABLED(CONFIG_PM) || pm_runtime_active(ptdev->base.dev))
panthor_pwr_irq_suspend(&ptdev->pwr->irq);
/* Wake-up all waiters. */
spin_lock_irqsave(&ptdev->pwr->reqs_lock, flags);
@@ -483,12 +484,13 @@ int panthor_pwr_init(struct panthor_device *ptdev)
if (irq < 0)
return irq;
err = panthor_request_pwr_irq(
ptdev, &pwr->irq, irq, PWR_INTERRUPTS_MASK,
pwr->iomem + PWR_INT_BASE);
err = panthor_request_pwr_irq(ptdev, &pwr->irq, irq,
pwr->iomem + PWR_INT_BASE);
if (err)
return err;
panthor_pwr_irq_enable_events(&pwr->irq, PWR_INTERRUPTS_MASK);
panthor_pwr_irq_resume(&pwr->irq);
return 0;
}

View File

@@ -1057,7 +1057,8 @@ group_unbind_locked(struct panthor_group *group)
/* Tiler OOM events will be re-issued next time the group is scheduled. */
atomic_set(&group->tiler_oom, 0);
cancel_work(&group->tiler_oom_work);
if (cancel_work(&group->tiler_oom_work))
group_put(group);
for (u32 i = 0; i < group->queue_count; i++)
group->queues[i]->doorbell_id = -1;
@@ -1151,15 +1152,14 @@ queue_suspend_timeout_locked(struct panthor_queue *queue)
static void
queue_suspend_timeout(struct panthor_queue *queue)
{
spin_lock(&queue->fence_ctx.lock);
guard(spinlock_irqsave)(&queue->fence_ctx.lock);
queue_suspend_timeout_locked(queue);
spin_unlock(&queue->fence_ctx.lock);
}
static void
queue_resume_timeout(struct panthor_queue *queue)
{
spin_lock(&queue->fence_ctx.lock);
guard(spinlock_irqsave)(&queue->fence_ctx.lock);
if (queue_timeout_is_suspended(queue)) {
mod_delayed_work(queue->scheduler.timeout_wq,
@@ -1168,8 +1168,6 @@ queue_resume_timeout(struct panthor_queue *queue)
queue->timeout.remaining = MAX_SCHEDULE_TIMEOUT;
}
spin_unlock(&queue->fence_ctx.lock);
}
/**
@@ -1542,7 +1540,7 @@ cs_slot_process_fault_event_locked(struct panthor_device *ptdev,
u64 cs_extract = queue->iface.output->extract;
struct panthor_job *job;
spin_lock(&queue->fence_ctx.lock);
guard(spinlock_irqsave)(&queue->fence_ctx.lock);
list_for_each_entry(job, &queue->fence_ctx.in_flight_jobs, node) {
if (cs_extract >= job->ringbuf.end)
continue;
@@ -1552,7 +1550,6 @@ cs_slot_process_fault_event_locked(struct panthor_device *ptdev,
dma_fence_set_error(job->done_fence, -EINVAL);
}
spin_unlock(&queue->fence_ctx.lock);
}
if (group) {
@@ -1604,7 +1601,10 @@ static int group_process_tiler_oom(struct panthor_group *group, u32 cs_id)
if (unlikely(csg_id < 0))
return 0;
if (IS_ERR(heaps) || frag_end > vt_end || vt_end >= vt_start) {
if (IS_ERR(heaps)) {
ret = -EINVAL;
heaps = NULL;
} else if (frag_end > vt_end || vt_end >= vt_start) {
ret = -EINVAL;
} else {
/* We do the allocation without holding the scheduler lock to avoid
@@ -2183,13 +2183,13 @@ group_term_post_processing(struct panthor_group *group)
if (!queue)
continue;
spin_lock(&queue->fence_ctx.lock);
list_for_each_entry_safe(job, tmp, &queue->fence_ctx.in_flight_jobs, node) {
list_move_tail(&job->node, &faulty_jobs);
dma_fence_set_error(job->done_fence, err);
dma_fence_signal_locked(job->done_fence);
scoped_guard(spinlock_irqsave, &queue->fence_ctx.lock) {
list_for_each_entry_safe(job, tmp, &queue->fence_ctx.in_flight_jobs, node) {
list_move_tail(&job->node, &faulty_jobs);
dma_fence_set_error(job->done_fence, err);
dma_fence_signal_locked(job->done_fence);
}
}
spin_unlock(&queue->fence_ctx.lock);
/* Manually update the syncobj seqno to unblock waiters. */
syncobj = group->syncobjs->kmap + (i * sizeof(*syncobj));
@@ -2368,7 +2368,13 @@ tick_ctx_apply(struct panthor_scheduler *sched, struct panthor_sched_tick_ctx *c
csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id);
csg_slot = &sched->csg_slots[csg_id];
group_bind_locked(group, csg_id);
ret = group_bind_locked(group, csg_id);
if (ret) {
panthor_device_schedule_reset(ptdev);
ctx->csg_upd_failed_mask |= BIT(csg_id);
return;
}
csg_slot_prog_locked(ptdev, csg_id, new_csg_prio--);
csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, csg_id,
group->state == PANTHOR_CS_GROUP_SUSPENDED ?
@@ -2668,7 +2674,14 @@ static void sched_resume_tick(struct panthor_device *ptdev)
else
delay_jiffies = 0;
sched_queue_delayed_work(sched, tick, delay_jiffies);
/* We schedule immediate ticks when we need to process events on CSGs,
* but those don't change the resched_target because we want the other
* groups to stay scheduled for the remaining of the GPU timeslot they
* were given. Make sure those immediate ticks don't get overruled by
* a sched_queue_delayed_work() that would delay the tick execution.
*/
if (!delayed_work_pending(&sched->tick_work))
sched_queue_delayed_work(sched, tick, delay_jiffies);
}
static void group_schedule_locked(struct panthor_group *group, u32 queue_mask)
@@ -3049,39 +3062,39 @@ static bool queue_check_job_completion(struct panthor_queue *queue)
LIST_HEAD(done_jobs);
cookie = dma_fence_begin_signalling();
spin_lock(&queue->fence_ctx.lock);
list_for_each_entry_safe(job, job_tmp, &queue->fence_ctx.in_flight_jobs, node) {
if (!syncobj) {
struct panthor_group *group = job->group;
scoped_guard(spinlock_irqsave, &queue->fence_ctx.lock) {
list_for_each_entry_safe(job, job_tmp, &queue->fence_ctx.in_flight_jobs, node) {
if (!syncobj) {
struct panthor_group *group = job->group;
syncobj = group->syncobjs->kmap +
(job->queue_idx * sizeof(*syncobj));
syncobj = group->syncobjs->kmap +
(job->queue_idx * sizeof(*syncobj));
}
if (syncobj->seqno < job->done_fence->seqno)
break;
list_move_tail(&job->node, &done_jobs);
dma_fence_signal_locked(job->done_fence);
}
if (syncobj->seqno < job->done_fence->seqno)
break;
if (list_empty(&queue->fence_ctx.in_flight_jobs)) {
/* If we have no job left, we cancel the timer, and reset remaining
* time to its default so it can be restarted next time
* queue_resume_timeout() is called.
*/
queue_suspend_timeout_locked(queue);
list_move_tail(&job->node, &done_jobs);
dma_fence_signal_locked(job->done_fence);
/* If there's no job pending, we consider it progress to avoid a
* spurious timeout if the timeout handler and the sync update
* handler raced.
*/
progress = true;
} else if (!list_empty(&done_jobs)) {
queue_reset_timeout_locked(queue);
progress = true;
}
}
if (list_empty(&queue->fence_ctx.in_flight_jobs)) {
/* If we have no job left, we cancel the timer, and reset remaining
* time to its default so it can be restarted next time
* queue_resume_timeout() is called.
*/
queue_suspend_timeout_locked(queue);
/* If there's no job pending, we consider it progress to avoid a
* spurious timeout if the timeout handler and the sync update
* handler raced.
*/
progress = true;
} else if (!list_empty(&done_jobs)) {
queue_reset_timeout_locked(queue);
progress = true;
}
spin_unlock(&queue->fence_ctx.lock);
dma_fence_end_signalling(cookie);
list_for_each_entry_safe(job, job_tmp, &done_jobs, node) {
@@ -3346,9 +3359,8 @@ queue_run_job(struct drm_sched_job *sched_job)
job->ringbuf.end = job->ringbuf.start + (instrs.count * sizeof(u64));
panthor_job_get(&job->base);
spin_lock(&queue->fence_ctx.lock);
list_add_tail(&job->node, &queue->fence_ctx.in_flight_jobs);
spin_unlock(&queue->fence_ctx.lock);
scoped_guard(spinlock_irqsave, &queue->fence_ctx.lock)
list_add_tail(&job->node, &queue->fence_ctx.in_flight_jobs);
/* Make sure the ring buffer is updated before the INSERT
* register.

View File

@@ -897,7 +897,8 @@ static int virtio_get_edid_block(void *data, u8 *buf,
struct virtio_gpu_resp_edid *resp = data;
size_t start = block * EDID_LENGTH;
if (start + len > le32_to_cpu(resp->size))
if (start + len > le32_to_cpu(resp->size) ||
start + len > sizeof(resp->edid))
return -EINVAL;
memcpy(buf, resp->edid + start, len);
return 0;

View File

@@ -48,7 +48,8 @@ static int xe_display_bo_framebuffer_init(struct drm_gem_object *obj,
if (ret)
goto err;
if (!(bo->flags & XE_BO_FLAG_FORCE_WC)) {
if (!(bo->flags & XE_BO_FLAG_FORCE_WC) &&
bo->ttm.type != ttm_bo_type_sg) {
/*
* XE_BO_FLAG_FORCE_WC should ideally be set at creation, or is
* automatically set when creating FB. We cannot change caching

View File

@@ -331,7 +331,8 @@ static struct i915_vma *__xe_pin_fb_vma(struct drm_gem_object *obj, bool is_dpt,
int ret = 0;
/* We reject creating !SCANOUT fb's, so this is weird.. */
drm_WARN_ON(bo->ttm.base.dev, !(bo->flags & XE_BO_FLAG_FORCE_WC));
drm_WARN_ON(bo->ttm.base.dev, !(bo->flags & XE_BO_FLAG_FORCE_WC) &&
bo->ttm.type != ttm_bo_type_sg);
if (!vma)
return ERR_PTR(-ENODEV);

View File

@@ -54,13 +54,13 @@ struct rtp_to_sr_test_case {
unsigned long expected_count_sr_entries;
unsigned int expected_sr_errors;
unsigned long expected_active;
const struct xe_rtp_entry_sr *entries;
const struct xe_rtp_table_sr table;
};
struct rtp_test_case {
const char *name;
unsigned long expected_active;
const struct xe_rtp_entry *entries;
const struct xe_rtp_table table;
};
static bool fake_xe_gt_mcr_check_reg(struct xe_gt *gt, struct xe_reg reg)
@@ -289,7 +289,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0) | BIT(1),
.expected_count_sr_entries = 1,
/* Different bits on the same register: create a single entry */
.entries = (const struct xe_rtp_entry_sr[]) {
.table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("basic-1"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
@@ -298,8 +298,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))
},
{}
},
),
},
{
.name = "no-match-no-add",
@@ -309,7 +308,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0),
.expected_count_sr_entries = 1,
/* Don't coalesce second entry since rules don't match */
.entries = (const struct xe_rtp_entry_sr[]) {
.table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("basic-1"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
@@ -318,8 +317,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
XE_RTP_RULES(FUNC(match_no)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(1)))
},
{}
},
),
},
{
.name = "two-regs-two-entries",
@@ -329,7 +327,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0) | BIT(1),
.expected_count_sr_entries = 2,
/* Same bits on different registers are not coalesced */
.entries = (const struct xe_rtp_entry_sr[]) {
.table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("basic-1"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
@@ -338,8 +336,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG2, REG_BIT(0)))
},
{}
},
),
},
{
.name = "clr-one-set-other",
@@ -349,7 +346,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0) | BIT(1),
.expected_count_sr_entries = 1,
/* Check clr vs set actions on different bits */
.entries = (const struct xe_rtp_entry_sr[]) {
.table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("basic-1"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
@@ -358,8 +355,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(CLR(REGULAR_REG1, REG_BIT(1)))
},
{}
},
),
},
{
#define TEMP_MASK REG_GENMASK(10, 8)
@@ -371,14 +367,13 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0),
.expected_count_sr_entries = 1,
/* Check FIELD_SET works */
.entries = (const struct xe_rtp_entry_sr[]) {
.table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("basic-1"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(FIELD_SET(REGULAR_REG1,
TEMP_MASK, TEMP_FIELD))
},
{}
},
),
#undef TEMP_MASK
#undef TEMP_FIELD
},
@@ -390,7 +385,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0) | BIT(1),
.expected_count_sr_entries = 1,
.expected_sr_errors = 1,
.entries = (const struct xe_rtp_entry_sr[]) {
.table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("basic-1"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
@@ -400,8 +395,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
},
{}
},
),
},
{
.name = "conflict-not-disjoint",
@@ -411,7 +405,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0) | BIT(1),
.expected_count_sr_entries = 1,
.expected_sr_errors = 1,
.entries = (const struct xe_rtp_entry_sr[]) {
.table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("basic-1"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
@@ -421,8 +415,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(CLR(REGULAR_REG1, REG_GENMASK(1, 0)))
},
{}
},
),
},
{
.name = "conflict-reg-type",
@@ -432,7 +425,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0) | BIT(1) | BIT(2),
.expected_count_sr_entries = 1,
.expected_sr_errors = 2,
.entries = (const struct xe_rtp_entry_sr[]) {
.table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("basic-1"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(REGULAR_REG1, REG_BIT(0)))
@@ -447,8 +440,7 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(MASKED_REG1, REG_BIT(0)))
},
{}
},
),
},
{
.name = "bad-mcr-reg-forced-to-regular",
@@ -458,13 +450,12 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0),
.expected_count_sr_entries = 1,
.expected_sr_errors = 1,
.entries = (const struct xe_rtp_entry_sr[]) {
.table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("bad-mcr-regular-reg"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(BAD_MCR_REG4, REG_BIT(0)))
},
{}
},
),
},
{
.name = "bad-regular-reg-forced-to-mcr",
@@ -474,13 +465,12 @@ static const struct rtp_to_sr_test_case rtp_to_sr_cases[] = {
.expected_active = BIT(0),
.expected_count_sr_entries = 1,
.expected_sr_errors = 1,
.entries = (const struct xe_rtp_entry_sr[]) {
.table = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("bad-regular-reg"),
XE_RTP_RULES(FUNC(match_yes)),
XE_RTP_ACTIONS(SET(BAD_REGULAR_REG5, REG_BIT(0)))
},
{}
},
),
},
};
@@ -492,16 +482,12 @@ static void xe_rtp_process_to_sr_tests(struct kunit *test)
struct xe_reg_sr *reg_sr = &gt->reg_sr;
const struct xe_reg_sr_entry *sre, *sr_entry = NULL;
struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(gt);
unsigned long idx, count_sr_entries = 0, count_rtp_entries = 0, active = 0;
unsigned long idx, count_sr_entries = 0, active = 0;
xe_reg_sr_init(reg_sr, "xe_rtp_to_sr_tests", xe);
while (param->entries[count_rtp_entries].rules)
count_rtp_entries++;
xe_rtp_process_ctx_enable_active_tracking(&ctx, &active, count_rtp_entries);
xe_rtp_process_to_sr(&ctx, param->entries, count_rtp_entries,
reg_sr, false);
xe_rtp_process_ctx_enable_active_tracking(&ctx, &active, param->table.n_entries);
xe_rtp_process_to_sr(&ctx, &param->table, reg_sr, false);
xa_for_each(&reg_sr->xa, idx, sre) {
if (idx == param->expected_reg.addr)
@@ -534,56 +520,52 @@ static const struct rtp_test_case rtp_cases[] = {
{
.name = "active1",
.expected_active = BIT(0),
.entries = (const struct xe_rtp_entry[]) {
.table = XE_RTP_TABLE(
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_yes)),
},
{}
},
),
},
{
.name = "active2",
.expected_active = BIT(0) | BIT(1),
.entries = (const struct xe_rtp_entry[]) {
.table = XE_RTP_TABLE(
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_yes)),
},
{ XE_RTP_NAME("r2"),
XE_RTP_RULES(FUNC(match_yes)),
},
{}
},
),
},
{
.name = "active-inactive",
.expected_active = BIT(0),
.entries = (const struct xe_rtp_entry[]) {
.table = XE_RTP_TABLE(
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_yes)),
},
{ XE_RTP_NAME("r2"),
XE_RTP_RULES(FUNC(match_no)),
},
{}
},
),
},
{
.name = "inactive-active",
.expected_active = BIT(1),
.entries = (const struct xe_rtp_entry[]) {
.table = XE_RTP_TABLE(
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_no)),
},
{ XE_RTP_NAME("r2"),
XE_RTP_RULES(FUNC(match_yes)),
},
{}
},
),
},
{
.name = "inactive-active-inactive",
.expected_active = BIT(1),
.entries = (const struct xe_rtp_entry[]) {
.table = XE_RTP_TABLE(
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_no)),
},
@@ -593,13 +575,12 @@ static const struct rtp_test_case rtp_cases[] = {
{ XE_RTP_NAME("r3"),
XE_RTP_RULES(FUNC(match_no)),
},
{}
},
),
},
{
.name = "inactive-inactive-inactive",
.expected_active = 0,
.entries = (const struct xe_rtp_entry[]) {
.table = XE_RTP_TABLE(
{ XE_RTP_NAME("r1"),
XE_RTP_RULES(FUNC(match_no)),
},
@@ -609,8 +590,7 @@ static const struct rtp_test_case rtp_cases[] = {
{ XE_RTP_NAME("r3"),
XE_RTP_RULES(FUNC(match_no)),
},
{}
},
),
},
};
@@ -620,13 +600,10 @@ static void xe_rtp_process_tests(struct kunit *test)
struct xe_device *xe = test->priv;
struct xe_gt *gt = xe_device_get_root_tile(xe)->primary_gt;
struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(gt);
unsigned long count_rtp_entries = 0, active = 0;
unsigned long active = 0;
while (param->entries[count_rtp_entries].rules)
count_rtp_entries++;
xe_rtp_process_ctx_enable_active_tracking(&ctx, &active, count_rtp_entries);
xe_rtp_process(&ctx, param->entries);
xe_rtp_process_ctx_enable_active_tracking(&ctx, &active, param->table.n_entries);
xe_rtp_process(&ctx, &param->table);
KUNIT_EXPECT_EQ(test, active, param->expected_active);
}

View File

@@ -168,10 +168,20 @@ static void bo_meminfo(struct xe_bo *bo,
struct drm_memory_stats stats[TTM_NUM_MEM_TYPES])
{
u64 sz = xe_bo_size(bo);
u32 mem_type = bo->ttm.resource->mem_type;
u32 mem_type;
xe_bo_assert_held(bo);
/*
* The resource can be NULL if the BO has been purged, plus maybe some
* other cases. Either way there shouldn't be any memory to account for,
* or a current resource to account this against, so skip for now.
*/
if (!bo->ttm.resource)
return;
mem_type = bo->ttm.resource->mem_type;
if (drm_gem_object_is_shared_for_memory_stats(&bo->ttm.base))
stats[mem_type].shared += sz;
else

View File

@@ -149,8 +149,10 @@ static int register_save_restore(struct xe_gt *gt, struct drm_printer *p)
drm_printf(p, "\n");
drm_printf(p, "Whitelist\n");
for_each_hw_engine(hwe, gt, id)
for_each_hw_engine(hwe, gt, id) {
xe_reg_whitelist_dump(&hwe->reg_whitelist, p);
xe_reg_whitelist_dump(&hwe->oa_whitelist, p);
}
return 0;
}

View File

@@ -689,12 +689,17 @@ static int relay_action_handler(struct xe_guc_relay *relay, u32 origin,
return relay_testloop_action_handler(relay, origin, msg, len, response, size);
type = FIELD_GET(GUC_HXG_MSG_0_TYPE, msg[0]);
relay_assert(relay, guc_hxg_type_is_action(type));
if (IS_SRIOV_PF(relay_to_xe(relay)))
ret = xe_gt_sriov_pf_service_process_request(gt, origin, msg, len, response, size);
else
if (IS_SRIOV_PF(relay_to_xe(relay))) {
if (type == GUC_HXG_TYPE_REQUEST)
ret = xe_gt_sriov_pf_service_process_request(gt, origin, msg, len,
response, size);
else
ret = -EOPNOTSUPP;
} else {
ret = -EOPNOTSUPP;
}
if (type == GUC_HXG_TYPE_EVENT)
relay_assert(relay, ret <= 0);

View File

@@ -1163,7 +1163,7 @@ static void submit_exec_queue(struct xe_exec_queue *q, struct xe_sched_job *job)
if (exec_queue_suspended(q))
return;
if (!exec_queue_enabled(q) && !exec_queue_suspended(q)) {
if (!exec_queue_enabled(q)) {
action[len++] = XE_GUC_ACTION_SCHED_CONTEXT_MODE_SET;
action[len++] = q->guc->id;
action[len++] = GUC_CONTEXT_ENABLE;
@@ -1493,7 +1493,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
struct xe_device *xe = guc_to_xe(guc);
int err = -ETIME;
pid_t pid = -1;
bool wedged = false, skip_timeout_check;
bool wedged = false, wedge_device = false, skip_timeout_check;
xe_gt_assert(guc_to_gt(guc), !exec_queue_destroyed(q));
@@ -1638,7 +1638,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
}
if (q->flags & EXEC_QUEUE_FLAG_KERNEL) {
xe_gt_WARN(q->gt, true, "Kernel-submitted job timed out\n");
xe_device_declare_wedged(gt_to_xe(q->gt));
wedge_device = true;
}
} else if (q->flags & EXEC_QUEUE_FLAG_VM && !exec_queue_killed(q)) {
xe_gt_WARN(q->gt, true, "VM job timed out on non-killed execqueue\n");
@@ -1658,6 +1658,9 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
xe_guc_exec_queue_trigger_cleanup(q);
}
if (wedge_device)
xe_device_declare_wedged(gt_to_xe(q->gt));
/*
* We want the job added back to the pending list so it gets freed; this
* is what DRM_GPU_SCHED_STAT_NO_HANG does.

View File

@@ -346,7 +346,7 @@ hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe)
u32 blit_cctl_val = REG_FIELD_PREP(BLIT_CCTL_DST_MOCS_MASK, mocs_write_idx) |
REG_FIELD_PREP(BLIT_CCTL_SRC_MOCS_MASK, mocs_read_idx);
struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(hwe);
const struct xe_rtp_entry_sr lrc_setup[] = {
const struct xe_rtp_table_sr lrc_setup = XE_RTP_TABLE_SR(
/*
* Some blitter commands do not have a field for MOCS, those
* commands will use MOCS index pointed by BLIT_CCTL.
@@ -369,10 +369,9 @@ hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe)
PREEMPT_GPGPU_THREAD_GROUP_LEVEL)),
XE_RTP_ENTRY_FLAG(FOREACH_ENGINE)
},
};
);
xe_rtp_process_to_sr(&ctx, lrc_setup, ARRAY_SIZE(lrc_setup),
&hwe->reg_lrc, true);
xe_rtp_process_to_sr(&ctx, &lrc_setup, &hwe->reg_lrc, true);
}
void xe_hw_engine_setup_reg_lrc(struct xe_hw_engine *hwe)
@@ -408,7 +407,7 @@ hw_engine_setup_default_state(struct xe_hw_engine *hwe)
u32 ring_cmd_cctl_val = REG_FIELD_PREP(CMD_CCTL_WRITE_OVERRIDE_MASK, mocs_write_idx) |
REG_FIELD_PREP(CMD_CCTL_READ_OVERRIDE_MASK, mocs_read_idx);
struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(hwe);
const struct xe_rtp_entry_sr engine_entries[] = {
const struct xe_rtp_table_sr engine_sr = XE_RTP_TABLE_SR(
{ XE_RTP_NAME("RING_CMD_CCTL_default_MOCS"),
XE_RTP_RULES(FUNC(xe_rtp_match_always)),
XE_RTP_ACTIONS(FIELD_SET(RING_CMD_CCTL(0),
@@ -465,10 +464,9 @@ hw_engine_setup_default_state(struct xe_hw_engine *hwe)
XE_RTP_ACTIONS(SET(GFX_MODE(0), GFX_MSIX_INTERRUPT_ENABLE,
XE_RTP_ACTION_FLAG(ENGINE_BASE)))
},
};
);
xe_rtp_process_to_sr(&ctx, engine_entries, ARRAY_SIZE(engine_entries),
&hwe->reg_sr, false);
xe_rtp_process_to_sr(&ctx, &engine_sr, &hwe->reg_sr, false);
}
static const struct engine_info *find_engine_info(enum xe_engine_class class, int instance)
@@ -574,6 +572,8 @@ static void hw_engine_init_early(struct xe_gt *gt, struct xe_hw_engine *hwe,
hw_engine_setup_default_state(hwe);
xe_reg_sr_init(&hwe->reg_whitelist, hwe->name, gt_to_xe(gt));
xe_reg_sr_init(&hwe->oa_whitelist, hwe->name, gt_to_xe(gt));
xe_reg_sr_init(&hwe->oa_sr, hwe->name, gt_to_xe(gt));
xe_reg_whitelist_process_engine(hwe);
}
@@ -628,7 +628,7 @@ static int hw_engine_init(struct xe_gt *gt, struct xe_hw_engine *hwe,
hwe->exl_port = xe_execlist_port_create(xe, hwe);
if (IS_ERR(hwe->exl_port)) {
err = PTR_ERR(hwe->exl_port);
goto err_hwsp;
goto err_name;
}
} else {
/* GSCCS has a special interrupt for reset */
@@ -648,8 +648,6 @@ static int hw_engine_init(struct xe_gt *gt, struct xe_hw_engine *hwe,
return devm_add_action_or_reset(xe->drm.dev, hw_engine_fini, hwe);
err_hwsp:
xe_bo_unpin_map_no_vm(hwe->hwsp);
err_name:
hwe->name = NULL;

View File

@@ -130,6 +130,14 @@ struct xe_hw_engine {
* @reg_whitelist: table with registers to be whitelisted
*/
struct xe_reg_sr reg_whitelist;
/**
* @oa_whitelist: oa registers to be whitelisted
*/
struct xe_reg_sr oa_whitelist;
/**
* @oa_sr: oa nonpriv whitelist registers, changed on oa stream open/close
*/
struct xe_reg_sr oa_sr;
/**
* @reg_lrc: LRC workaround registers
*/

View File

@@ -37,6 +37,7 @@
#include "xe_oa.h"
#include "xe_observation.h"
#include "xe_pm.h"
#include "xe_reg_whitelist.h"
#include "xe_sched_job.h"
#include "xe_sriov.h"
#include "xe_sync.h"
@@ -885,6 +886,9 @@ static void xe_oa_stream_destroy(struct xe_oa_stream *stream)
mutex_destroy(&stream->stream_lock);
if (stream->sample)
xe_reg_dewhitelist_oa_regs(stream->gt);
xe_oa_disable_metric_set(stream);
xe_exec_queue_put(stream->k_exec_q);
@@ -1885,6 +1889,9 @@ static int xe_oa_stream_open_ioctl_locked(struct xe_oa *oa,
goto err_disable;
}
if (stream->sample)
xe_reg_whitelist_oa_regs(stream->gt);
/* Hold a reference on the drm device till stream_fd is released */
drm_dev_get(&stream->oa->xe->drm);

Some files were not shown because too many files have changed in this diff Show More