drm fixes for 7.0-rc3

mm:
 - mm: Fix a hmm_range_fault() livelock / starvation problem
 
 pagemap:
 - Revert "drm/pagemap: Disable device-to-device migration"
 
 ttm:
 - fix function return breaking reclaim
 - fix build failure on PREEMPT_RT
 - fix bo->resource UAF
 
 dma-buf:
 - include ioctl.h in uapi header
 
 sched:
 - fix kernel doc warning
 
 amdgpu:
 - LUT fixes
 - VCN5 fix
 - Dispclk fix
 - SMU 13.x fix
 - Fix race in VM acquire
 - PSP 15.x fix
 - UserQ fix
 
 amdxdna:
 - fix invalid payload for failed command
 - fix NULL ptr dereference
 - fix major fw version check
 - avoid inconsistent fw state on error
 
 i915/display:
 - Fix for Lenovo T14 G7 display not refreshing
 
 xe:
 - Do not preempt fence signaling CS instructions
 - Some leak and finalization fixes
 - Workaround fix
 
 nouveau:
 - avoid runtime suspend oops when using dp aux
 
 panthor:
 - fix gem_sync argument ordering
 
 solomon:
 - fix incorrect display output
 
 renesas:
 - fix DSI divider programming
 
 ethosu:
 - fix job submit error clean-up refcount
 - fix NPU_OP_ELEMENTWISE validation
 - handle possible underflows in IFM size calcs
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmmrODEACgkQDHTzWXnE
 hr6ENA/9E+ABsQPUSr1ZUR6MfS3FdDMfyNi34u9F0XE0vL/6J4DIN2MXHJN0yj4S
 YeR8RIH1uuteexRCVjK8gYrDFZm5GpdJ7tZsPBogKSjfr4P4zvSdcyP0DtubmHN8
 k/Rbdr1m2BnAerviPUlQ09voG4VyM/IlnkOj/aUrAG4xHfNLWhQ/eY21HjvTaMEw
 eNPk75G32AkusybhYGLcfRKUqmZ9Sh/EAIOiqp5Gd61bSbNXFbXqU59AliRSW16D
 dRMjCenQbBtXnf1xzn9xmC95Mr5NhlId3BddY6nsmTvqnse50w1IBw4MbA5703iv
 teNAsRHNWBiyachtolylu63z8fjc3mqRgyB3qoYCIn4pGm6wej3SSuOr+WaKTPMr
 ucKNxvsluiXOIdUrkLYyl1LTU1Bqs2/mFTPzyHFykeB72swHGyCfYyh/RgL+dYIc
 nuOsY1n4JR1JCkg5p4Y8LZq0RXLE6PJfyxmpF9W2r9DVV4T52Yk5fiXEo+HJ9WaJ
 yaa3xBJJLP0z50JuaV7iEIiXQBwj482m0No+jG4+ZTatRm/4oz0cHpmoRkPuN6Og
 vc6UdFUtRysVqSetLfV1oBpLm3zkhumDxtrqb6GHB7n+ahY7mFCLc175wFXoGCqu
 DxCshK5FZchyPbOXaxOWyIVXDCYJtCJnK4vBCHwkJAkxLQCpv/k=
 =yGA4
 -----END PGP SIGNATURE-----

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

Pull drm fixes from Dave Airlie:
 "Weekly fixes pull.

  There is one mm fix in here for a HMM livelock triggered by the xe
  driver tests. Otherwise it's a pretty wide range of fixes across the
  board, ttm UAF regression fix, amdgpu fixes, nouveau doesn't crash my
  laptop anymore fix, and a fair bit of misc.

  Seems about right for rc3.

  mm:
   - mm: Fix a hmm_range_fault() livelock / starvation problem

  pagemap:
   - Revert "drm/pagemap: Disable device-to-device migration"

  ttm:
   - fix function return breaking reclaim
   - fix build failure on PREEMPT_RT
   - fix bo->resource UAF

  dma-buf:
   - include ioctl.h in uapi header

  sched:
   - fix kernel doc warning

  amdgpu:
   - LUT fixes
   - VCN5 fix
   - Dispclk fix
   - SMU 13.x fix
   - Fix race in VM acquire
   - PSP 15.x fix
   - UserQ fix

  amdxdna:
   - fix invalid payload for failed command
   - fix NULL ptr dereference
   - fix major fw version check
   - avoid inconsistent fw state on error

  i915/display:
   - Fix for Lenovo T14 G7 display not refreshing

  xe:
   - Do not preempt fence signaling CS instructions
   - Some leak and finalization fixes
   - Workaround fix

  nouveau:
   - avoid runtime suspend oops when using dp aux

  panthor:
   - fix gem_sync argument ordering

  solomon:
   - fix incorrect display output

  renesas:
   - fix DSI divider programming

  ethosu:
   - fix job submit error clean-up refcount
   - fix NPU_OP_ELEMENTWISE validation
   - handle possible underflows in IFM size calcs"

* tag 'drm-fixes-2026-03-07' of https://gitlab.freedesktop.org/drm/kernel: (38 commits)
  accel: ethosu: Handle possible underflow in IFM size calculations
  accel: ethosu: Fix NPU_OP_ELEMENTWISE validation with scalar
  accel: ethosu: Fix job submit error clean-up refcount underflows
  accel/amdxdna: Split mailbox channel create function
  drm/panthor: Correct the order of arguments passed to gem_sync
  Revert "drm/syncobj: Fix handle <-> fd ioctls with dirty stack"
  drm/ttm: Fix bo resource use-after-free
  nouveau/dpcd: return EBUSY for aux xfer if the device is asleep
  accel/amdxdna: Fix major version check on NPU1 platform
  drm/amdgpu/userq: refcount userqueues to avoid any race conditions
  drm/amdgpu/userq: Consolidate wait ioctl exit path
  drm/amdgpu/psp: Use Indirect access address for GFX to PSP mailbox
  drm/amdgpu: Fix use-after-free race in VM acquire
  drm/amd/pm: remove invalid gpu_metrics.energy_accumulator on smu v13.0.x
  drm/xe: Fix memory leak in xe_vm_madvise_ioctl
  drm/xe/reg_sr: Fix leak on xa_store failure
  drm/xe/xe2_hpg: Correct implementation of Wa_16025250150
  drm/xe/gsc: Fix GSC proxy cleanup on early initialization failure
  Revert "drm/pagemap: Disable device-to-device migration"
  drm/i915/psr: Fix for Panel Replay X granularity DPCD register handling
  ...
This commit is contained in:
Linus Torvalds 2026-03-06 13:29:12 -08:00
commit dfb3142844
51 changed files with 516 additions and 291 deletions

View file

@ -186,13 +186,13 @@ aie2_sched_resp_handler(void *handle, void __iomem *data, size_t size)
cmd_abo = job->cmd_bo;
if (unlikely(job->job_timeout)) {
amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_TIMEOUT);
amdxdna_cmd_set_error(cmd_abo, job, 0, ERT_CMD_STATE_TIMEOUT);
ret = -EINVAL;
goto out;
}
if (unlikely(!data) || unlikely(size != sizeof(u32))) {
amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_ABORT);
amdxdna_cmd_set_error(cmd_abo, job, 0, ERT_CMD_STATE_ABORT);
ret = -EINVAL;
goto out;
}
@ -202,7 +202,7 @@ aie2_sched_resp_handler(void *handle, void __iomem *data, size_t size)
if (status == AIE2_STATUS_SUCCESS)
amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_COMPLETED);
else
amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_ERROR);
amdxdna_cmd_set_error(cmd_abo, job, 0, ERT_CMD_STATE_ERROR);
out:
aie2_sched_notify(job);
@ -244,13 +244,13 @@ aie2_sched_cmdlist_resp_handler(void *handle, void __iomem *data, size_t size)
cmd_abo = job->cmd_bo;
if (unlikely(job->job_timeout)) {
amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_TIMEOUT);
amdxdna_cmd_set_error(cmd_abo, job, 0, ERT_CMD_STATE_TIMEOUT);
ret = -EINVAL;
goto out;
}
if (unlikely(!data) || unlikely(size != sizeof(u32) * 3)) {
amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_ABORT);
amdxdna_cmd_set_error(cmd_abo, job, 0, ERT_CMD_STATE_ABORT);
ret = -EINVAL;
goto out;
}
@ -270,19 +270,12 @@ aie2_sched_cmdlist_resp_handler(void *handle, void __iomem *data, size_t size)
fail_cmd_idx, fail_cmd_status);
if (fail_cmd_status == AIE2_STATUS_SUCCESS) {
amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_ABORT);
amdxdna_cmd_set_error(cmd_abo, job, fail_cmd_idx, ERT_CMD_STATE_ABORT);
ret = -EINVAL;
goto out;
} else {
amdxdna_cmd_set_error(cmd_abo, job, fail_cmd_idx, ERT_CMD_STATE_ERROR);
}
amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_ERROR);
if (amdxdna_cmd_get_op(cmd_abo) == ERT_CMD_CHAIN) {
struct amdxdna_cmd_chain *cc = amdxdna_cmd_get_payload(cmd_abo, NULL);
cc->error_index = fail_cmd_idx;
if (cc->error_index >= cc->command_count)
cc->error_index = 0;
}
out:
aie2_sched_notify(job);
return ret;

View file

