drm fixes for 7.0-rc2

i915/display:
 - Fix Panel Replay stuck with X during mode transitions on Panther Lake
 
 xe:
 - W/a fix for multi-cast registers
 - Fix xe_sync initialization issues
 
 amdgpu:
 - UserQ fixes
 - DC fix
 - RAS fixes
 - VCN 5 fix
 - Slot reset fix
 - Remove MES workaround that's no longer needed
 
 amdxdna:
 - deadlock fix
 - NULL ptr deref fix
 - suspend failure fix
 - OOB access fix
 - buffer overflow fix
 - input sanitiation fix
 - firmware loading fix
 
 dw-dp:
 - An error handling fix
 
 ethosu:
 - A binary shift overflow fix
 
 imx:
 - An error handling fix
 
 logicvc:
 - A dt node reference leak fix
 
 nouveau:
 - A WARN_ON removal
 
 samsung-dsim:
 - A memory leak fix
 
 tiny:
 - sharp-memory: NULL pointer deref fix
 
 vmwgfx:
 - A reference count and error handling fix
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmmhNZoACgkQDHTzWXnE
 hr4F0hAAoc+Lbq0tePa+I6Pf6Yjq/ufzqBSWvEjN+5mXjBuY2oUytpGrGzqASczr
 03Q6zGVFzdXA5mJtRPxlhUVUn/SVbTGauTHs5wzZejiylw2+xngGAt81kIFab4km
 y2BLkOOCn96JhE/VqjrisydfwwXQD4TAbzpF12EZ4t+zyqmuEnuJ9TDTLcFDrOxn
 WfOY5neXtmntHavZ14IqghQNPUcj0x8KLC65BldNUfLdhnk5JwdsqdLwrID80fYW
 OBPGW1g1/4Ee4AKv+aKUB+1dm3fQGWh1K9C4Xh6g+OWIhn30Oo7BnTbu6N15GPN6
 rle+t5jnxkxhNcxEQNA8l1WJgexBJz4wKixwf7XwrF21OMom+QhS9hboCwhunQt6
 BTtw5HJubFXHRgEnTXiMeTLgW80TppDUjt5nEsy5CzP+5G8gqi1Xh3qMF0SjJHki
 Spxvt7Fh0qxHctzecOJi5aqVq2PiTeKNihI7OfZ5604OLlhbZE2WL556upJRLMz+
 u5CrdB3gCJ5aSNQyi3bP0Rg25jE8/mobdWJSgn3n2Z8v/XKdFX+s7cxyZiyTBEYu
 aQuQAfVOh5l1VT1ydQ0tki/sHyZ2cWDTukKHR7li8rJPC0kkZc28IE8T2YML8+A8
 1zgKhVHnTKoa/ngmTvmhBAfKaoLr+wgf646JGTllDw1z8hk5+3k=
 =/AzA
 -----END PGP SIGNATURE-----

Merge tag 'drm-fixes-2026-02-27' of https://gitlab.freedesktop.org/drm/kernel

Pull drm fixes from Dave Airlie:
 "Regular fixes pull, amdxdna and amdgpu are the main ones, with a
  couple of intel fixes, then a scattering of fixes across drivers,
  nothing too major.

  i915/display:
   - Fix Panel Replay stuck with X during mode transitions on Panther
     Lake

  xe:
   - W/a fix for multi-cast registers
   - Fix xe_sync initialization issues

  amdgpu:
   - UserQ fixes
   - DC fix
   - RAS fixes
   - VCN 5 fix
   - Slot reset fix
   - Remove MES workaround that's no longer needed

  amdxdna:
   - deadlock fix
   - NULL ptr deref fix
   - suspend failure fix
   - OOB access fix
   - buffer overflow fix
   - input sanitiation fix
   - firmware loading fix

  dw-dp:
   - An error handling fix

  ethosu:
   - A binary shift overflow fix

  imx:
   - An error handling fix

  logicvc:
   - A dt node reference leak fix

  nouveau:
   - A WARN_ON removal

  samsung-dsim:
   - A memory leak fix

  tiny:
   - sharp-memory: NULL pointer deref fix

  vmwgfx:
   - A reference count and error handling fix"

* tag 'drm-fixes-2026-02-27' of https://gitlab.freedesktop.org/drm/kernel: (39 commits)
  drm/amd: Disable MES LR compute W/A
  drm/amdgpu: Fix error handling in slot reset
  drm/amdgpu/vcn5: Add SMU dpm interface type
  drm/amdgpu: Fix locking bugs in error paths
  drm/amdgpu: Unlock a mutex before destroying it
  drm/amd/display: Use GFP_ATOMIC in dc_create_stream_for_sink
  drm/amdgpu: add upper bound check on user inputs in wait ioctl
  drm/amdgpu: add upper bound check on user inputs in signal ioctl
  drm/amdgpu/userq: Do not allow userspace to trivially triger kernel warnings
  drm/amdgpu/userq: Fix reference leak in amdgpu_userq_wait_ioctl
  accel/amdxdna: Use a different name for latest firmware
  drm/client: Do not destroy NULL modes
  drm/gpusvm: Fix drm_gpusvm_pages_valid_unlocked() kernel-doc
  drm/xe/sync: Fix user fence leak on alloc failure
  drm/xe/sync: Cleanup partially initialized sync on parse failure
  drm/xe/wa: Steer RMW of MCR registers while building default LRC
  accel/amdxdna: Validate command buffer payload count
  accel/amdxdna: Prevent ubuf size overflow
  accel/amdxdna: Fix out-of-bounds memset in command slot handling
  accel/amdxdna: Fix command hang on suspended hardware context
  ...
This commit is contained in:
Linus Torvalds 2026-02-27 08:56:07 -08:00
commit 466d6175e3
40 changed files with 300 additions and 161 deletions

View file