@ -40,11 +40,8 @@ static int aie2_send_mgmt_msg_wait(struct amdxdna_dev_hdl *ndev,
return -ENODEV;
ret = xdna_send_msg_wait(xdna, ndev->mgmt_chann, msg);
if (ret == -ETIME) {
xdna_mailbox_stop_channel(ndev->mgmt_chann);
xdna_mailbox_destroy_channel(ndev->mgmt_chann);
ndev->mgmt_chann = NULL;
}
if (ret == -ETIME)
aie2_destroy_mgmt_chann(ndev);
if (!ret && *hdl->status != AIE2_STATUS_SUCCESS) {
XDNA_ERR(xdna, "command opcode 0x%x failed, status 0x%x",
@ -296,13 +293,20 @@ int aie2_create_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwct
}
intr_reg = i2x.mb_head_ptr_reg + 4;
hwctx->priv->mbox_chann = xdna_mailbox_create_channel(ndev->mbox, &x2i, &i2x,
intr_reg, ret);
hwctx->priv->mbox_chann = xdna_mailbox_alloc_channel(ndev->mbox);
if (!hwctx->priv->mbox_chann) {
XDNA_ERR(xdna, "Not able to create channel");
ret = -EINVAL;
goto del_ctx_req;
}
ret = xdna_mailbox_start_channel(hwctx->priv->mbox_chann, &x2i, &i2x,
intr_reg, ret);
if (ret) {
XDNA_ERR(xdna, "Not able to create channel");
ret = -EINVAL;
goto free_channel;
}
ndev->hwctx_num++;
XDNA_DBG(xdna, "Mailbox channel irq: %d, msix_id: %d", ret, resp.msix_id);
@ -310,6 +314,8 @@ int aie2_create_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwct
return 0;
free_channel:
xdna_mailbox_free_channel(hwctx->priv->mbox_chann);
del_ctx_req:
aie2_destroy_context_req(ndev, hwctx->fw_ctx_id);
return ret;
@ -325,7 +331,7 @@ int aie2_destroy_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwc
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);
xdna_mailbox_free_channel(hwctx->priv->mbox_chann);
XDNA_DBG(xdna, "Destroyed fw ctx %d", hwctx->fw_ctx_id);
hwctx->priv->mbox_chann = NULL;
hwctx->fw_ctx_id = -1;
@ -914,6 +920,20 @@ void aie2_msg_init(struct amdxdna_dev_hdl *ndev)
ndev->exec_msg_ops = &legacy_exec_message_ops;
}
void aie2_destroy_mgmt_chann(struct amdxdna_dev_hdl *ndev)
{
struct amdxdna_dev *xdna = ndev->xdna;
drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
if (!ndev->mgmt_chann)
return;
xdna_mailbox_stop_channel(ndev->mgmt_chann);
xdna_mailbox_free_channel(ndev->mgmt_chann);
ndev->mgmt_chann = NULL;
}
static inline struct amdxdna_gem_obj *
aie2_cmdlist_get_cmd_buf(struct amdxdna_sched_job *job)
{

View file

@ -330,9 +330,7 @@ static void aie2_hw_stop(struct amdxdna_dev *xdna)
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);
ndev->mgmt_chann = NULL;
aie2_destroy_mgmt_chann(ndev);
drmm_kfree(&xdna->ddev, ndev->mbox);
ndev->mbox = NULL;
aie2_psp_stop(ndev->psp_hdl);
@ -363,10 +361,29 @@ static int aie2_hw_start(struct amdxdna_dev *xdna)
}
pci_set_master(pdev);
mbox_res.ringbuf_base = ndev->sram_base;
mbox_res.ringbuf_size = pci_resource_len(pdev, xdna->dev_info->sram_bar);
mbox_res.mbox_base = ndev->mbox_base;
mbox_res.mbox_size = MBOX_SIZE(ndev);
mbox_res.name = "xdna_mailbox";
ndev->mbox = xdnam_mailbox_create(&xdna->ddev, &mbox_res);
if (!ndev->mbox) {
XDNA_ERR(xdna, "failed to create mailbox device");
ret = -ENODEV;
goto disable_dev;
}
ndev->mgmt_chann = xdna_mailbox_alloc_channel(ndev->mbox);
if (!ndev->mgmt_chann) {
XDNA_ERR(xdna, "failed to alloc channel");
ret = -ENODEV;
goto disable_dev;
}
ret = aie2_smu_init(ndev);
if (ret) {
XDNA_ERR(xdna, "failed to init smu, ret %d", ret);
goto disable_dev;
goto free_channel;
}
ret = aie2_psp_start(ndev->psp_hdl);
@ -381,18 +398,6 @@ static int aie2_hw_start(struct amdxdna_dev *xdna)
goto stop_psp;
}
mbox_res.ringbuf_base = ndev->sram_base;
mbox_res.ringbuf_size = pci_resource_len(pdev, xdna->dev_info->sram_bar);
mbox_res.mbox_base = ndev->mbox_base;
mbox_res.mbox_size = MBOX_SIZE(ndev);
mbox_res.name = "xdna_mailbox";
ndev->mbox = xdnam_mailbox_create(&xdna->ddev, &mbox_res);
if (!ndev->mbox) {
XDNA_ERR(xdna, "failed to create mailbox device");
ret = -ENODEV;
goto stop_psp;
}
mgmt_mb_irq = pci_irq_vector(pdev, ndev->mgmt_chan_idx);
if (mgmt_mb_irq < 0) {
ret = mgmt_mb_irq;
@ -401,13 +406,13 @@ static int aie2_hw_start(struct amdxdna_dev *xdna)
}
xdna_mailbox_intr_reg = ndev->mgmt_i2x.mb_head_ptr_reg + 4;
ndev->mgmt_chann = xdna_mailbox_create_channel(ndev->mbox,
ret = xdna_mailbox_start_channel(ndev->mgmt_chann,
&ndev->mgmt_x2i,
&ndev->mgmt_i2x,
xdna_mailbox_intr_reg,
mgmt_mb_irq);
if (!ndev->mgmt_chann) {
XDNA_ERR(xdna, "failed to create management mailbox channel");
if (ret) {
XDNA_ERR(xdna, "failed to start management mailbox channel");
ret = -EINVAL;
goto stop_psp;
}
@ -415,38 +420,41 @@ static int aie2_hw_start(struct amdxdna_dev *xdna)
ret = aie2_mgmt_fw_init(ndev);
if (ret) {
XDNA_ERR(xdna, "initial mgmt firmware failed, ret %d", ret);
goto destroy_mgmt_chann;
goto stop_fw;
}
ret = aie2_pm_init(ndev);
if (ret) {
XDNA_ERR(xdna, "failed to init pm, ret %d", ret);
goto destroy_mgmt_chann;
goto stop_fw;
}
ret = aie2_mgmt_fw_query(ndev);
if (ret) {
XDNA_ERR(xdna, "failed to query fw, ret %d", ret);
goto destroy_mgmt_chann;
goto stop_fw;
}
ret = aie2_error_async_events_alloc(ndev);
if (ret) {
XDNA_ERR(xdna, "Allocate async events failed, ret %d", ret);
goto destroy_mgmt_chann;
goto stop_fw;
}
ndev->dev_status = AIE2_DEV_START;
return 0;
destroy_mgmt_chann:
stop_fw:
aie2_suspend_fw(ndev);
xdna_mailbox_stop_channel(ndev->mgmt_chann);
xdna_mailbox_destroy_channel(ndev->mgmt_chann);
stop_psp:
aie2_psp_stop(ndev->psp_hdl);
fini_smu:
aie2_smu_fini(ndev);
free_channel:
xdna_mailbox_free_channel(ndev->mgmt_chann);
ndev->mgmt_chann = NULL;
disable_dev:
pci_disable_device(pdev);

View file

@ -303,6 +303,7 @@ int aie2_get_array_async_error(struct amdxdna_dev_hdl *ndev,
/* aie2_message.c */
void aie2_msg_init(struct amdxdna_dev_hdl *ndev);
void aie2_destroy_mgmt_chann(struct amdxdna_dev_hdl *ndev);
int aie2_suspend_fw(struct amdxdna_dev_hdl *ndev);
int aie2_resume_fw(struct amdxdna_dev_hdl *ndev);
int aie2_set_runtime_cfg(struct amdxdna_dev_hdl *ndev, u32 type, u64 value);

View file

@ -135,6 +135,33 @@ u32 amdxdna_cmd_get_cu_idx(struct amdxdna_gem_obj *abo)
return INVALID_CU_IDX;
}
int amdxdna_cmd_set_error(struct amdxdna_gem_obj *abo,
struct amdxdna_sched_job *job, u32 cmd_idx,
enum ert_cmd_state error_state)
{
struct amdxdna_client *client = job->hwctx->client;
struct amdxdna_cmd *cmd = abo->mem.kva;
struct amdxdna_cmd_chain *cc = NULL;
cmd->header &= ~AMDXDNA_CMD_STATE;
cmd->header |= FIELD_PREP(AMDXDNA_CMD_STATE, error_state);
if (amdxdna_cmd_get_op(abo) == ERT_CMD_CHAIN) {
cc = amdxdna_cmd_get_payload(abo, NULL);
cc->error_index = (cmd_idx < cc->command_count) ? cmd_idx : 0;
abo = amdxdna_gem_get_obj(client, cc->data[0], AMDXDNA_BO_CMD);
if (!abo)
return -EINVAL;
cmd = abo->mem.kva;
}
memset(cmd->data, 0xff, abo->mem.size - sizeof(*cmd));
if (cc)
amdxdna_gem_put_obj(abo);
return 0;
}
/*
* This should be called in close() and remove(). DO NOT call in other syscalls.
* This guarantee that when hwctx and resources will be released, if user

View file

@ -167,6 +167,9 @@ amdxdna_cmd_get_state(struct amdxdna_gem_obj *abo)
void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size);
u32 amdxdna_cmd_get_cu_idx(struct amdxdna_gem_obj *abo);
int amdxdna_cmd_set_error(struct amdxdna_gem_obj *abo,
struct amdxdna_sched_job *job, u32 cmd_idx,
enum ert_cmd_state error_state);
void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job);
void amdxdna_hwctx_remove_all(struct amdxdna_client *client);

View file

@ -460,26 +460,49 @@ msg_id_failed:
return ret;
}
struct mailbox_channel *
xdna_mailbox_create_channel(struct mailbox *mb,
const struct xdna_mailbox_chann_res *x2i,
const struct xdna_mailbox_chann_res *i2x,
u32 iohub_int_addr,
int mb_irq)
struct mailbox_channel *xdna_mailbox_alloc_channel(struct mailbox *mb)
{
struct mailbox_channel *mb_chann;
int ret;
if (!is_power_of_2(x2i->rb_size) || !is_power_of_2(i2x->rb_size)) {
pr_err("Ring buf size must be power of 2");
return NULL;
}
mb_chann = kzalloc_obj(*mb_chann);
if (!mb_chann)
return NULL;
INIT_WORK(&mb_chann->rx_work, mailbox_rx_worker);
mb_chann->work_q = create_singlethread_workqueue(MAILBOX_NAME);
if (!mb_chann->work_q) {
MB_ERR(mb_chann, "Create workqueue failed");
goto free_chann;
}
mb_chann->mb = mb;
return mb_chann;
free_chann:
kfree(mb_chann);
return NULL;
}
void xdna_mailbox_free_channel(struct mailbox_channel *mb_chann)
{
destroy_workqueue(mb_chann->work_q);
kfree(mb_chann);
}
int
xdna_mailbox_start_channel(struct mailbox_channel *mb_chann,
const struct xdna_mailbox_chann_res *x2i,
const struct xdna_mailbox_chann_res *i2x,
u32 iohub_int_addr,
int mb_irq)
{
int ret;
if (!is_power_of_2(x2i->rb_size) || !is_power_of_2(i2x->rb_size)) {
pr_err("Ring buf size must be power of 2");
return -EINVAL;
}
mb_chann->msix_irq = mb_irq;
mb_chann->iohub_int_addr = iohub_int_addr;
memcpy(&mb_chann->res[CHAN_RES_X2I], x2i, sizeof(*x2i));
@ -489,61 +512,37 @@ xdna_mailbox_create_channel(struct mailbox *mb,
mb_chann->x2i_tail = mailbox_get_tailptr(mb_chann, CHAN_RES_X2I);
mb_chann->i2x_head = mailbox_get_headptr(mb_chann, CHAN_RES_I2X);
INIT_WORK(&mb_chann->rx_work, mailbox_rx_worker);
mb_chann->work_q = create_singlethread_workqueue(MAILBOX_NAME);
if (!mb_chann->work_q) {
MB_ERR(mb_chann, "Create workqueue failed");
goto free_and_out;
}
/* Everything look good. Time to enable irq handler */
ret = request_irq(mb_irq, mailbox_irq_handler, 0, MAILBOX_NAME, mb_chann);
if (ret) {
MB_ERR(mb_chann, "Failed to request irq %d ret %d", mb_irq, ret);
goto destroy_wq;
return ret;
}
mb_chann->bad_state = false;
mailbox_reg_write(mb_chann, mb_chann->iohub_int_addr, 0);
MB_DBG(mb_chann, "Mailbox channel created (irq: %d)", mb_chann->msix_irq);
return mb_chann;
destroy_wq:
destroy_workqueue(mb_chann->work_q);
free_and_out:
kfree(mb_chann);
return NULL;
}
int xdna_mailbox_destroy_channel(struct mailbox_channel *mb_chann)
{
struct mailbox_msg *mb_msg;
unsigned long msg_id;
MB_DBG(mb_chann, "IRQ disabled and RX work cancelled");
free_irq(mb_chann->msix_irq, mb_chann);
destroy_workqueue(mb_chann->work_q);
/* We can clean up and release resources */
xa_for_each(&mb_chann->chan_xa, msg_id, mb_msg)
mailbox_release_msg(mb_chann, mb_msg);
xa_destroy(&mb_chann->chan_xa);
MB_DBG(mb_chann, "Mailbox channel destroyed, irq: %d", mb_chann->msix_irq);
kfree(mb_chann);
MB_DBG(mb_chann, "Mailbox channel started (irq: %d)", mb_chann->msix_irq);
return 0;
}
void xdna_mailbox_stop_channel(struct mailbox_channel *mb_chann)
{
struct mailbox_msg *mb_msg;
unsigned long msg_id;
/* Disable an irq and wait. This might sleep. */
disable_irq(mb_chann->msix_irq);
free_irq(mb_chann->msix_irq, mb_chann);
/* Cancel RX work and wait for it to finish */
cancel_work_sync(&mb_chann->rx_work);
MB_DBG(mb_chann, "IRQ disabled and RX work cancelled");
drain_workqueue(mb_chann->work_q);
/* We can clean up and release resources */
xa_for_each(&mb_chann->chan_xa, msg_id, mb_msg)
mailbox_release_msg(mb_chann, mb_msg);
xa_destroy(&mb_chann->chan_xa);
MB_DBG(mb_chann, "Mailbox channel stopped, irq: %d", mb_chann->msix_irq);
}
struct mailbox *xdnam_mailbox_create(struct drm_device *ddev,

View file

@ -74,9 +74,16 @@ struct mailbox *xdnam_mailbox_create(struct drm_device *ddev,
const struct xdna_mailbox_res *res);
/*
* xdna_mailbox_create_channel() -- Create a mailbox channel instance
* xdna_mailbox_alloc_channel() -- alloc a mailbox channel
*
* @mailbox: the handle return from xdna_mailbox_create()
* @mb: mailbox handle
*/
struct mailbox_channel *xdna_mailbox_alloc_channel(struct mailbox *mb);
/*
* xdna_mailbox_start_channel() -- start a mailbox channel instance
*
* @mb_chann: the handle return from xdna_mailbox_alloc_channel()
* @x2i: host to firmware mailbox resources
* @i2x: firmware to host mailbox resources
* @xdna_mailbox_intr_reg: register addr of MSI-X interrupt
@ -84,28 +91,24 @@ struct mailbox *xdnam_mailbox_create(struct drm_device *ddev,
*
* Return: If success, return a handle of mailbox channel. Otherwise, return NULL.
*/
struct mailbox_channel *
xdna_mailbox_create_channel(struct mailbox *mailbox,
int
xdna_mailbox_start_channel(struct mailbox_channel *mb_chann,
const struct xdna_mailbox_chann_res *x2i,
const struct xdna_mailbox_chann_res *i2x,
u32 xdna_mailbox_intr_reg,
int mb_irq);
/*
* xdna_mailbox_destroy_channel() -- destroy mailbox channel
* xdna_mailbox_free_channel() -- free mailbox channel
*
* @mailbox_chann: the handle return from xdna_mailbox_create_channel()
*
* Return: if success, return 0. otherwise return error code
*/
int xdna_mailbox_destroy_channel(struct mailbox_channel *mailbox_chann);
void xdna_mailbox_free_channel(struct mailbox_channel *mailbox_chann);
/*
* xdna_mailbox_stop_channel() -- stop mailbox channel
*
* @mailbox_chann: the handle return from xdna_mailbox_create_channel()
*
* Return: if success, return 0. otherwise return error code
*/
void xdna_mailbox_stop_channel(struct mailbox_channel *mailbox_chann);

View file

@ -67,7 +67,7 @@ const struct dpm_clk_freq npu1_dpm_clk_table[] = {
static const struct aie2_fw_feature_tbl npu1_fw_feature_table[] = {
{ .major = 5, .min_minor = 7 },
{ .features = BIT_U64(AIE2_NPU_COMMAND), .min_minor = 8 },
{ .features = BIT_U64(AIE2_NPU_COMMAND), .major = 5, .min_minor = 8 },
{ 0 }
};

View file

@ -245,11 +245,14 @@ static int calc_sizes(struct drm_device *ddev,
((st->ifm.stride_kernel >> 1) & 0x1) + 1;
u32 stride_x = ((st->ifm.stride_kernel >> 5) & 0x2) +
(st->ifm.stride_kernel & 0x1) + 1;
u32 ifm_height = st->ofm.height[2] * stride_y +
s32 ifm_height = st->ofm.height[2] * stride_y +
st->ifm.height[2] - (st->ifm.pad_top + st->ifm.pad_bottom);
u32 ifm_width = st->ofm.width * stride_x +
s32 ifm_width = st->ofm.width * stride_x +
st->ifm.width - (st->ifm.pad_left + st->ifm.pad_right);
if (ifm_height < 0 || ifm_width < 0)
return -EINVAL;
len = feat_matrix_length(info, &st->ifm, ifm_width,
ifm_height, st->ifm.depth);
dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n",
@ -417,7 +420,10 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
return ret;
break;
case NPU_OP_ELEMENTWISE:
use_ifm2 = !((st.ifm2.broadcast == 8) || (param == 5) ||
use_scale = ethosu_is_u65(edev) ?
(st.ifm2.broadcast & 0x80) :
(st.ifm2.broadcast == 8);
use_ifm2 = !(use_scale || (param == 5) ||
(param == 6) || (param == 7) || (param == 0x24));
use_ifm = st.ifm.broadcast != 8;
ret = calc_sizes_elemwise(ddev, info, cmd, &st, use_ifm, use_ifm2);

View file

@ -143,17 +143,10 @@ out:
return ret;
}
static void ethosu_job_cleanup(struct kref *ref)
static void ethosu_job_err_cleanup(struct ethosu_job *job)
{
struct ethosu_job *job = container_of(ref, struct ethosu_job,
refcount);
unsigned int i;
pm_runtime_put_autosuspend(job->dev->base.dev);
dma_fence_put(job->done_fence);
dma_fence_put(job->inference_done_fence);
for (i = 0; i < job->region_cnt; i++)
drm_gem_object_put(job->region_bo[i]);
@ -162,6 +155,19 @@ static void ethosu_job_cleanup(struct kref *ref)
kfree(job);
}
static void ethosu_job_cleanup(struct kref *ref)
{
struct ethosu_job *job = container_of(ref, struct ethosu_job,
refcount);
pm_runtime_put_autosuspend(job->dev->base.dev);
dma_fence_put(job->done_fence);
dma_fence_put(job->inference_done_fence);
ethosu_job_err_cleanup(job);
}
static void ethosu_job_put(struct ethosu_job *job)
{
kref_put(&job->refcount, ethosu_job_cleanup);
@ -454,12 +460,16 @@ static int ethosu_ioctl_submit_job(struct drm_device *dev, struct drm_file *file
}
}
ret = ethosu_job_push(ejob);
if (!ret) {
ethosu_job_put(ejob);
return 0;
}
out_cleanup_job:
if (ret)
drm_sched_job_cleanup(&ejob->base);
out_put_job:
ethosu_job_put(ejob);
ethosu_job_err_cleanup(ejob);
return ret;
}

View file

@ -1439,7 +1439,10 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info,
*process_info = info;
}
vm->process_info = *process_info;
if (cmpxchg(&vm->process_info, NULL, *process_info) != NULL) {
ret = -EINVAL;
goto already_acquired;
}
/* Validate page directory and attach eviction fence */
ret = amdgpu_bo_reserve(vm->root.bo, true);
@ -1479,6 +1482,7 @@ validate_pd_fail:
amdgpu_bo_unreserve(vm->root.bo);
reserve_pd_fail:
vm->process_info = NULL;
already_acquired:
if (info) {
dma_fence_put(&info->eviction_fence->base);
*process_info = NULL;

View file

@ -446,8 +446,7 @@ static int amdgpu_userq_wait_for_last_fence(struct amdgpu_usermode_queue *queue)
return ret;
}
static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue,
int queue_id)
static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue)
{
struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr;
struct amdgpu_device *adev = uq_mgr->adev;
@ -461,7 +460,6 @@ static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue,
uq_funcs->mqd_destroy(queue);
amdgpu_userq_fence_driver_free(queue);
/* Use interrupt-safe locking since IRQ handlers may access these XArrays */
xa_erase_irq(&uq_mgr->userq_xa, (unsigned long)queue_id);
xa_erase_irq(&adev->userq_doorbell_xa, queue->doorbell_index);
queue->userq_mgr = NULL;
list_del(&queue->userq_va_list);
@ -470,12 +468,6 @@ static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue,
up_read(&adev->reset_domain->sem);
}
static struct amdgpu_usermode_queue *
amdgpu_userq_find(struct amdgpu_userq_mgr *uq_mgr, int qid)
{
return xa_load(&uq_mgr->userq_xa, qid);
}
void
amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_eviction_fence_mgr *evf_mgr)
@ -625,22 +617,13 @@ unref_bo:
}
static int
amdgpu_userq_destroy(struct drm_file *filp, int queue_id)
amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_queue *queue)
{
struct amdgpu_fpriv *fpriv = filp->driver_priv;
struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
struct amdgpu_device *adev = uq_mgr->adev;
struct amdgpu_usermode_queue *queue;
int r = 0;
cancel_delayed_work_sync(&uq_mgr->resume_work);
mutex_lock(&uq_mgr->userq_mutex);
queue = amdgpu_userq_find(uq_mgr, queue_id);
if (!queue) {
drm_dbg_driver(adev_to_drm(uq_mgr->adev), "Invalid queue id to destroy\n");
mutex_unlock(&uq_mgr->userq_mutex);
return -EINVAL;
}
amdgpu_userq_wait_for_last_fence(queue);
/* Cancel any pending hang detection work and cleanup */
if (queue->hang_detect_fence) {
@ -672,7 +655,7 @@ amdgpu_userq_destroy(struct drm_file *filp, int queue_id)
drm_warn(adev_to_drm(uq_mgr->adev), "trying to destroy a HW mapping userq\n");
queue->state = AMDGPU_USERQ_STATE_HUNG;
}
amdgpu_userq_cleanup(queue, queue_id);
amdgpu_userq_cleanup(queue);
mutex_unlock(&uq_mgr->userq_mutex);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@ -680,6 +663,37 @@ amdgpu_userq_destroy(struct drm_file *filp, int queue_id)
return r;
}
static void amdgpu_userq_kref_destroy(struct kref *kref)
{
int r;
struct amdgpu_usermode_queue *queue =
container_of(kref, struct amdgpu_usermode_queue, refcount);
struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr;
r = amdgpu_userq_destroy(uq_mgr, queue);
if (r)
drm_file_err(uq_mgr->file, "Failed to destroy usermode queue %d\n", r);
}
struct amdgpu_usermode_queue *amdgpu_userq_get(struct amdgpu_userq_mgr *uq_mgr, u32 qid)
{
struct amdgpu_usermode_queue *queue;
xa_lock(&uq_mgr->userq_xa);
queue = xa_load(&uq_mgr->userq_xa, qid);
if (queue)
kref_get(&queue->refcount);
xa_unlock(&uq_mgr->userq_xa);
return queue;
}
void amdgpu_userq_put(struct amdgpu_usermode_queue *queue)
{
if (queue)
kref_put(&queue->refcount, amdgpu_userq_kref_destroy);
}
static int amdgpu_userq_priority_permit(struct drm_file *filp,
int priority)
{
@ -834,6 +848,9 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
goto unlock;
}
/* drop this refcount during queue destroy */
kref_init(&queue->refcount);
/* Wait for mode-1 reset to complete */
down_read(&adev->reset_domain->sem);
r = xa_err(xa_store_irq(&adev->userq_doorbell_xa, index, queue, GFP_KERNEL));
@ -985,7 +1002,9 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp)
{
union drm_amdgpu_userq *args = data;
int r;
struct amdgpu_fpriv *fpriv = filp->driver_priv;
struct amdgpu_usermode_queue *queue;
int r = 0;
if (!amdgpu_userq_enabled(dev))
return -ENOTSUPP;
@ -1000,11 +1019,16 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
drm_file_err(filp, "Failed to create usermode queue\n");
break;
case AMDGPU_USERQ_OP_FREE:
r = amdgpu_userq_destroy(filp, args->in.queue_id);
if (r)
drm_file_err(filp, "Failed to destroy usermode queue\n");
case AMDGPU_USERQ_OP_FREE: {
xa_lock(&fpriv->userq_mgr.userq_xa);
queue = __xa_erase(&fpriv->userq_mgr.userq_xa, args->in.queue_id);
xa_unlock(&fpriv->userq_mgr.userq_xa);
if (!queue)
return -ENOENT;
amdgpu_userq_put(queue);
break;
}
default:
drm_dbg_driver(dev, "Invalid user queue op specified: %d\n", args->in.op);
@ -1023,16 +1047,23 @@ amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr)
/* Resume all the queues for this process */
xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
queue = amdgpu_userq_get(uq_mgr, queue_id);
if (!queue)
continue;
if (!amdgpu_userq_buffer_vas_mapped(queue)) {
drm_file_err(uq_mgr->file,
"trying restore queue without va mapping\n");
queue->state = AMDGPU_USERQ_STATE_INVALID_VA;
amdgpu_userq_put(queue);
continue;
}
r = amdgpu_userq_restore_helper(queue);
if (r)
ret = r;
amdgpu_userq_put(queue);
}
if (ret)
@ -1266,9 +1297,13 @@ amdgpu_userq_evict_all(struct amdgpu_userq_mgr *uq_mgr)
amdgpu_userq_detect_and_reset_queues(uq_mgr);
/* Try to unmap all the queues in this process ctx */
xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
queue = amdgpu_userq_get(uq_mgr, queue_id);
if (!queue)
continue;
r = amdgpu_userq_preempt_helper(queue);
if (r)
ret = r;
amdgpu_userq_put(queue);
}
if (ret)
@ -1301,16 +1336,24 @@ amdgpu_userq_wait_for_signal(struct amdgpu_userq_mgr *uq_mgr)
int ret;
xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
queue = amdgpu_userq_get(uq_mgr, queue_id);
if (!queue)
continue;
struct dma_fence *f = queue->last_fence;
if (!f || dma_fence_is_signaled(f))
if (!f || dma_fence_is_signaled(f)) {
amdgpu_userq_put(queue);
continue;
}
ret = dma_fence_wait_timeout(f, true, msecs_to_jiffies(100));
if (ret <= 0) {
drm_file_err(uq_mgr->file, "Timed out waiting for fence=%llu:%llu\n",
f->context, f->seqno);
amdgpu_userq_put(queue);
return -ETIMEDOUT;
}
amdgpu_userq_put(queue);
}
return 0;
@ -1361,20 +1404,23 @@ int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct drm_file *f
void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr)
{
struct amdgpu_usermode_queue *queue;
unsigned long queue_id;
unsigned long queue_id = 0;
cancel_delayed_work_sync(&userq_mgr->resume_work);
for (;;) {
xa_lock(&userq_mgr->userq_xa);
queue = xa_find(&userq_mgr->userq_xa, &queue_id, ULONG_MAX,
XA_PRESENT);
if (queue)
__xa_erase(&userq_mgr->userq_xa, queue_id);
xa_unlock(&userq_mgr->userq_xa);
mutex_lock(&userq_mgr->userq_mutex);
amdgpu_userq_detect_and_reset_queues(userq_mgr);
xa_for_each(&userq_mgr->userq_xa, queue_id, queue) {
amdgpu_userq_wait_for_last_fence(queue);
amdgpu_userq_unmap_helper(queue);
amdgpu_userq_cleanup(queue, queue_id);
if (!queue)
break;
amdgpu_userq_put(queue);
}
xa_destroy(&userq_mgr->userq_xa);
mutex_unlock(&userq_mgr->userq_mutex);
mutex_destroy(&userq_mgr->userq_mutex);
}

View file

@ -74,6 +74,7 @@ struct amdgpu_usermode_queue {
struct dentry *debugfs_queue;
struct delayed_work hang_detect_work;
struct dma_fence *hang_detect_fence;
struct kref refcount;
struct list_head userq_va_list;
};
@ -112,6 +113,9 @@ struct amdgpu_db_info {
struct amdgpu_userq_obj *db_obj;
};
struct amdgpu_usermode_queue *amdgpu_userq_get(struct amdgpu_userq_mgr *uq_mgr, u32 qid);
void amdgpu_userq_put(struct amdgpu_usermode_queue *queue);
int amdgpu_userq_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct drm_file *file_priv,

View file

@ -466,7 +466,7 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data,
struct drm_amdgpu_userq_signal *args = data;
struct drm_gem_object **gobj_write = NULL;
struct drm_gem_object **gobj_read = NULL;
struct amdgpu_usermode_queue *queue;
struct amdgpu_usermode_queue *queue = NULL;
struct amdgpu_userq_fence *userq_fence;
struct drm_syncobj **syncobj = NULL;
u32 *bo_handles_write, num_write_bo_handles;
@ -553,7 +553,7 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data,
}
/* Retrieve the user queue */
queue = xa_load(&userq_mgr->userq_xa, args->queue_id);
queue = amdgpu_userq_get(userq_mgr, args->queue_id);
if (!queue) {
r = -ENOENT;
goto put_gobj_write;
@ -648,6 +648,9 @@ free_syncobj:
free_syncobj_handles:
kfree(syncobj_handles);
if (queue)
amdgpu_userq_put(queue);
return r;
}
@ -660,7 +663,7 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
struct drm_amdgpu_userq_wait *wait_info = data;
struct amdgpu_fpriv *fpriv = filp->driver_priv;
struct amdgpu_userq_mgr *userq_mgr = &fpriv->userq_mgr;
struct amdgpu_usermode_queue *waitq;
struct amdgpu_usermode_queue *waitq = NULL;
struct drm_gem_object **gobj_write;
struct drm_gem_object **gobj_read;
struct dma_fence **fences = NULL;
@ -926,7 +929,7 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
*/
num_fences = dma_fence_dedup_array(fences, num_fences);
waitq = xa_load(&userq_mgr->userq_xa, wait_info->waitq_id);
waitq = amdgpu_userq_get(userq_mgr, wait_info->waitq_id);
if (!waitq) {
r = -EINVAL;
goto free_fences;
@ -983,32 +986,14 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
r = -EFAULT;
goto free_fences;
}
kfree(fences);
kfree(fence_info);
}
drm_exec_fini(&exec);
for (i = 0; i < num_read_bo_handles; i++)
drm_gem_object_put(gobj_read[i]);
kfree(gobj_read);
for (i = 0; i < num_write_bo_handles; i++)
drm_gem_object_put(gobj_write[i]);
kfree(gobj_write);
kfree(timeline_points);
kfree(timeline_handles);
kfree(syncobj_handles);
kfree(bo_handles_write);
kfree(bo_handles_read);
return 0;
free_fences:
if (fences) {
while (num_fences-- > 0)
dma_fence_put(fences[num_fences]);
kfree(fences);
}
free_fence_info:
kfree(fence_info);
exec_fini:
@ -1032,5 +1017,8 @@ free_bo_handles_write:
free_bo_handles_read:
kfree(bo_handles_read);
if (waitq)
amdgpu_userq_put(waitq);
return r;
}

View file

@ -69,12 +69,12 @@ static int psp_v15_0_0_ring_stop(struct psp_context *psp,
0x80000000, 0x80000000, false);
} else {
/* Write the ring destroy command*/
WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_64,
WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64,
GFX_CTRL_CMD_ID_DESTROY_RINGS);
/* there might be handshake issue with hardware which needs delay */
mdelay(20);
/* Wait for response flag (bit 31) */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_64),
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64),
0x80000000, 0x80000000, false);
}
@ -116,7 +116,7 @@ static int psp_v15_0_0_ring_create(struct psp_context *psp,
} else {
/* Wait for sOS ready for ring creation */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_64),
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64),
0x80000000, 0x80000000, false);
if (ret) {
DRM_ERROR("Failed to wait for trust OS ready for ring creation\n");
@ -125,23 +125,23 @@ static int psp_v15_0_0_ring_create(struct psp_context *psp,
/* Write low address of the ring to C2PMSG_69 */
psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr);
WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_69, psp_ring_reg);
WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_69, psp_ring_reg);
/* Write high address of the ring to C2PMSG_70 */
psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr);
WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_70, psp_ring_reg);
WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_70, psp_ring_reg);
/* Write size of ring to C2PMSG_71 */
psp_ring_reg = ring->ring_size;
WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_71, psp_ring_reg);
WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_71, psp_ring_reg);
/* Write the ring initialization command to C2PMSG_64 */
psp_ring_reg = ring_type;
psp_ring_reg = psp_ring_reg << 16;
WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_64, psp_ring_reg);
WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64, psp_ring_reg);
/* there might be handshake issue with hardware which needs delay */
mdelay(20);
/* Wait for response flag (bit 31) in C2PMSG_64 */
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_SMN_C2PMSG_64),
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_64),
0x80000000, 0x8000FFFF, false);
}
@ -174,7 +174,7 @@ static uint32_t psp_v15_0_0_ring_get_wptr(struct psp_context *psp)
if (amdgpu_sriov_vf(adev))
data = RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_102);
else
data = RREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_67);
data = RREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_67);
return data;
}
@ -188,7 +188,7 @@ static void psp_v15_0_0_ring_set_wptr(struct psp_context *psp, uint32_t value)
WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_101,
GFX_CTRL_CMD_ID_CONSUME_CMD);
} else
WREG32_SOC15(MP0, 0, regMPASP_SMN_C2PMSG_67, value);
WREG32_SOC15(MP0, 0, regMPASP_PCRU1_MPASP_C2PMSG_67, value);
}
static const struct psp_funcs psp_v15_0_0_funcs = {

View file

@ -858,7 +858,9 @@ static int soc21_common_early_init(struct amdgpu_ip_block *ip_block)
AMD_CG_SUPPORT_IH_CG |
AMD_CG_SUPPORT_BIF_MGCG |
AMD_CG_SUPPORT_BIF_LS;
adev->pg_flags = AMD_PG_SUPPORT_VCN |
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 + 0x1;

View file

@ -1706,6 +1706,7 @@ __set_dm_plane_colorop_3dlut(struct drm_plane_state *plane_state,
struct dc_transfer_func *tf = &dc_plane_state->in_shaper_func;
struct drm_atomic_state *state = plane_state->state;
const struct amdgpu_device *adev = drm_to_adev(colorop->dev);
bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut || adev->dm.dc->caps.color.mpc.preblend;
const struct drm_device *dev = colorop->dev;
const struct drm_color_lut32 *lut3d;
uint32_t lut3d_size;
@ -1722,7 +1723,7 @@ __set_dm_plane_colorop_3dlut(struct drm_plane_state *plane_state,
}
if (colorop_state && !colorop_state->bypass && colorop->type == DRM_COLOROP_3D_LUT) {
if (!adev->dm.dc->caps.color.dpp.hw_3d_lut) {
if (!has_3dlut) {
drm_dbg(dev, "3D LUT is not supported by hardware\n");
return -EINVAL;
}
@ -1875,6 +1876,7 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
struct drm_colorop *colorop = plane_state->color_pipeline;
struct drm_device *dev = plane_state->plane->dev;
struct amdgpu_device *adev = drm_to_adev(dev);
bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut || adev->dm.dc->caps.color.mpc.preblend;
int ret;
/* 1D Curve - DEGAM TF */
@ -1907,7 +1909,7 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
if (ret)
return ret;
if (adev->dm.dc->caps.color.dpp.hw_3d_lut) {
if (has_3dlut) {
/* 1D Curve & LUT - SHAPER TF & LUT */
colorop = colorop->next;
if (!colorop) {

View file

@ -60,6 +60,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS];
struct drm_device *dev = plane->dev;
struct amdgpu_device *adev = drm_to_adev(dev);
bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut || adev->dm.dc->caps.color.mpc.preblend;
int ret;
int i = 0;
@ -112,7 +113,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
i++;
if (adev->dm.dc->caps.color.dpp.hw_3d_lut) {
if (has_3dlut) {
/* 1D curve - SHAPER TF */
ops[i] = kzalloc_obj(*ops[0]);
if (!ops[i]) {

View file

@ -765,13 +765,13 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
dm->adev->mode_info.crtcs[crtc_index] = acrtc;
/* Don't enable DRM CRTC degamma property for
* 1. Degamma is replaced by color pipeline.
* 2. DCE since it doesn't support programmable degamma anywhere.
* 3. DCN401 since pre-blending degamma LUT doesn't apply to cursor.
* 1. DCE since it doesn't support programmable degamma anywhere.
* 2. DCN401 since pre-blending degamma LUT doesn't apply to cursor.
* Note: DEGAMMA properties are created even if the primary plane has the
* COLOR_PIPELINE property. User space can use either the DEGAMMA properties
* or the COLOR_PIPELINE property. An atomic commit which attempts to enable
* both is rejected.
*/
if (plane->color_pipeline_property)
has_degamma = false;
else
has_degamma = dm->adev->dm.dc->caps.color.dpp.dcn_arch &&
dm->adev->dm.dc->ctx->dce_version != DCN_VERSION_4_01;

View file

@ -1256,6 +1256,14 @@ static int amdgpu_dm_plane_atomic_check(struct drm_plane *plane,
if (ret)
return ret;
/* Reject commits that attempt to use both COLOR_PIPELINE and CRTC DEGAMMA_LUT */
if (new_plane_state->color_pipeline && new_crtc_state->degamma_lut) {
drm_dbg_atomic(plane->dev,
"[PLANE:%d:%s] COLOR_PIPELINE and CRTC DEGAMMA_LUT cannot be enabled simultaneously\n",
plane->base.id, plane->name);
return -EINVAL;
}
ret = amdgpu_dm_plane_fill_dc_scaling_info(adev, new_plane_state, &scaling_info);
if (ret)
return ret;

View file

@ -72,7 +72,11 @@ void dcn401_initialize_min_clocks(struct dc *dc)
* audio corruption. Read current DISPCLK from DENTIST and request the same
* freq to ensure that the timing is valid and unchanged.
*/
if (dc->clk_mgr->funcs->get_dispclk_from_dentist) {
clocks->dispclk_khz = dc->clk_mgr->funcs->get_dispclk_from_dentist(dc->clk_mgr);
} else {
clocks->dispclk_khz = dc->clk_mgr->boot_snapshot.dispclk * 1000;
}
}
clocks->ref_dtbclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dtbclk_mhz * 1000;
clocks->fclk_p_state_change_support = true;

View file

@ -82,6 +82,24 @@
#define regMPASP_SMN_IH_SW_INT_CTRL 0x0142
#define regMPASP_SMN_IH_SW_INT_CTRL_BASE_IDX 0
// addressBlock: mp_SmuMpASPPub_PcruDec
// base address: 0x3800000
#define regMPASP_PCRU1_MPASP_C2PMSG_64 0x4280
#define regMPASP_PCRU1_MPASP_C2PMSG_64_BASE_IDX 3
#define regMPASP_PCRU1_MPASP_C2PMSG_65 0x4281
#define regMPASP_PCRU1_MPASP_C2PMSG_65_BASE_IDX 3
#define regMPASP_PCRU1_MPASP_C2PMSG_66 0x4282
#define regMPASP_PCRU1_MPASP_C2PMSG_66_BASE_IDX 3
#define regMPASP_PCRU1_MPASP_C2PMSG_67 0x4283
#define regMPASP_PCRU1_MPASP_C2PMSG_67_BASE_IDX 3
#define regMPASP_PCRU1_MPASP_C2PMSG_68 0x4284
#define regMPASP_PCRU1_MPASP_C2PMSG_68_BASE_IDX 3
#define regMPASP_PCRU1_MPASP_C2PMSG_69 0x4285
#define regMPASP_PCRU1_MPASP_C2PMSG_69_BASE_IDX 3
#define regMPASP_PCRU1_MPASP_C2PMSG_70 0x4286
#define regMPASP_PCRU1_MPASP_C2PMSG_70_BASE_IDX 3
#define regMPASP_PCRU1_MPASP_C2PMSG_71 0x4287
#define regMPASP_PCRU1_MPASP_C2PMSG_71_BASE_IDX 3
// addressBlock: mp_SmuMp1_SmnDec
// base address: 0x0

View file

@ -2034,6 +2034,7 @@ static ssize_t smu_v13_0_0_get_gpu_metrics(struct smu_context *smu,
smu, SMU_DRIVER_TABLE_GPU_METRICS);
SmuMetricsExternal_t metrics_ext;
SmuMetrics_t *metrics = &metrics_ext.SmuMetrics;
uint32_t mp1_ver = amdgpu_ip_version(smu->adev, MP1_HWIP, 0);
int ret = 0;
ret = smu_cmn_get_metrics_table(smu,
@ -2058,7 +2059,12 @@ static ssize_t smu_v13_0_0_get_gpu_metrics(struct smu_context *smu,
metrics->Vcn1ActivityPercentage);
gpu_metrics->average_socket_power = metrics->AverageSocketPower;
if ((mp1_ver == IP_VERSION(13, 0, 0) && smu->smc_fw_version <= 0x004e1e00) ||
(mp1_ver == IP_VERSION(13, 0, 10) && smu->smc_fw_version <= 0x00500800))
gpu_metrics->energy_accumulator = metrics->EnergyAccumulator;
else
gpu_metrics->energy_accumulator = UINT_MAX;
if (metrics->AverageGfxActivity <= SMU_13_0_0_BUSY_THRESHOLD)
gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs;

View file

@ -2065,7 +2065,8 @@ static ssize_t smu_v13_0_7_get_gpu_metrics(struct smu_context *smu,
metrics->Vcn1ActivityPercentage);
gpu_metrics->average_socket_power = metrics->AverageSocketPower;
gpu_metrics->energy_accumulator = metrics->EnergyAccumulator;
gpu_metrics->energy_accumulator = smu->smc_fw_version <= 0x00521400 ?
metrics->EnergyAccumulator : UINT_MAX;
if (metrics->AverageGfxActivity <= SMU_13_0_7_BUSY_THRESHOLD)
gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs;

View file

@ -480,18 +480,8 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
.start = start,
.end = end,
.pgmap_owner = pagemap->owner,
/*
* FIXME: MIGRATE_VMA_SELECT_DEVICE_PRIVATE intermittently
* causes 'xe_exec_system_allocator --r *race*no*' to trigger aa
* engine reset and a hard hang due to getting stuck on a folio
* lock. This should work and needs to be root-caused. The only
* downside of not selecting MIGRATE_VMA_SELECT_DEVICE_PRIVATE
* is that device-to-device migrations wont work; instead,
* memory will bounce through system memory. This path should be
* rare and only occur when the madvise attributes of memory are
* changed or atomics are being used.
*/
.flags = MIGRATE_VMA_SELECT_SYSTEM | MIGRATE_VMA_SELECT_DEVICE_COHERENT,
.flags = MIGRATE_VMA_SELECT_SYSTEM | MIGRATE_VMA_SELECT_DEVICE_COHERENT |
MIGRATE_VMA_SELECT_DEVICE_PRIVATE,
};
unsigned long i, npages = npages_in_range(start, end);
unsigned long own_pages = 0, migrated_pages = 0;

View file

@ -1307,9 +1307,14 @@ static bool psr2_granularity_check(struct intel_crtc_state *crtc_state,
u16 sink_y_granularity = crtc_state->has_panel_replay ?
connector->dp.panel_replay_caps.su_y_granularity :
connector->dp.psr_caps.su_y_granularity;
u16 sink_w_granularity = crtc_state->has_panel_replay ?
connector->dp.panel_replay_caps.su_w_granularity :
connector->dp.psr_caps.su_w_granularity;
u16 sink_w_granularity;
if (crtc_state->has_panel_replay)
sink_w_granularity = connector->dp.panel_replay_caps.su_w_granularity ==
DP_PANEL_REPLAY_FULL_LINE_GRANULARITY ?
crtc_hdisplay : connector->dp.panel_replay_caps.su_w_granularity;
else
sink_w_granularity = connector->dp.psr_caps.su_w_granularity;
/* PSR2 HW only send full lines so we only need to validate the width */
if (crtc_hdisplay % sink_w_granularity)

View file

@ -1230,6 +1230,9 @@ nouveau_connector_aux_xfer(struct drm_dp_aux *obj, struct drm_dp_aux_msg *msg)
u8 size = msg->size;
int ret;
if (pm_runtime_suspended(nv_connector->base.dev->dev))
return -EBUSY;
nv_encoder = find_encoder(&nv_connector->base, DCB_OUTPUT_DP);
if (!nv_encoder)
return -ENODEV;

View file

@ -893,14 +893,15 @@ panthor_queue_get_syncwait_obj(struct panthor_group *group, struct panthor_queue
out_sync:
/* Make sure the CPU caches are invalidated before the seqno is read.
* drm_gem_shmem_sync() is a NOP if map_wc=true, so no need to check
* panthor_gem_sync() is a NOP if map_wc=true, so no need to check
* it here.
*/
panthor_gem_sync(&bo->base.base, queue->syncwait.offset,
panthor_gem_sync(&bo->base.base,
DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE,
queue->syncwait.offset,
queue->syncwait.sync64 ?
sizeof(struct panthor_syncobj_64b) :
sizeof(struct panthor_syncobj_32b),
DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE);
sizeof(struct panthor_syncobj_32b));
return queue->syncwait.kmap + queue->syncwait.offset;

View file

@ -1122,6 +1122,7 @@ static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *device)
{
struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
int bpp;
int ret;
if (device->lanes > dsi->num_data_lanes) {
@ -1131,7 +1132,8 @@ static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host,
return -EINVAL;
}
switch (mipi_dsi_pixel_format_to_bpp(device->format)) {
bpp = mipi_dsi_pixel_format_to_bpp(device->format);
switch (bpp) {
case 24:
break;
case 18:
@ -1162,6 +1164,18 @@ static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host,
drm_bridge_add(&dsi->bridge);
/*
* Report the required division ratio setting for the MIPI clock dividers.
*
* vclk * bpp = hsclk * 8 * num_lanes
*
* vclk * DSI_AB_divider = hsclk * 16
*
* which simplifies to...
* DSI_AB_divider = bpp * 2 / num_lanes
*/
rzg2l_cpg_dsi_div_set_divider(bpp * 2 / dsi->lanes, PLL5_TARGET_DSI);
return 0;
}

View file

@ -361,6 +361,7 @@ static void drm_sched_run_free_queue(struct drm_gpu_scheduler *sched)
/**
* drm_sched_job_done - complete a job
* @s_job: pointer to the job which is done
* @result: 0 on success, -ERRNO on error
*
* Finish the job's fence and resubmit the work items.
*/

View file

@ -737,6 +737,7 @@ static int ssd130x_update_rect(struct ssd130x_device *ssd130x,
unsigned int height = drm_rect_height(rect);
unsigned int line_length = DIV_ROUND_UP(width, 8);
unsigned int page_height = SSD130X_PAGE_HEIGHT;
u8 page_start = ssd130x->page_offset + y / page_height;
unsigned int pages = DIV_ROUND_UP(height, page_height);
struct drm_device *drm = &ssd130x->drm;
u32 array_idx = 0;
@ -774,14 +775,11 @@ static int ssd130x_update_rect(struct ssd130x_device *ssd130x,
*/
if (!ssd130x->page_address_mode) {
u8 page_start;
/* Set address range for horizontal addressing mode */
ret = ssd130x_set_col_range(ssd130x, ssd130x->col_offset + x, width);
if (ret < 0)
return ret;
page_start = ssd130x->page_offset + y / page_height;
ret = ssd130x_set_page_range(ssd130x, page_start, pages);
if (ret < 0)
return ret;
@ -813,7 +811,7 @@ static int ssd130x_update_rect(struct ssd130x_device *ssd130x,
*/
if (ssd130x->page_address_mode) {
ret = ssd130x_set_page_pos(ssd130x,
ssd130x->page_offset + i,
page_start + i,
ssd130x->col_offset + x);
if (ret < 0)
return ret;

View file

@ -222,13 +222,13 @@ static void ttm_bo_reserve_interrupted(struct kunit *test)
KUNIT_FAIL(test, "Couldn't create ttm bo reserve task\n");
/* Take a lock so the threaded reserve has to wait */
mutex_lock(&bo->base.resv->lock.base);
dma_resv_lock(bo->base.resv, NULL);
wake_up_process(task);
msleep(20);
err = kthread_stop(task);
mutex_unlock(&bo->base.resv->lock.base);
dma_resv_unlock(bo->base.resv);
KUNIT_ASSERT_EQ(test, err, -ERESTARTSYS);
}

View file

@ -1107,8 +1107,7 @@ struct ttm_bo_swapout_walk {
static s64
ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
{
struct ttm_resource *res = bo->resource;
struct ttm_place place = { .mem_type = res->mem_type };
struct ttm_place place = { .mem_type = bo->resource->mem_type };
struct ttm_bo_swapout_walk *swapout_walk =
container_of(walk, typeof(*swapout_walk), walk);
struct ttm_operation_ctx *ctx = walk->arg.ctx;
@ -1148,7 +1147,7 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
/*
* Move to system cached
*/
if (res->mem_type != TTM_PL_SYSTEM) {
if (bo->resource->mem_type != TTM_PL_SYSTEM) {
struct ttm_resource *evict_mem;
struct ttm_place hop;
@ -1180,15 +1179,15 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
if (ttm_tt_is_populated(tt)) {
spin_lock(&bdev->lru_lock);
ttm_resource_del_bulk_move(res, bo);
ttm_resource_del_bulk_move(bo->resource, bo);
spin_unlock(&bdev->lru_lock);
ret = ttm_tt_swapout(bdev, tt, swapout_walk->gfp_flags);
spin_lock(&bdev->lru_lock);
if (ret)
ttm_resource_add_bulk_move(res, bo);
ttm_resource_move_to_lru_tail(res);
ttm_resource_add_bulk_move(bo->resource, bo);
ttm_resource_move_to_lru_tail(bo->resource);
spin_unlock(&bdev->lru_lock);
}

View file

@ -17,7 +17,7 @@ static inline bool ttm_pool_uses_dma32(struct ttm_pool *pool)
return pool->alloc_flags & TTM_ALLOCATION_POOL_USE_DMA32;
}
static inline bool ttm_pool_beneficial_order(struct ttm_pool *pool)
static inline unsigned int ttm_pool_beneficial_order(struct ttm_pool *pool)
{
return pool->alloc_flags & 0xff;
}

View file

@ -830,6 +830,7 @@ static void xe_config_device_release(struct config_item *item)
mutex_destroy(&dev->lock);
kfree(dev->config.ctx_restore_mid_bb[0].cs);
kfree(dev->config.ctx_restore_post_bb[0].cs);
kfree(dev);
}

View file

@ -266,6 +266,16 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,
return q;
}
static void __xe_exec_queue_fini(struct xe_exec_queue *q)
{
int i;
q->ops->fini(q);
for (i = 0; i < q->width; ++i)
xe_lrc_put(q->lrc[i]);
}
static int __xe_exec_queue_init(struct xe_exec_queue *q, u32 exec_queue_flags)
{
int i, err;
@ -320,21 +330,10 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q, u32 exec_queue_flags)
return 0;
err_lrc:
for (i = i - 1; i >= 0; --i)
xe_lrc_put(q->lrc[i]);
__xe_exec_queue_fini(q);
return err;
}
static void __xe_exec_queue_fini(struct xe_exec_queue *q)
{
int i;
q->ops->fini(q);
for (i = 0; i < q->width; ++i)
xe_lrc_put(q->lrc[i]);
}
struct xe_exec_queue *xe_exec_queue_create(struct xe_device *xe, struct xe_vm *vm,
u32 logical_mask, u16 width,
struct xe_hw_engine *hwe, u32 flags,

View file

@ -435,15 +435,11 @@ static int proxy_channel_alloc(struct xe_gsc *gsc)
return 0;
}
static void xe_gsc_proxy_remove(void *arg)
static void xe_gsc_proxy_stop(struct xe_gsc *gsc)
{
struct xe_gsc *gsc = arg;
struct xe_gt *gt = gsc_to_gt(gsc);
struct xe_device *xe = gt_to_xe(gt);
if (!gsc->proxy.component_added)
return;
/* disable HECI2 IRQs */
scoped_guard(xe_pm_runtime, xe) {
CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GSC);
@ -455,6 +451,30 @@ static void xe_gsc_proxy_remove(void *arg)
}
xe_gsc_wait_for_worker_completion(gsc);
gsc->proxy.started = false;
}
static void xe_gsc_proxy_remove(void *arg)
{
struct xe_gsc *gsc = arg;
struct xe_gt *gt = gsc_to_gt(gsc);
struct xe_device *xe = gt_to_xe(gt);
if (!gsc->proxy.component_added)
return;
/*
* GSC proxy start is an async process that can be ongoing during
* Xe module load/unload. Using devm managed action to register
* xe_gsc_proxy_stop could cause issues if Xe module unload has
* already started when the action is registered, potentially leading
* to the cleanup being called at the wrong time. Therefore, instead
* of registering a separate devm action to undo what is done in
* proxy start, we call it from here, but only if the start has
* completed successfully (tracked with the 'started' flag).
*/
if (gsc->proxy.started)
xe_gsc_proxy_stop(gsc);
component_del(xe->drm.dev, &xe_gsc_proxy_component_ops);
gsc->proxy.component_added = false;
@ -510,6 +530,7 @@ int xe_gsc_proxy_init(struct xe_gsc *gsc)
*/
int xe_gsc_proxy_start(struct xe_gsc *gsc)
{
struct xe_gt *gt = gsc_to_gt(gsc);
int err;
/* enable the proxy interrupt in the GSC shim layer */
@ -521,12 +542,18 @@ int xe_gsc_proxy_start(struct xe_gsc *gsc)
*/
err = xe_gsc_proxy_request_handler(gsc);
if (err)
return err;
goto err_irq_disable;
if (!xe_gsc_proxy_init_done(gsc)) {
xe_gt_err(gsc_to_gt(gsc), "GSC FW reports proxy init not completed\n");
return -EIO;
xe_gt_err(gt, "GSC FW reports proxy init not completed\n");
err = -EIO;
goto err_irq_disable;
}
gsc->proxy.started = true;
return 0;
err_irq_disable:
gsc_proxy_irq_toggle(gsc, false);
return err;
}

View file

@ -58,6 +58,8 @@ struct xe_gsc {
struct mutex mutex;
/** @proxy.component_added: whether the component has been added */
bool component_added;
/** @proxy.started: whether the proxy has been started */
bool started;
/** @proxy.bo: object to store message to and from the GSC */
struct xe_bo *bo;
/** @proxy.to_gsc: map of the memory used to send messages to the GSC */

View file

@ -75,6 +75,7 @@ static inline struct xe_lrc *xe_lrc_get(struct xe_lrc *lrc)
*/
static inline void xe_lrc_put(struct xe_lrc *lrc)
{
if (lrc)
kref_put(&lrc->refcount, xe_lrc_destroy);
}

View file

@ -98,10 +98,12 @@ int xe_reg_sr_add(struct xe_reg_sr *sr,
*pentry = *e;
ret = xa_err(xa_store(&sr->xa, idx, pentry, GFP_KERNEL));
if (ret)
goto fail;
goto fail_free;
return 0;
fail_free:
kfree(pentry);
fail:
xe_gt_err(gt,
"discarding save-restore reg %04lx (clear: %08x, set: %08x, masked: %s, mcr: %s): ret=%d\n",

View file

@ -280,6 +280,9 @@ static void __emit_job_gen12_simple(struct xe_sched_job *job, struct xe_lrc *lrc
i = emit_bb_start(batch_addr, ppgtt_flag, dw, i);
/* Don't preempt fence signaling */
dw[i++] = MI_ARB_ON_OFF | MI_ARB_DISABLE;
if (job->user_fence.used) {
i = emit_flush_dw(dw, i);
i = emit_store_imm_ppgtt_posted(job->user_fence.addr,
@ -345,6 +348,9 @@ static void __emit_job_gen12_video(struct xe_sched_job *job, struct xe_lrc *lrc,
i = emit_bb_start(batch_addr, ppgtt_flag, dw, i);
/* Don't preempt fence signaling */
dw[i++] = MI_ARB_ON_OFF | MI_ARB_DISABLE;
if (job->user_fence.used) {
i = emit_flush_dw(dw, i);
i = emit_store_imm_ppgtt_posted(job->user_fence.addr,
@ -397,6 +403,9 @@ static void __emit_job_gen12_render_compute(struct xe_sched_job *job,
i = emit_bb_start(batch_addr, ppgtt_flag, dw, i);
/* Don't preempt fence signaling */
dw[i++] = MI_ARB_ON_OFF | MI_ARB_DISABLE;
i = emit_render_cache_flush(job, dw, i);
if (job->user_fence.used)

View file

@ -453,7 +453,7 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
madvise_range.num_vmas,
args->atomic.val)) {
err = -EINVAL;
goto madv_fini;
goto free_vmas;
}
}
@ -490,6 +490,7 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
err_fini:
if (madvise_range.has_bo_vmas)
drm_exec_fini(&exec);
free_vmas:
kfree(madvise_range.vmas);
madvise_range.vmas = NULL;
madv_fini:

View file

@ -241,11 +241,12 @@ static const struct xe_rtp_entry_sr gt_was[] = {
{ XE_RTP_NAME("16025250150"),
XE_RTP_RULES(GRAPHICS_VERSION(2001)),
XE_RTP_ACTIONS(SET(LSN_VC_REG2,
LSN_LNI_WGT(1) |
LSN_LNE_WGT(1) |
LSN_DIM_X_WGT(1) |
LSN_DIM_Y_WGT(1) |
XE_RTP_ACTIONS(FIELD_SET(LSN_VC_REG2,
LSN_LNI_WGT_MASK | LSN_LNE_WGT_MASK |
LSN_DIM_X_WGT_MASK | LSN_DIM_Y_WGT_MASK |
LSN_DIM_Z_WGT_MASK,
LSN_LNI_WGT(1) | LSN_LNE_WGT(1) |
LSN_DIM_X_WGT(1) | LSN_DIM_Y_WGT(1) |
LSN_DIM_Z_WGT(1)))
},

View file

@ -571,6 +571,8 @@
# define DP_PANEL_REPLAY_LINK_OFF_SUPPORTED_IN_PR_AFTER_ADAPTIVE_SYNC_SDP (1 << 7)
#define DP_PANEL_REPLAY_CAP_X_GRANULARITY 0xb2
# define DP_PANEL_REPLAY_FULL_LINE_GRANULARITY 0xffff
#define DP_PANEL_REPLAY_CAP_Y_GRANULARITY 0xb4
/* Link Configuration */

View file

@ -65,7 +65,7 @@ bool isolate_folio_to_list(struct folio *folio, struct list_head *list);
int migrate_huge_page_move_mapping(struct address_space *mapping,
struct folio *dst, struct folio *src);
void migration_entry_wait_on_locked(softleaf_t entry, spinlock_t *ptl)
void softleaf_entry_wait_on_locked(softleaf_t entry, spinlock_t *ptl)
__releases(ptl);
void folio_migrate_flags(struct folio *newfolio, struct folio *folio);
int folio_migrate_mapping(struct address_space *mapping,
@ -97,6 +97,14 @@ static inline int set_movable_ops(const struct movable_operations *ops, enum pag
return -ENOSYS;
}
static inline void softleaf_entry_wait_on_locked(softleaf_t entry, spinlock_t *ptl)
__releases(ptl)
{
WARN_ON_ONCE(1);
spin_unlock(ptl);
}
#endif /* CONFIG_MIGRATION */
#ifdef CONFIG_NUMA_BALANCING

View file

@ -20,6 +20,7 @@
#ifndef _DMA_BUF_UAPI_H_
#define _DMA_BUF_UAPI_H_
#include <linux/ioctl.h>
#include <linux/types.h>
/**

View file

@ -1379,14 +1379,16 @@ repeat:
#ifdef CONFIG_MIGRATION
/**
* migration_entry_wait_on_locked - Wait for a migration entry to be removed
* @entry: migration swap entry.
* softleaf_entry_wait_on_locked - Wait for a migration entry or
* device_private entry to be removed.
* @entry: migration or device_private swap entry.
* @ptl: already locked ptl. This function will drop the lock.
*
* Wait for a migration entry referencing the given page to be removed. This is
* Wait for a migration entry referencing the given page, or device_private
* entry referencing a dvice_private page to be unlocked. This is
* equivalent to folio_put_wait_locked(folio, TASK_UNINTERRUPTIBLE) except
* this can be called without taking a reference on the page. Instead this
* should be called while holding the ptl for the migration entry referencing
* should be called while holding the ptl for @entry referencing
* the page.
*
* Returns after unlocking the ptl.
@ -1394,7 +1396,7 @@ repeat:
* This follows the same logic as folio_wait_bit_common() so see the comments
* there.
*/
void migration_entry_wait_on_locked(softleaf_t entry, spinlock_t *ptl)
void softleaf_entry_wait_on_locked(softleaf_t entry, spinlock_t *ptl)
__releases(ptl)
{
struct wait_page_queue wait_page;
@ -1428,6 +1430,9 @@ void migration_entry_wait_on_locked(softleaf_t entry, spinlock_t *ptl)
* If a migration entry exists for the page the migration path must hold
* a valid reference to the page, and it must take the ptl to remove the
* migration entry. So the page is valid until the ptl is dropped.
* Similarly any path attempting to drop the last reference to a
* device-private page needs to grab the ptl to remove the device-private
* entry.
*/
spin_unlock(ptl);

View file

@ -4763,7 +4763,8 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
unlock_page(vmf->page);
put_page(vmf->page);
} else {
pte_unmap_unlock(vmf->pte, vmf->ptl);
pte_unmap(vmf->pte);
softleaf_entry_wait_on_locked(entry, vmf->ptl);
}
} else if (softleaf_is_hwpoison(entry)) {
ret = VM_FAULT_HWPOISON;

View file

@ -500,7 +500,7 @@ void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd,
if (!softleaf_is_migration(entry))
goto out;
migration_entry_wait_on_locked(entry, ptl);
softleaf_entry_wait_on_locked(entry, ptl);
return;
out:
spin_unlock(ptl);
@ -532,10 +532,10 @@ void migration_entry_wait_huge(struct vm_area_struct *vma, unsigned long addr, p
* If migration entry existed, safe to release vma lock
* here because the pgtable page won't be freed without the
* pgtable lock released. See comment right above pgtable
* lock release in migration_entry_wait_on_locked().
* lock release in softleaf_entry_wait_on_locked().
*/
hugetlb_vma_unlock_read(vma);
migration_entry_wait_on_locked(entry, ptl);
softleaf_entry_wait_on_locked(entry, ptl);
return;
}
@ -553,7 +553,7 @@ void pmd_migration_entry_wait(struct mm_struct *mm, pmd_t *pmd)
ptl = pmd_lock(mm, pmd);
if (!pmd_is_migration_entry(*pmd))
goto unlock;
migration_entry_wait_on_locked(softleaf_from_pmd(*pmd), ptl);
softleaf_entry_wait_on_locked(softleaf_from_pmd(*pmd), ptl);
return;
unlock:
spin_unlock(ptl);

View file

@ -176,7 +176,7 @@ static int migrate_vma_collect_huge_pmd(pmd_t *pmdp, unsigned long start,
}
if (softleaf_is_migration(entry)) {
migration_entry_wait_on_locked(entry, ptl);
softleaf_entry_wait_on_locked(entry, ptl);
spin_unlock(ptl);
return -EAGAIN;
}