@ -23,9 +23,9 @@
#include "amdxdna_pci_drv.h"
#include "amdxdna_pm.h"
static bool force_cmdlist;
static bool force_cmdlist = true;
module_param(force_cmdlist, bool, 0600);
MODULE_PARM_DESC(force_cmdlist, "Force use command list (Default false)");
MODULE_PARM_DESC(force_cmdlist, "Force use command list (Default true)");
#define HWCTX_MAX_TIMEOUT 60000 /* milliseconds */
@ -53,6 +53,7 @@ static void aie2_hwctx_stop(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hwct
{
drm_sched_stop(&hwctx->priv->sched, bad_job);
aie2_destroy_context(xdna->dev_handle, hwctx);
drm_sched_start(&hwctx->priv->sched, 0);
}
static int aie2_hwctx_restart(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hwctx)
@ -80,7 +81,6 @@ static int aie2_hwctx_restart(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hw
}
out:
drm_sched_start(&hwctx->priv->sched, 0);
XDNA_DBG(xdna, "%s restarted, ret %d", hwctx->name, ret);
return ret;
}
@ -297,19 +297,23 @@ aie2_sched_job_run(struct drm_sched_job *sched_job)
struct dma_fence *fence;
int ret;
if (!hwctx->priv->mbox_chann)
ret = amdxdna_pm_resume_get(hwctx->client->xdna);
if (ret)
return NULL;
if (!mmget_not_zero(job->mm))
if (!hwctx->priv->mbox_chann) {
amdxdna_pm_suspend_put(hwctx->client->xdna);
return NULL;
}
if (!mmget_not_zero(job->mm)) {
amdxdna_pm_suspend_put(hwctx->client->xdna);
return ERR_PTR(-ESRCH);
}
kref_get(&job->refcnt);
fence = dma_fence_get(job->fence);
ret = amdxdna_pm_resume_get(hwctx->client->xdna);
if (ret)
goto out;
if (job->drv_cmd) {
switch (job->drv_cmd->opcode) {
case SYNC_DEBUG_BO:
@ -497,7 +501,7 @@ static void aie2_release_resource(struct amdxdna_hwctx *hwctx)
if (AIE2_FEATURE_ON(xdna->dev_handle, AIE2_TEMPORAL_ONLY)) {
ret = aie2_destroy_context(xdna->dev_handle, hwctx);
if (ret)
if (ret && ret != -ENODEV)
XDNA_ERR(xdna, "Destroy temporal only context failed, ret %d", ret);
} else {
ret = xrs_release_resource(xdna->xrs_hdl, (uintptr_t)hwctx);
@ -629,7 +633,7 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
goto free_entity;
}
ret = amdxdna_pm_resume_get(xdna);
ret = amdxdna_pm_resume_get_locked(xdna);
if (ret)
goto free_col_list;
@ -760,7 +764,7 @@ static int aie2_hwctx_cu_config(struct amdxdna_hwctx *hwctx, void *buf, u32 size
if (!hwctx->cus)
return -ENOMEM;
ret = amdxdna_pm_resume_get(xdna);
ret = amdxdna_pm_resume_get_locked(xdna);
if (ret)
goto free_cus;
@ -1070,6 +1074,8 @@ void aie2_hmm_invalidate(struct amdxdna_gem_obj *abo,
ret = dma_resv_wait_timeout(gobj->resv, DMA_RESV_USAGE_BOOKKEEP,
true, MAX_SCHEDULE_TIMEOUT);
if (!ret || ret == -ERESTARTSYS)
if (!ret)
XDNA_ERR(xdna, "Failed to wait for bo, ret %ld", ret);
else if (ret == -ERESTARTSYS)
XDNA_DBG(xdna, "Wait for bo interrupted by signal");
}

View file

@ -216,8 +216,10 @@ static int aie2_destroy_context_req(struct amdxdna_dev_hdl *ndev, u32 id)
req.context_id = id;
ret = aie2_send_mgmt_msg_wait(ndev, &msg);
if (ret)
if (ret && ret != -ENODEV)
XDNA_WARN(xdna, "Destroy context failed, ret %d", ret);
else if (ret == -ENODEV)
XDNA_DBG(xdna, "Destroy context: device already stopped");
return ret;
}
@ -318,6 +320,9 @@ int aie2_destroy_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwc
struct amdxdna_dev *xdna = ndev->xdna;
int ret;
if (!hwctx->priv->mbox_chann)
return 0;
xdna_mailbox_stop_channel(hwctx->priv->mbox_chann);
ret = aie2_destroy_context_req(ndev, hwctx->fw_ctx_id);
xdna_mailbox_destroy_channel(hwctx->priv->mbox_chann);
@ -694,11 +699,11 @@ aie2_cmdlist_fill_npu_cf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *siz
u32 cmd_len;
void *cmd;
memset(npu_slot, 0, sizeof(*npu_slot));
cmd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
if (*size < sizeof(*npu_slot) + cmd_len)
return -EINVAL;
memset(npu_slot, 0, sizeof(*npu_slot));
npu_slot->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
if (npu_slot->cu_idx == INVALID_CU_IDX)
return -EINVAL;
@ -719,7 +724,6 @@ aie2_cmdlist_fill_npu_dpu(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si
u32 cmd_len;
u32 arg_sz;
memset(npu_slot, 0, sizeof(*npu_slot));
sn = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
arg_sz = cmd_len - sizeof(*sn);
if (cmd_len < sizeof(*sn) || arg_sz > MAX_NPU_ARGS_SIZE)
@ -728,6 +732,7 @@ aie2_cmdlist_fill_npu_dpu(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si
if (*size < sizeof(*npu_slot) + arg_sz)
return -EINVAL;
memset(npu_slot, 0, sizeof(*npu_slot));
npu_slot->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
if (npu_slot->cu_idx == INVALID_CU_IDX)
return -EINVAL;
@ -751,7 +756,6 @@ aie2_cmdlist_fill_npu_preempt(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t
u32 cmd_len;
u32 arg_sz;
memset(npu_slot, 0, sizeof(*npu_slot));
pd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
arg_sz = cmd_len - sizeof(*pd);
if (cmd_len < sizeof(*pd) || arg_sz > MAX_NPU_ARGS_SIZE)
@ -760,6 +764,7 @@ aie2_cmdlist_fill_npu_preempt(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t
if (*size < sizeof(*npu_slot) + arg_sz)
return -EINVAL;
memset(npu_slot, 0, sizeof(*npu_slot));
npu_slot->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
if (npu_slot->cu_idx == INVALID_CU_IDX)
return -EINVAL;
@ -787,7 +792,6 @@ aie2_cmdlist_fill_npu_elf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si
u32 cmd_len;
u32 arg_sz;
memset(npu_slot, 0, sizeof(*npu_slot));
pd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
arg_sz = cmd_len - sizeof(*pd);
if (cmd_len < sizeof(*pd) || arg_sz > MAX_NPU_ARGS_SIZE)
@ -796,6 +800,7 @@ aie2_cmdlist_fill_npu_elf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si
if (*size < sizeof(*npu_slot) + arg_sz)
return -EINVAL;
memset(npu_slot, 0, sizeof(*npu_slot));
npu_slot->type = EXEC_NPU_TYPE_ELF;
npu_slot->inst_buf_addr = pd->inst_buf;
npu_slot->save_buf_addr = pd->save_buf;

View file

@ -32,6 +32,11 @@ static int aie2_max_col = XRS_MAX_COL;
module_param(aie2_max_col, uint, 0600);
MODULE_PARM_DESC(aie2_max_col, "Maximum column could be used");
static char *npu_fw[] = {
"npu_7.sbin",
"npu.sbin"
};
/*
* The management mailbox channel is allocated by firmware.
* The related register and ring buffer information is on SRAM BAR.
@ -323,6 +328,7 @@ static void aie2_hw_stop(struct amdxdna_dev *xdna)
return;
}
aie2_runtime_cfg(ndev, AIE2_RT_CFG_CLK_GATING, NULL);
aie2_mgmt_fw_fini(ndev);
xdna_mailbox_stop_channel(ndev->mgmt_chann);
xdna_mailbox_destroy_channel(ndev->mgmt_chann);
@ -406,18 +412,18 @@ static int aie2_hw_start(struct amdxdna_dev *xdna)
goto stop_psp;
}
ret = aie2_pm_init(ndev);
if (ret) {
XDNA_ERR(xdna, "failed to init pm, ret %d", ret);
goto destroy_mgmt_chann;
}
ret = aie2_mgmt_fw_init(ndev);
if (ret) {
XDNA_ERR(xdna, "initial mgmt firmware failed, ret %d", ret);
goto destroy_mgmt_chann;
}
ret = aie2_pm_init(ndev);
if (ret) {
XDNA_ERR(xdna, "failed to init pm, ret %d", ret);
goto destroy_mgmt_chann;
}
ret = aie2_mgmt_fw_query(ndev);
if (ret) {
XDNA_ERR(xdna, "failed to query fw, ret %d", ret);
@ -451,7 +457,6 @@ static int aie2_hw_suspend(struct amdxdna_dev *xdna)
{
struct amdxdna_client *client;
guard(mutex)(&xdna->dev_lock);
list_for_each_entry(client, &xdna->client_list, node)
aie2_hwctx_suspend(client);
@ -489,6 +494,7 @@ static int aie2_init(struct amdxdna_dev *xdna)
struct psp_config psp_conf;
const struct firmware *fw;
unsigned long bars = 0;
char *fw_full_path;
int i, nvec, ret;
if (!hypervisor_is_type(X86_HYPER_NATIVE)) {
@ -503,7 +509,19 @@ static int aie2_init(struct amdxdna_dev *xdna)
ndev->priv = xdna->dev_info->dev_priv;
ndev->xdna = xdna;
ret = request_firmware(&fw, ndev->priv->fw_path, &pdev->dev);
for (i = 0; i < ARRAY_SIZE(npu_fw); i++) {
fw_full_path = kasprintf(GFP_KERNEL, "%s%s", ndev->priv->fw_path, npu_fw[i]);
if (!fw_full_path)
return -ENOMEM;
ret = firmware_request_nowarn(&fw, fw_full_path, &pdev->dev);
kfree(fw_full_path);
if (!ret) {
XDNA_INFO(xdna, "Load firmware %s%s", ndev->priv->fw_path, npu_fw[i]);
break;
}
}
if (ret) {
XDNA_ERR(xdna, "failed to request_firmware %s, ret %d",
ndev->priv->fw_path, ret);
@ -951,7 +969,7 @@ static int aie2_get_info(struct amdxdna_client *client, struct amdxdna_drm_get_i
if (!drm_dev_enter(&xdna->ddev, &idx))
return -ENODEV;
ret = amdxdna_pm_resume_get(xdna);
ret = amdxdna_pm_resume_get_locked(xdna);
if (ret)
goto dev_exit;
@ -1044,7 +1062,7 @@ static int aie2_get_array(struct amdxdna_client *client,
if (!drm_dev_enter(&xdna->ddev, &idx))
return -ENODEV;
ret = amdxdna_pm_resume_get(xdna);
ret = amdxdna_pm_resume_get_locked(xdna);
if (ret)
goto dev_exit;
@ -1134,7 +1152,7 @@ static int aie2_set_state(struct amdxdna_client *client,
if (!drm_dev_enter(&xdna->ddev, &idx))
return -ENODEV;
ret = amdxdna_pm_resume_get(xdna);
ret = amdxdna_pm_resume_get_locked(xdna);
if (ret)
goto dev_exit;

View file

@ -31,7 +31,7 @@ int aie2_pm_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level)
{
int ret;
ret = amdxdna_pm_resume_get(ndev->xdna);
ret = amdxdna_pm_resume_get_locked(ndev->xdna);
if (ret)
return ret;

View file

@ -104,7 +104,10 @@ void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size)
if (size) {
count = FIELD_GET(AMDXDNA_CMD_COUNT, cmd->header);
if (unlikely(count <= num_masks)) {
if (unlikely(count <= num_masks ||
count * sizeof(u32) +
offsetof(struct amdxdna_cmd, data[0]) >
abo->mem.size)) {
*size = 0;
return NULL;
}
@ -266,9 +269,9 @@ int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct dr
struct amdxdna_drm_config_hwctx *args = data;
struct amdxdna_dev *xdna = to_xdna_dev(dev);
struct amdxdna_hwctx *hwctx;
int ret, idx;
u32 buf_size;
void *buf;
int ret;
u64 val;
if (XDNA_MBZ_DBG(xdna, &args->pad, sizeof(args->pad)))
@ -310,20 +313,17 @@ int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct dr
return -EINVAL;
}
mutex_lock(&xdna->dev_lock);
idx = srcu_read_lock(&client->hwctx_srcu);
guard(mutex)(&xdna->dev_lock);
hwctx = xa_load(&client->hwctx_xa, args->handle);
if (!hwctx) {
XDNA_DBG(xdna, "PID %d failed to get hwctx %d", client->pid, args->handle);
ret = -EINVAL;
goto unlock_srcu;
goto free_buf;
}
ret = xdna->dev_info->ops->hwctx_config(hwctx, args->param_type, val, buf, buf_size);
unlock_srcu:
srcu_read_unlock(&client->hwctx_srcu, idx);
mutex_unlock(&xdna->dev_lock);
free_buf:
kfree(buf);
return ret;
}
@ -334,7 +334,7 @@ int amdxdna_hwctx_sync_debug_bo(struct amdxdna_client *client, u32 debug_bo_hdl)
struct amdxdna_hwctx *hwctx;
struct amdxdna_gem_obj *abo;
struct drm_gem_object *gobj;
int ret, idx;
int ret;
if (!xdna->dev_info->ops->hwctx_sync_debug_bo)
return -EOPNOTSUPP;
@ -345,17 +345,15 @@ int amdxdna_hwctx_sync_debug_bo(struct amdxdna_client *client, u32 debug_bo_hdl)
abo = to_xdna_obj(gobj);
guard(mutex)(&xdna->dev_lock);
idx = srcu_read_lock(&client->hwctx_srcu);
hwctx = xa_load(&client->hwctx_xa, abo->assigned_hwctx);
if (!hwctx) {
ret = -EINVAL;
goto unlock_srcu;
goto put_obj;
}
ret = xdna->dev_info->ops->hwctx_sync_debug_bo(hwctx, debug_bo_hdl);
unlock_srcu:
srcu_read_unlock(&client->hwctx_srcu, idx);
put_obj:
drm_gem_object_put(gobj);
return ret;
}

View file

@ -21,8 +21,6 @@
#include "amdxdna_pci_drv.h"
#include "amdxdna_ubuf.h"
#define XDNA_MAX_CMD_BO_SIZE SZ_32K
MODULE_IMPORT_NS("DMA_BUF");
static int
@ -745,12 +743,6 @@ amdxdna_drm_create_cmd_bo(struct drm_device *dev,
{
struct amdxdna_dev *xdna = to_xdna_dev(dev);
struct amdxdna_gem_obj *abo;
int ret;
if (args->size > XDNA_MAX_CMD_BO_SIZE) {
XDNA_ERR(xdna, "Command bo size 0x%llx too large", args->size);
return ERR_PTR(-EINVAL);
}
if (args->size < sizeof(struct amdxdna_cmd)) {
XDNA_DBG(xdna, "Command BO size 0x%llx too small", args->size);
@ -764,17 +756,7 @@ amdxdna_drm_create_cmd_bo(struct drm_device *dev,
abo->type = AMDXDNA_BO_CMD;
abo->client = filp->driver_priv;
ret = amdxdna_gem_obj_vmap(abo, &abo->mem.kva);
if (ret) {
XDNA_ERR(xdna, "Vmap cmd bo failed, ret %d", ret);
goto release_obj;
}
return abo;
release_obj:
drm_gem_object_put(to_gobj(abo));
return ERR_PTR(ret);
}
int amdxdna_drm_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
@ -871,6 +853,7 @@ struct amdxdna_gem_obj *amdxdna_gem_get_obj(struct amdxdna_client *client,
struct amdxdna_dev *xdna = client->xdna;
struct amdxdna_gem_obj *abo;
struct drm_gem_object *gobj;
int ret;
gobj = drm_gem_object_lookup(client->filp, bo_hdl);
if (!gobj) {
@ -879,9 +862,26 @@ struct amdxdna_gem_obj *amdxdna_gem_get_obj(struct amdxdna_client *client,
}
abo = to_xdna_obj(gobj);
if (bo_type == AMDXDNA_BO_INVALID || abo->type == bo_type)
if (bo_type != AMDXDNA_BO_INVALID && abo->type != bo_type)
goto put_obj;
if (bo_type != AMDXDNA_BO_CMD || abo->mem.kva)
return abo;
if (abo->mem.size > SZ_32K) {
XDNA_ERR(xdna, "Cmd bo is too big %ld", abo->mem.size);
goto put_obj;
}
ret = amdxdna_gem_obj_vmap(abo, &abo->mem.kva);
if (ret) {
XDNA_ERR(xdna, "Vmap cmd bo failed, ret %d", ret);
goto put_obj;
}
return abo;
put_obj:
drm_gem_object_put(gobj);
return NULL;
}

View file

@ -23,6 +23,9 @@ MODULE_FIRMWARE("amdnpu/1502_00/npu.sbin");
MODULE_FIRMWARE("amdnpu/17f0_10/npu.sbin");
MODULE_FIRMWARE("amdnpu/17f0_11/npu.sbin");
MODULE_FIRMWARE("amdnpu/17f0_20/npu.sbin");
MODULE_FIRMWARE("amdnpu/1502_00/npu_7.sbin");
MODULE_FIRMWARE("amdnpu/17f0_10/npu_7.sbin");
MODULE_FIRMWARE("amdnpu/17f0_11/npu_7.sbin");
/*
* 0.0: Initial version

View file

@ -16,6 +16,7 @@ int amdxdna_pm_suspend(struct device *dev)
struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev));
int ret = -EOPNOTSUPP;
guard(mutex)(&xdna->dev_lock);
if (xdna->dev_info->ops->suspend)
ret = xdna->dev_info->ops->suspend(xdna);
@ -28,6 +29,7 @@ int amdxdna_pm_resume(struct device *dev)
struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev));
int ret = -EOPNOTSUPP;
guard(mutex)(&xdna->dev_lock);
if (xdna->dev_info->ops->resume)
ret = xdna->dev_info->ops->resume(xdna);

View file

@ -15,4 +15,15 @@ void amdxdna_pm_suspend_put(struct amdxdna_dev *xdna);
void amdxdna_pm_init(struct amdxdna_dev *xdna);
void amdxdna_pm_fini(struct amdxdna_dev *xdna);
static inline int amdxdna_pm_resume_get_locked(struct amdxdna_dev *xdna)
{
int ret;
mutex_unlock(&xdna->dev_lock);
ret = amdxdna_pm_resume_get(xdna);
mutex_lock(&xdna->dev_lock);
return ret;
}
#endif /* _AMDXDNA_PM_H_ */

View file

@ -7,6 +7,7 @@
#include <drm/drm_device.h>
#include <drm/drm_print.h>
#include <linux/dma-buf.h>
#include <linux/overflow.h>
#include <linux/pagemap.h>
#include <linux/vmalloc.h>
@ -176,7 +177,10 @@ struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
goto free_ent;
}
exp_info.size += va_ent[i].len;
if (check_add_overflow(exp_info.size, va_ent[i].len, &exp_info.size)) {
ret = -EINVAL;
goto free_ent;
}
}
ubuf->nr_pages = exp_info.size >> PAGE_SHIFT;

View file

@ -72,7 +72,7 @@ static const struct aie2_fw_feature_tbl npu1_fw_feature_table[] = {
};
static const struct amdxdna_dev_priv npu1_dev_priv = {
.fw_path = "amdnpu/1502_00/npu.sbin",
.fw_path = "amdnpu/1502_00/",
.rt_config = npu1_default_rt_cfg,
.dpm_clk_tbl = npu1_dpm_clk_table,
.fw_feature_tbl = npu1_fw_feature_table,

View file

@ -98,7 +98,7 @@ const struct aie2_fw_feature_tbl npu4_fw_feature_table[] = {
};
static const struct amdxdna_dev_priv npu4_dev_priv = {
.fw_path = "amdnpu/17f0_10/npu.sbin",
.fw_path = "amdnpu/17f0_10/",
.rt_config = npu4_default_rt_cfg,
.dpm_clk_tbl = npu4_dpm_clk_table,
.fw_feature_tbl = npu4_fw_feature_table,

View file

@ -63,7 +63,7 @@
#define NPU5_SRAM_BAR_BASE MMNPU_APERTURE1_BASE
static const struct amdxdna_dev_priv npu5_dev_priv = {
.fw_path = "amdnpu/17f0_11/npu.sbin",
.fw_path = "amdnpu/17f0_11/",
.rt_config = npu4_default_rt_cfg,
.dpm_clk_tbl = npu4_dpm_clk_table,
.fw_feature_tbl = npu4_fw_feature_table,

View file

@ -63,7 +63,7 @@
#define NPU6_SRAM_BAR_BASE MMNPU_APERTURE1_BASE
static const struct amdxdna_dev_priv npu6_dev_priv = {
.fw_path = "amdnpu/17f0_10/npu.sbin",
.fw_path = "amdnpu/17f0_10/",
.rt_config = npu4_default_rt_cfg,
.dpm_clk_tbl = npu4_dpm_clk_table,
.fw_feature_tbl = npu4_fw_feature_table,

View file

@ -154,7 +154,7 @@ static void cmd_state_init(struct cmd_state *st)
static u64 cmd_to_addr(u32 *cmd)
{
return ((u64)((cmd[0] & 0xff0000) << 16)) | cmd[1];
return (((u64)cmd[0] & 0xff0000) << 16) | cmd[1];
}
static u64 dma_length(struct ethosu_validated_cmdstream_info *info,

View file

@ -641,6 +641,7 @@ static void aca_error_fini(struct aca_error *aerr)
aca_bank_error_remove(aerr, bank_error);
out_unlock:
mutex_unlock(&aerr->lock);
mutex_destroy(&aerr->lock);
}

View file

@ -7059,6 +7059,15 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
dev_info(adev->dev, "PCI error: slot reset callback!!\n");
memset(&reset_context, 0, sizeof(reset_context));
INIT_LIST_HEAD(&device_list);
hive = amdgpu_get_xgmi_hive(adev);
if (hive) {
mutex_lock(&hive->hive_lock);
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head)
list_add_tail(&tmp_adev->reset_list, &device_list);
} else {
list_add_tail(&adev->reset_list, &device_list);
}
if (adev->pcie_reset_ctx.swus)
link_dev = adev->pcie_reset_ctx.swus;
@ -7099,19 +7108,13 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
reset_context.reset_req_dev = adev;
set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
set_bit(AMDGPU_SKIP_COREDUMP, &reset_context.flags);
INIT_LIST_HEAD(&device_list);
hive = amdgpu_get_xgmi_hive(adev);
if (hive) {
mutex_lock(&hive->hive_lock);
reset_context.hive = hive;
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) {
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head)
tmp_adev->pcie_reset_ctx.in_link_reset = true;
list_add_tail(&tmp_adev->reset_list, &device_list);
}
} else {
set_bit(AMDGPU_SKIP_HW_RESET, &reset_context.flags);
list_add_tail(&adev->reset_list, &device_list);
}
r = amdgpu_device_asic_reset(adev, &device_list, &reset_context);

View file

@ -332,13 +332,13 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
if (!context || !context->initialized) {
dev_err(adev->dev, "TA is not initialized\n");
ret = -EINVAL;
goto err_free_shared_buf;
goto free_shared_buf;
}
if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_invoke) {
dev_err(adev->dev, "Unsupported function to invoke TA\n");
ret = -EOPNOTSUPP;
goto err_free_shared_buf;
goto free_shared_buf;
}
context->session_id = ta_id;
@ -346,7 +346,7 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
mutex_lock(&psp->ras_context.mutex);
ret = prep_ta_mem_context(&context->mem_context, shared_buf, shared_buf_len);
if (ret)
goto err_free_shared_buf;
goto unlock;
ret = psp_fn_ta_invoke(psp, cmd_id);
if (ret || context->resp_status) {
@ -354,15 +354,17 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
ret, context->resp_status);
if (!ret) {
ret = -EINVAL;
goto err_free_shared_buf;
goto unlock;
}
}
if (copy_to_user((char *)&buf[copy_pos], context->mem_context.shared_buf, shared_buf_len))
ret = -EFAULT;
err_free_shared_buf:
unlock:
mutex_unlock(&psp->ras_context.mutex);
free_shared_buf:
kfree(shared_buf);
return ret;

View file

@ -35,6 +35,8 @@
static const struct dma_fence_ops amdgpu_userq_fence_ops;
static struct kmem_cache *amdgpu_userq_fence_slab;
#define AMDGPU_USERQ_MAX_HANDLES (1U << 16)
int amdgpu_userq_fence_slab_init(void)
{
amdgpu_userq_fence_slab = kmem_cache_create("amdgpu_userq_fence",
@ -478,6 +480,11 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data,
if (!amdgpu_userq_enabled(dev))
return -ENOTSUPP;
if (args->num_syncobj_handles > AMDGPU_USERQ_MAX_HANDLES ||
args->num_bo_write_handles > AMDGPU_USERQ_MAX_HANDLES ||
args->num_bo_read_handles > AMDGPU_USERQ_MAX_HANDLES)
return -EINVAL;
num_syncobj_handles = args->num_syncobj_handles;
syncobj_handles = memdup_user(u64_to_user_ptr(args->syncobj_handles),
size_mul(sizeof(u32), num_syncobj_handles));
@ -664,6 +671,11 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
if (!amdgpu_userq_enabled(dev))
return -ENOTSUPP;
if (wait_info->num_syncobj_handles > AMDGPU_USERQ_MAX_HANDLES ||
wait_info->num_bo_write_handles > AMDGPU_USERQ_MAX_HANDLES ||
wait_info->num_bo_read_handles > AMDGPU_USERQ_MAX_HANDLES)
return -EINVAL;
num_read_bo_handles = wait_info->num_bo_read_handles;
bo_handles_read = memdup_user(u64_to_user_ptr(wait_info->bo_read_handles),
size_mul(sizeof(u32), num_read_bo_handles));
@ -833,7 +845,7 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
dma_resv_for_each_fence(&resv_cursor, gobj_read[i]->resv,
DMA_RESV_USAGE_READ, fence) {
if (WARN_ON_ONCE(num_fences >= wait_info->num_fences)) {
if (num_fences >= wait_info->num_fences) {
r = -EINVAL;
goto free_fences;
}
@ -850,7 +862,7 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
dma_resv_for_each_fence(&resv_cursor, gobj_write[i]->resv,
DMA_RESV_USAGE_WRITE, fence) {
if (WARN_ON_ONCE(num_fences >= wait_info->num_fences)) {
if (num_fences >= wait_info->num_fences) {
r = -EINVAL;
goto free_fences;
}
@ -874,8 +886,9 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
goto free_fences;
dma_fence_unwrap_for_each(f, &iter, fence) {
if (WARN_ON_ONCE(num_fences >= wait_info->num_fences)) {
if (num_fences >= wait_info->num_fences) {
r = -EINVAL;
dma_fence_put(fence);
goto free_fences;
}
@ -898,8 +911,9 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
if (r)
goto free_fences;
if (WARN_ON_ONCE(num_fences >= wait_info->num_fences)) {
if (num_fences >= wait_info->num_fences) {
r = -EINVAL;
dma_fence_put(fence);
goto free_fences;
}

View file

@ -720,11 +720,6 @@ static int mes_v11_0_set_hw_resources(struct amdgpu_mes *mes)
mes_set_hw_res_pkt.enable_reg_active_poll = 1;
mes_set_hw_res_pkt.enable_level_process_quantum_check = 1;
mes_set_hw_res_pkt.oversubscription_timer = 50;
if ((mes->adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) >= 0x7f)
mes_set_hw_res_pkt.enable_lr_compute_wa = 1;
else
dev_info_once(mes->adev->dev,
"MES FW version must be >= 0x7f to enable LR compute workaround.\n");
if (amdgpu_mes_log_enable) {
mes_set_hw_res_pkt.enable_mes_event_int_logging = 1;

View file

@ -779,11 +779,6 @@ static int mes_v12_0_set_hw_resources(struct amdgpu_mes *mes, int pipe)
mes_set_hw_res_pkt.use_different_vmid_compute = 1;
mes_set_hw_res_pkt.enable_reg_active_poll = 1;
mes_set_hw_res_pkt.enable_level_process_quantum_check = 1;
if ((mes->adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) >= 0x82)
mes_set_hw_res_pkt.enable_lr_compute_wa = 1;
else
dev_info_once(adev->dev,
"MES FW version must be >= 0x82 to enable LR compute workaround.\n");
/*
* Keep oversubscribe timer for sdma . When we have unmapped doorbell

View file

@ -174,6 +174,10 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE);
fw_shared->sq.is_enabled = 1;
fw_shared->present_flag_0 |= cpu_to_le32(AMDGPU_VCN_SMU_DPM_INTERFACE_FLAG);
fw_shared->smu_dpm_interface.smu_interface_type = (adev->flags & AMD_IS_APU) ?
AMDGPU_VCN_SMU_DPM_INTERFACE_APU : AMDGPU_VCN_SMU_DPM_INTERFACE_DGPU;
if (amdgpu_vcnfw_log)
amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);

View file

@ -170,11 +170,11 @@ struct dc_stream_state *dc_create_stream_for_sink(
if (sink == NULL)
goto fail;
stream = kzalloc_obj(struct dc_stream_state);
stream = kzalloc_obj(struct dc_stream_state, GFP_ATOMIC);
if (stream == NULL)
goto fail;
stream->update_scratch = kzalloc((int32_t) dc_update_scratch_space_size(), GFP_KERNEL);
stream->update_scratch = kzalloc((int32_t) dc_update_scratch_space_size(), GFP_ATOMIC);
if (stream->update_scratch == NULL)
goto fail;

View file

@ -1881,6 +1881,14 @@ static int samsung_dsim_register_te_irq(struct samsung_dsim *dsi, struct device
return 0;
}
static void samsung_dsim_unregister_te_irq(struct samsung_dsim *dsi)
{
if (dsi->te_gpio) {
free_irq(gpiod_to_irq(dsi->te_gpio), dsi);
gpiod_put(dsi->te_gpio);
}
}
static int samsung_dsim_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *device)
{
@ -1961,7 +1969,7 @@ of_find_panel_or_bridge:
if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
ret = samsung_dsim_register_te_irq(dsi, &device->dev);
if (ret)
return ret;
goto err_remove_bridge;
}
// The next bridge can be used by host_ops->attach
@ -1982,15 +1990,12 @@ of_find_panel_or_bridge:
err_release_next_bridge:
drm_bridge_put(dsi->bridge.next_bridge);
dsi->bridge.next_bridge = NULL;
return ret;
}
static void samsung_dsim_unregister_te_irq(struct samsung_dsim *dsi)
{
if (dsi->te_gpio) {
free_irq(gpiod_to_irq(dsi->te_gpio), dsi);
gpiod_put(dsi->te_gpio);
}
if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO))
samsung_dsim_unregister_te_irq(dsi);
err_remove_bridge:
drm_bridge_remove(&dsi->bridge);
return ret;
}
static int samsung_dsim_host_detach(struct mipi_dsi_host *host,

View file

@ -2049,7 +2049,9 @@ struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
bridge->type = DRM_MODE_CONNECTOR_DisplayPort;
bridge->ycbcr_420_allowed = true;
devm_drm_bridge_add(dev, bridge);
ret = devm_drm_bridge_add(dev, bridge);
if (ret)
return ERR_PTR(ret);
dp->aux.dev = dev;
dp->aux.drm_dev = encoder->dev;

View file

@ -1415,6 +1415,7 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev,
{
struct ti_sn65dsi86 *pdata = dev_get_drvdata(adev->dev.parent);
struct device_node *np = pdata->dev->of_node;
const struct i2c_client *client = to_i2c_client(pdata->dev);
int ret;
pdata->next_bridge = devm_drm_of_get_bridge(&adev->dev, np, 1, 0);
@ -1433,8 +1434,9 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev,
? DRM_MODE_CONNECTOR_DisplayPort : DRM_MODE_CONNECTOR_eDP;
if (pdata->bridge.type == DRM_MODE_CONNECTOR_DisplayPort) {
pdata->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_DETECT |
DRM_BRIDGE_OP_HPD;
pdata->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_DETECT;
if (client->irq)
pdata->bridge.ops |= DRM_BRIDGE_OP_HPD;
/*
* If comms were already enabled they would have been enabled
* with the wrong value of HPD_DISABLE. Update it now. Comms

View file

@ -930,7 +930,8 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width,
mutex_unlock(&client->modeset_mutex);
out:
kfree(crtcs);
modes_destroy(dev, modes, connector_count);
if (modes)
modes_destroy(dev, modes, connector_count);
kfree(modes);
kfree(offsets);
kfree(enabled);

View file

@ -1338,14 +1338,14 @@ bool drm_gpusvm_range_pages_valid(struct drm_gpusvm *gpusvm,
EXPORT_SYMBOL_GPL(drm_gpusvm_range_pages_valid);
/**
* drm_gpusvm_range_pages_valid_unlocked() - GPU SVM range pages valid unlocked
* drm_gpusvm_pages_valid_unlocked() - GPU SVM pages valid unlocked
* @gpusvm: Pointer to the GPU SVM structure
* @range: Pointer to the GPU SVM range structure
* @svm_pages: Pointer to the GPU SVM pages structure
*
* This function determines if a GPU SVM range pages are valid. Expected be
* called without holding gpusvm->notifier_lock.
* This function determines if a GPU SVM pages are valid. Expected be called
* without holding gpusvm->notifier_lock.
*
* Return: True if GPU SVM range has valid pages, False otherwise
* Return: True if GPU SVM pages are valid, False otherwise
*/
static bool drm_gpusvm_pages_valid_unlocked(struct drm_gpusvm *gpusvm,
struct drm_gpusvm_pages *svm_pages)

View file

@ -562,12 +562,7 @@ void intel_alpm_disable(struct intel_dp *intel_dp)
mutex_lock(&intel_dp->alpm.lock);
intel_de_rmw(display, ALPM_CTL(display, cpu_transcoder),
ALPM_CTL_ALPM_ENABLE | ALPM_CTL_LOBF_ENABLE |
ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0);
intel_de_rmw(display,
PORT_ALPM_CTL(cpu_transcoder),
PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0);
ALPM_CTL_ALPM_ENABLE | ALPM_CTL_LOBF_ENABLE, 0);
drm_dbg_kms(display->drm, "Disabling ALPM\n");
mutex_unlock(&intel_dp->alpm.lock);

View file

@ -256,7 +256,9 @@ static int imx_pd_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, imxpd);
devm_drm_bridge_add(dev, &imxpd->bridge);
ret = devm_drm_bridge_add(dev, &imxpd->bridge);
if (ret)
return ret;
return component_add(dev, &imx_pd_ops);
}

View file

@ -92,7 +92,6 @@ static int logicvc_drm_config_parse(struct logicvc_drm *logicvc)
struct device *dev = drm_dev->dev;
struct device_node *of_node = dev->of_node;
struct logicvc_drm_config *config = &logicvc->config;
struct device_node *layers_node;
int ret;
logicvc_of_property_parse_bool(of_node, LOGICVC_OF_PROPERTY_DITHERING,
@ -128,7 +127,8 @@ static int logicvc_drm_config_parse(struct logicvc_drm *logicvc)
if (ret)
return ret;
layers_node = of_get_child_by_name(of_node, "layers");
struct device_node *layers_node __free(device_node) =
of_get_child_by_name(of_node, "layers");
if (!layers_node) {
drm_err(drm_dev, "Missing non-optional layers node\n");
return -EINVAL;

View file

@ -737,8 +737,8 @@ r535_gsp_acpi_caps(acpi_handle handle, CAPS_METHOD_DATA *caps)
if (!obj)
goto done;
if (WARN_ON(obj->type != ACPI_TYPE_BUFFER) ||
WARN_ON(obj->buffer.length != 4))
if (obj->type != ACPI_TYPE_BUFFER ||
obj->buffer.length != 4)
goto done;
caps->status = 0;
@ -773,8 +773,8 @@ r535_gsp_acpi_jt(acpi_handle handle, JT_METHOD_DATA *jt)
if (!obj)
goto done;
if (WARN_ON(obj->type != ACPI_TYPE_BUFFER) ||
WARN_ON(obj->buffer.length != 4))
if (obj->type != ACPI_TYPE_BUFFER ||
obj->buffer.length != 4)
goto done;
jt->status = 0;
@ -861,8 +861,8 @@ r535_gsp_acpi_dod(acpi_handle handle, DOD_METHOD_DATA *dod)
_DOD = output.pointer;
if (WARN_ON(_DOD->type != ACPI_TYPE_PACKAGE) ||
WARN_ON(_DOD->package.count > ARRAY_SIZE(dod->acpiIdList)))
if (_DOD->type != ACPI_TYPE_PACKAGE ||
_DOD->package.count > ARRAY_SIZE(dod->acpiIdList))
return;
for (int i = 0; i < _DOD->package.count; i++) {

View file

@ -541,8 +541,8 @@ static int sharp_memory_probe(struct spi_device *spi)
smd = devm_drm_dev_alloc(dev, &sharp_memory_drm_driver,
struct sharp_memory_device, drm);
if (!smd)
return -ENOMEM;
if (IS_ERR(smd))
return PTR_ERR(smd);
spi_set_drvdata(spi, smd);

View file

@ -105,6 +105,7 @@ struct vmw_cmdbuf_context {
* @handle: DMA address handle for the command buffer space if @using_mob is
* false. Immutable.
* @size: The size of the command buffer space. Immutable.
* @id: Monotonically increasing ID of the last cmdbuf submitted.
* @num_contexts: Number of contexts actually enabled.
*/
struct vmw_cmdbuf_man {
@ -132,6 +133,7 @@ struct vmw_cmdbuf_man {
bool has_pool;
dma_addr_t handle;
size_t size;
u64 id;
u32 num_contexts;
};
@ -303,6 +305,8 @@ static int vmw_cmdbuf_header_submit(struct vmw_cmdbuf_header *header)
struct vmw_cmdbuf_man *man = header->man;
u32 val;
header->cb_header->id = man->id++;
val = upper_32_bits(header->handle);
vmw_write(man->dev_priv, SVGA_REG_COMMAND_HIGH, val);

View file

@ -1143,7 +1143,7 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
ret = vmw_user_bo_lookup(sw_context->filp, handle, &vmw_bo);
if (ret != 0) {
drm_dbg(&dev_priv->drm, "Could not find or use MOB buffer.\n");
return PTR_ERR(vmw_bo);
return ret;
}
vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB);
ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo);
@ -1199,7 +1199,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
ret = vmw_user_bo_lookup(sw_context->filp, handle, &vmw_bo);
if (ret != 0) {
drm_dbg(&dev_priv->drm, "Could not find or use GMR region.\n");
return PTR_ERR(vmw_bo);
return ret;
}
vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM,
VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM);

View file

@ -260,6 +260,13 @@ out_no_dirty:
return ret;
}
static void vmw_bo_dirty_free(struct kref *kref)
{
struct vmw_bo_dirty *dirty = container_of(kref, struct vmw_bo_dirty, ref_count);
kvfree(dirty);
}
/**
* vmw_bo_dirty_release - Release a dirty-tracking user from a buffer object
* @vbo: The buffer object
@ -274,7 +281,7 @@ void vmw_bo_dirty_release(struct vmw_bo *vbo)
{
struct vmw_bo_dirty *dirty = vbo->dirty;
if (dirty && kref_put(&dirty->ref_count, (void *)kvfree))
if (dirty && kref_put(&dirty->ref_count, vmw_bo_dirty_free))
vbo->dirty = NULL;
}

View file

@ -96,6 +96,12 @@
#define ENABLE_SEMAPHORE_POLL_BIT REG_BIT(13)
#define RING_CMD_CCTL(base) XE_REG((base) + 0xc4, XE_REG_OPTION_MASKED)
#define CS_MMIO_GROUP_INSTANCE_SELECT(base) XE_REG((base) + 0xcc)
#define SELECTIVE_READ_ADDRESSING REG_BIT(30)
#define SELECTIVE_READ_GROUP REG_GENMASK(29, 23)
#define SELECTIVE_READ_INSTANCE REG_GENMASK(22, 16)
/*
* CMD_CCTL read/write fields take a MOCS value and _not_ a table index.
* The lsb of each can be considered a separate enabling bit for encryption.

View file

@ -210,11 +210,15 @@ static int emit_nop_job(struct xe_gt *gt, struct xe_exec_queue *q)
return ret;
}
/* Dwords required to emit a RMW of a register */
#define EMIT_RMW_DW 20
static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q)
{
struct xe_reg_sr *sr = &q->hwe->reg_lrc;
struct xe_hw_engine *hwe = q->hwe;
struct xe_reg_sr *sr = &hwe->reg_lrc;
struct xe_reg_sr_entry *entry;
int count_rmw = 0, count = 0, ret;
int count_rmw = 0, count_rmw_mcr = 0, count = 0, ret;
unsigned long idx;
struct xe_bb *bb;
size_t bb_len = 0;
@ -224,6 +228,8 @@ static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q)
xa_for_each(&sr->xa, idx, entry) {
if (entry->reg.masked || entry->clr_bits == ~0)
++count;
else if (entry->reg.mcr)
++count_rmw_mcr;
else
++count_rmw;
}
@ -231,17 +237,35 @@ static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q)
if (count)
bb_len += count * 2 + 1;
if (count_rmw)
bb_len += count_rmw * 20 + 7;
/*
* RMW of MCR registers is the same as a normal RMW, except an
* additional LRI (3 dwords) is required per register to steer the read
* to a nom-terminated instance.
*
* We could probably shorten the batch slightly by eliding the
* steering for consecutive MCR registers that have the same
* group/instance target, but it's not worth the extra complexity to do
* so.
*/
bb_len += count_rmw * EMIT_RMW_DW;
bb_len += count_rmw_mcr * (EMIT_RMW_DW + 3);
if (q->hwe->class == XE_ENGINE_CLASS_RENDER)
/*
* After doing all RMW, we need 7 trailing dwords to clean up,
* plus an additional 3 dwords to reset steering if any of the
* registers were MCR.
*/
if (count_rmw || count_rmw_mcr)
bb_len += 7 + (count_rmw_mcr ? 3 : 0);
if (hwe->class == XE_ENGINE_CLASS_RENDER)
/*
* Big enough to emit all of the context's 3DSTATE via
* xe_lrc_emit_hwe_state_instructions()
*/
bb_len += xe_gt_lrc_size(gt, q->hwe->class) / sizeof(u32);
bb_len += xe_gt_lrc_size(gt, hwe->class) / sizeof(u32);
xe_gt_dbg(gt, "LRC %s WA job: %zu dwords\n", q->hwe->name, bb_len);
xe_gt_dbg(gt, "LRC %s WA job: %zu dwords\n", hwe->name, bb_len);
bb = xe_bb_new(gt, bb_len, false);
if (IS_ERR(bb))
@ -276,13 +300,23 @@ static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q)
}
}
if (count_rmw) {
/* Emit MI_MATH for each RMW reg: 20dw per reg + 7 trailing dw */
if (count_rmw || count_rmw_mcr) {
xa_for_each(&sr->xa, idx, entry) {
if (entry->reg.masked || entry->clr_bits == ~0)
continue;
if (entry->reg.mcr) {
struct xe_reg_mcr reg = { .__reg.raw = entry->reg.raw };
u8 group, instance;
xe_gt_mcr_get_nonterminated_steering(gt, reg, &group, &instance);
*cs++ = MI_LOAD_REGISTER_IMM | MI_LRI_NUM_REGS(1);
*cs++ = CS_MMIO_GROUP_INSTANCE_SELECT(hwe->mmio_base).addr;
*cs++ = SELECTIVE_READ_ADDRESSING |
REG_FIELD_PREP(SELECTIVE_READ_GROUP, group) |
REG_FIELD_PREP(SELECTIVE_READ_INSTANCE, instance);
}
*cs++ = MI_LOAD_REGISTER_REG | MI_LRR_DST_CS_MMIO;
*cs++ = entry->reg.addr;
*cs++ = CS_GPR_REG(0, 0).addr;
@ -308,8 +342,9 @@ static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q)
*cs++ = CS_GPR_REG(0, 0).addr;
*cs++ = entry->reg.addr;
xe_gt_dbg(gt, "REG[%#x] = ~%#x|%#x\n",
entry->reg.addr, entry->clr_bits, entry->set_bits);
xe_gt_dbg(gt, "REG[%#x] = ~%#x|%#x%s\n",
entry->reg.addr, entry->clr_bits, entry->set_bits,
entry->reg.mcr ? " (MCR)" : "");
}
/* reset used GPR */
@ -321,6 +356,13 @@ static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q)
*cs++ = 0;
*cs++ = CS_GPR_REG(0, 2).addr;
*cs++ = 0;
/* reset steering */
if (count_rmw_mcr) {
*cs++ = MI_LOAD_REGISTER_IMM | MI_LRI_NUM_REGS(1);
*cs++ = CS_MMIO_GROUP_INSTANCE_SELECT(q->hwe->mmio_base).addr;
*cs++ = 0;
}
}
cs = xe_lrc_emit_hwe_state_instructions(q, cs);

View file

@ -146,8 +146,10 @@ int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef,
if (!signal) {
sync->fence = drm_syncobj_fence_get(sync->syncobj);
if (XE_IOCTL_DBG(xe, !sync->fence))
return -EINVAL;
if (XE_IOCTL_DBG(xe, !sync->fence)) {
err = -EINVAL;
goto free_sync;
}
}
break;
@ -167,17 +169,21 @@ int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef,
if (signal) {
sync->chain_fence = dma_fence_chain_alloc();
if (!sync->chain_fence)
return -ENOMEM;
if (!sync->chain_fence) {
err = -ENOMEM;
goto free_sync;
}
} else {
sync->fence = drm_syncobj_fence_get(sync->syncobj);
if (XE_IOCTL_DBG(xe, !sync->fence))
return -EINVAL;
if (XE_IOCTL_DBG(xe, !sync->fence)) {
err = -EINVAL;
goto free_sync;
}
err = dma_fence_chain_find_seqno(&sync->fence,
sync_in.timeline_value);
if (err)
return err;
goto free_sync;
}
break;
@ -200,8 +206,10 @@ int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef,
if (XE_IOCTL_DBG(xe, IS_ERR(sync->ufence)))
return PTR_ERR(sync->ufence);
sync->ufence_chain_fence = dma_fence_chain_alloc();
if (!sync->ufence_chain_fence)
return -ENOMEM;
if (!sync->ufence_chain_fence) {
err = -ENOMEM;
goto free_sync;
}
sync->ufence_syncobj = ufence_syncobj;
}
@ -216,6 +224,10 @@ int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef,
sync->timeline_value = sync_in.timeline_value;
return 0;
free_sync:
xe_sync_entry_cleanup(sync);
return err;
}
ALLOW_ERROR_INJECTION(xe_sync_entry_parse, ERRNO);

View file

@ -401,8 +401,8 @@ extern "C" {
* implementation can multiply the values by 2^6=64. For that reason the padding
* must only contain zeros.
* index 0 = Y plane, [15:0] z:Y [6:10] little endian
* index 1 = Cr plane, [15:0] z:Cr [6:10] little endian
* index 2 = Cb plane, [15:0] z:Cb [6:10] little endian
* index 1 = Cb plane, [15:0] z:Cb [6:10] little endian
* index 2 = Cr plane, [15:0] z:Cr [6:10] little endian
*/
#define DRM_FORMAT_S010 fourcc_code('S', '0', '1', '0') /* 2x2 subsampled Cb (1) and Cr (2) planes 10 bits per channel */
#define DRM_FORMAT_S210 fourcc_code('S', '2', '1', '0') /* 2x1 subsampled Cb (1) and Cr (2) planes 10 bits per channel */
@ -414,8 +414,8 @@ extern "C" {
* implementation can multiply the values by 2^4=16. For that reason the padding
* must only contain zeros.
* index 0 = Y plane, [15:0] z:Y [4:12] little endian
* index 1 = Cr plane, [15:0] z:Cr [4:12] little endian
* index 2 = Cb plane, [15:0] z:Cb [4:12] little endian
* index 1 = Cb plane, [15:0] z:Cb [4:12] little endian
* index 2 = Cr plane, [15:0] z:Cr [4:12] little endian
*/
#define DRM_FORMAT_S012 fourcc_code('S', '0', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes 12 bits per channel */
#define DRM_FORMAT_S212 fourcc_code('S', '2', '1', '2') /* 2x1 subsampled Cb (1) and Cr (2) planes 12 bits per channel */
@ -424,8 +424,8 @@ extern "C" {
/*
* 3 plane YCbCr
* index 0 = Y plane, [15:0] Y little endian
* index 1 = Cr plane, [15:0] Cr little endian
* index 2 = Cb plane, [15:0] Cb little endian
* index 1 = Cb plane, [15:0] Cb little endian
* index 2 = Cr plane, [15:0] Cr little endian
*/
#define DRM_FORMAT_S016 fourcc_code('S', '0', '1', '6') /* 2x2 subsampled Cb (1) and Cr (2) planes 16 bits per channel */
#define DRM_FORMAT_S216 fourcc_code('S', '2', '1', '6') /* 2x1 subsampled Cb (1) and Cr (2) planes 16 bits per channel */