Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

accel/amdxdna: Enhance runtime power management

Currently, pm_runtime_resume_and_get() is invoked in the driver's open
callback, and pm_runtime_put_autosuspend() is called in the close
callback. As a result, the device remains active whenever an application
opens it, even if no I/O is performed, leading to unnecessary power
consumption.

Move the runtime PM calls to the AIE2 callbacks that actually interact
with the hardware. The device will automatically suspend after 5 seconds
of inactivity (no hardware accesses and no pending commands), and it will
be resumed on the next hardware access.

Reviewed-by: Karol Wachowski <karol.wachowski@linux.intel.com>
Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
Link: https://lore.kernel.org/r/20250923152229.1303625-1-lizhi.hou@amd.com

Lizhi Hou 063db451 90315cd2

+264 -162
+1
drivers/accel/amdxdna/Makefile
··· 14 14 amdxdna_mailbox.o \ 15 15 amdxdna_mailbox_helper.o \ 16 16 amdxdna_pci_drv.o \ 17 + amdxdna_pm.o \ 17 18 amdxdna_sysfs.o \ 18 19 amdxdna_ubuf.o \ 19 20 npu1_regs.o \
+31 -11
drivers/accel/amdxdna/aie2_ctx.c
··· 21 21 #include "amdxdna_gem.h" 22 22 #include "amdxdna_mailbox.h" 23 23 #include "amdxdna_pci_drv.h" 24 + #include "amdxdna_pm.h" 24 25 25 26 static bool force_cmdlist; 26 27 module_param(force_cmdlist, bool, 0600); ··· 89 88 goto out; 90 89 } 91 90 92 - ret = aie2_config_cu(hwctx); 91 + ret = aie2_config_cu(hwctx, NULL); 93 92 if (ret) { 94 93 XDNA_ERR(xdna, "Config cu failed, ret %d", ret); 95 94 goto out; ··· 168 167 169 168 int aie2_hwctx_resume(struct amdxdna_client *client) 170 169 { 171 - struct amdxdna_dev *xdna = client->xdna; 172 - 173 170 /* 174 171 * The resume path cannot guarantee that mailbox channel can be 175 172 * regenerated. If this happen, when submit message to this 176 173 * mailbox channel, error will return. 177 174 */ 178 - drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock)); 179 175 return amdxdna_hwctx_walk(client, NULL, aie2_hwctx_resume_cb); 180 176 } 181 177 ··· 182 184 struct dma_fence *fence = job->fence; 183 185 184 186 trace_xdna_job(&job->base, job->hwctx->name, "signaled fence", job->seq); 187 + 188 + amdxdna_pm_suspend_put(job->hwctx->client->xdna); 185 189 job->hwctx->priv->completed++; 186 190 dma_fence_signal(fence); 187 191 ··· 531 531 .num_rqs = DRM_SCHED_PRIORITY_COUNT, 532 532 .credit_limit = HWCTX_MAX_CMDS, 533 533 .timeout = msecs_to_jiffies(HWCTX_MAX_TIMEOUT), 534 - .name = hwctx->name, 534 + .name = "amdxdna_js", 535 535 .dev = xdna->ddev.dev, 536 536 }; 537 537 struct drm_gpu_scheduler *sched; ··· 697 697 kfree(hwctx->cus); 698 698 } 699 699 700 + static int aie2_config_cu_resp_handler(void *handle, void __iomem *data, size_t size) 701 + { 702 + struct amdxdna_hwctx *hwctx = handle; 703 + 704 + amdxdna_pm_suspend_put(hwctx->client->xdna); 705 + return 0; 706 + } 707 + 700 708 static int aie2_hwctx_cu_config(struct amdxdna_hwctx *hwctx, void *buf, u32 size) 701 709 { 702 710 struct amdxdna_hwctx_param_config_cu *config = buf; ··· 736 728 if (!hwctx->cus) 737 729 return -ENOMEM; 738 730 739 - ret = aie2_config_cu(hwctx); 731 + ret = amdxdna_pm_resume_get(xdna); 732 + if (ret) 733 + goto free_cus; 734 + 735 + ret = aie2_config_cu(hwctx, aie2_config_cu_resp_handler); 740 736 if (ret) { 741 737 XDNA_ERR(xdna, "Config CU to firmware failed, ret %d", ret); 742 - goto free_cus; 738 + goto pm_suspend_put; 743 739 } 744 740 745 741 wmb(); /* To avoid locking in command submit when check status */ ··· 751 739 752 740 return 0; 753 741 742 + pm_suspend_put: 743 + amdxdna_pm_suspend_put(xdna); 754 744 free_cus: 755 745 kfree(hwctx->cus); 756 746 hwctx->cus = NULL; ··· 876 862 goto free_chain; 877 863 } 878 864 865 + ret = amdxdna_pm_resume_get(xdna); 866 + if (ret) 867 + goto cleanup_job; 868 + 879 869 retry: 880 870 ret = drm_gem_lock_reservations(job->bos, job->bo_cnt, &acquire_ctx); 881 871 if (ret) { 882 872 XDNA_WARN(xdna, "Failed to lock BOs, ret %d", ret); 883 - goto cleanup_job; 873 + goto suspend_put; 884 874 } 885 875 886 876 for (i = 0; i < job->bo_cnt; i++) { ··· 892 874 if (ret) { 893 875 XDNA_WARN(xdna, "Failed to reserve fences %d", ret); 894 876 drm_gem_unlock_reservations(job->bos, job->bo_cnt, &acquire_ctx); 895 - goto cleanup_job; 877 + goto suspend_put; 896 878 } 897 879 } 898 880 ··· 907 889 msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); 908 890 } else if (time_after(jiffies, timeout)) { 909 891 ret = -ETIME; 910 - goto cleanup_job; 892 + goto suspend_put; 911 893 } 912 894 913 895 ret = aie2_populate_range(abo); 914 896 if (ret) 915 - goto cleanup_job; 897 + goto suspend_put; 916 898 goto retry; 917 899 } 918 900 } ··· 938 920 939 921 return 0; 940 922 923 + suspend_put: 924 + amdxdna_pm_suspend_put(xdna); 941 925 cleanup_job: 942 926 drm_sched_job_cleanup(&job->base); 943 927 free_chain:
+12 -16
drivers/accel/amdxdna/aie2_message.c
··· 37 37 if (!ndev->mgmt_chann) 38 38 return -ENODEV; 39 39 40 - drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock)); 40 + drm_WARN_ON(&xdna->ddev, xdna->rpm_on && !mutex_is_locked(&xdna->dev_lock)); 41 41 ret = xdna_send_msg_wait(xdna, ndev->mgmt_chann, msg); 42 42 if (ret == -ETIME) { 43 43 xdna_mailbox_stop_channel(ndev->mgmt_chann); ··· 377 377 return xdna_mailbox_send_msg(ndev->mgmt_chann, &msg, TX_TIMEOUT); 378 378 } 379 379 380 - int aie2_config_cu(struct amdxdna_hwctx *hwctx) 380 + int aie2_config_cu(struct amdxdna_hwctx *hwctx, 381 + int (*notify_cb)(void *, void __iomem *, size_t)) 381 382 { 382 383 struct mailbox_channel *chann = hwctx->priv->mbox_chann; 383 384 struct amdxdna_dev *xdna = hwctx->client->xdna; 384 385 u32 shift = xdna->dev_info->dev_mem_buf_shift; 385 - DECLARE_AIE2_MSG(config_cu, MSG_OP_CONFIG_CU); 386 + struct config_cu_req req = { 0 }; 387 + struct xdna_mailbox_msg msg; 386 388 struct drm_gem_object *gobj; 387 389 struct amdxdna_gem_obj *abo; 388 - int ret, i; 390 + int i; 389 391 390 392 if (!chann) 391 393 return -ENODEV; ··· 425 423 } 426 424 req.num_cus = hwctx->cus->num_cus; 427 425 428 - ret = xdna_send_msg_wait(xdna, chann, &msg); 429 - if (ret == -ETIME) 430 - aie2_destroy_context(xdna->dev_handle, hwctx); 431 - 432 - if (resp.status == AIE2_STATUS_SUCCESS) { 433 - XDNA_DBG(xdna, "Configure %d CUs, ret %d", req.num_cus, ret); 434 - return 0; 435 - } 436 - 437 - XDNA_ERR(xdna, "Command opcode 0x%x failed, status 0x%x ret %d", 438 - msg.opcode, resp.status, ret); 439 - return ret; 426 + msg.send_data = (u8 *)&req; 427 + msg.send_size = sizeof(req); 428 + msg.handle = hwctx; 429 + msg.opcode = MSG_OP_CONFIG_CU; 430 + msg.notify_cb = notify_cb; 431 + return xdna_mailbox_send_msg(chann, &msg, TX_TIMEOUT); 440 432 } 441 433 442 434 int aie2_execbuf(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job,
+38 -41
drivers/accel/amdxdna/aie2_pci.c
··· 25 25 #include "amdxdna_gem.h" 26 26 #include "amdxdna_mailbox.h" 27 27 #include "amdxdna_pci_drv.h" 28 + #include "amdxdna_pm.h" 28 29 29 30 static int aie2_max_col = XRS_MAX_COL; 30 31 module_param(aie2_max_col, uint, 0600); ··· 224 223 return ret; 225 224 } 226 225 227 - if (!ndev->async_events) 228 - return 0; 229 - 230 - ret = aie2_error_async_events_send(ndev); 231 - if (ret) { 232 - XDNA_ERR(ndev->xdna, "Send async events failed"); 233 - return ret; 234 - } 235 - 236 226 return 0; 237 227 } 238 228 ··· 248 256 XDNA_ERR(ndev->xdna, "Query AIE metadata failed"); 249 257 return ret; 250 258 } 259 + 260 + ndev->total_col = min(aie2_max_col, ndev->metadata.cols); 251 261 252 262 return 0; 253 263 } ··· 332 338 ndev->mbox = NULL; 333 339 aie2_psp_stop(ndev->psp_hdl); 334 340 aie2_smu_fini(ndev); 341 + aie2_error_async_events_free(ndev); 335 342 pci_disable_device(pdev); 336 343 337 344 ndev->dev_status = AIE2_DEV_INIT; ··· 419 424 goto destroy_mgmt_chann; 420 425 } 421 426 427 + ret = aie2_mgmt_fw_query(ndev); 428 + if (ret) { 429 + XDNA_ERR(xdna, "failed to query fw, ret %d", ret); 430 + goto destroy_mgmt_chann; 431 + } 432 + 433 + ret = aie2_error_async_events_alloc(ndev); 434 + if (ret) { 435 + XDNA_ERR(xdna, "Allocate async events failed, ret %d", ret); 436 + goto destroy_mgmt_chann; 437 + } 438 + 422 439 ndev->dev_status = AIE2_DEV_START; 423 440 424 441 return 0; ··· 466 459 struct amdxdna_client *client; 467 460 int ret; 468 461 469 - guard(mutex)(&xdna->dev_lock); 470 462 ret = aie2_hw_start(xdna); 471 463 if (ret) { 472 464 XDNA_ERR(xdna, "Start hardware failed, %d", ret); ··· 571 565 goto release_fw; 572 566 } 573 567 574 - ret = aie2_mgmt_fw_query(ndev); 575 - if (ret) { 576 - XDNA_ERR(xdna, "Query firmware failed, ret %d", ret); 577 - goto stop_hw; 578 - } 579 - ndev->total_col = min(aie2_max_col, ndev->metadata.cols); 580 - 581 568 xrs_cfg.clk_list.num_levels = ndev->max_dpm_level + 1; 582 569 for (i = 0; i < xrs_cfg.clk_list.num_levels; i++) 583 570 xrs_cfg.clk_list.cu_clk_list[i] = ndev->priv->dpm_clk_tbl[i].hclk; ··· 586 587 goto stop_hw; 587 588 } 588 589 589 - ret = aie2_error_async_events_alloc(ndev); 590 - if (ret) { 591 - XDNA_ERR(xdna, "Allocate async events failed, ret %d", ret); 592 - goto stop_hw; 593 - } 594 - 595 - ret = aie2_error_async_events_send(ndev); 596 - if (ret) { 597 - XDNA_ERR(xdna, "Send async events failed, ret %d", ret); 598 - goto async_event_free; 599 - } 600 - 601 - /* Issue a command to make sure firmware handled async events */ 602 - ret = aie2_query_firmware_version(ndev, &ndev->xdna->fw_ver); 603 - if (ret) { 604 - XDNA_ERR(xdna, "Re-query firmware version failed"); 605 - goto async_event_free; 606 - } 607 - 608 590 release_firmware(fw); 591 + amdxdna_pm_init(xdna); 609 592 return 0; 610 593 611 - async_event_free: 612 - aie2_error_async_events_free(ndev); 613 594 stop_hw: 614 595 aie2_hw_stop(xdna); 615 596 release_fw: ··· 600 621 601 622 static void aie2_fini(struct amdxdna_dev *xdna) 602 623 { 603 - struct amdxdna_dev_hdl *ndev = xdna->dev_handle; 604 - 624 + amdxdna_pm_fini(xdna); 605 625 aie2_hw_stop(xdna); 606 - aie2_error_async_events_free(ndev); 607 626 } 608 627 609 628 static int aie2_get_aie_status(struct amdxdna_client *client, ··· 833 856 if (!drm_dev_enter(&xdna->ddev, &idx)) 834 857 return -ENODEV; 835 858 859 + ret = amdxdna_pm_resume_get(xdna); 860 + if (ret) 861 + goto dev_exit; 862 + 836 863 switch (args->param) { 837 864 case DRM_AMDXDNA_QUERY_AIE_STATUS: 838 865 ret = aie2_get_aie_status(client, args); ··· 863 882 XDNA_ERR(xdna, "Not supported request parameter %u", args->param); 864 883 ret = -EOPNOTSUPP; 865 884 } 885 + 886 + amdxdna_pm_suspend_put(xdna); 866 887 XDNA_DBG(xdna, "Got param %d", args->param); 867 888 889 + dev_exit: 868 890 drm_dev_exit(idx); 869 891 return ret; 870 892 } ··· 916 932 if (!drm_dev_enter(&xdna->ddev, &idx)) 917 933 return -ENODEV; 918 934 935 + ret = amdxdna_pm_resume_get(xdna); 936 + if (ret) 937 + goto dev_exit; 938 + 919 939 switch (args->param) { 920 940 case DRM_AMDXDNA_HW_CONTEXT_ALL: 921 941 ret = aie2_query_ctx_status_array(client, args); ··· 928 940 XDNA_ERR(xdna, "Not supported request parameter %u", args->param); 929 941 ret = -EOPNOTSUPP; 930 942 } 943 + 944 + amdxdna_pm_suspend_put(xdna); 931 945 XDNA_DBG(xdna, "Got param %d", args->param); 932 946 947 + dev_exit: 933 948 drm_dev_exit(idx); 934 949 return ret; 935 950 } ··· 971 980 if (!drm_dev_enter(&xdna->ddev, &idx)) 972 981 return -ENODEV; 973 982 983 + ret = amdxdna_pm_resume_get(xdna); 984 + if (ret) 985 + goto dev_exit; 986 + 974 987 switch (args->param) { 975 988 case DRM_AMDXDNA_SET_POWER_MODE: 976 989 ret = aie2_set_power_mode(client, args); ··· 985 990 break; 986 991 } 987 992 993 + amdxdna_pm_suspend_put(xdna); 994 + dev_exit: 988 995 drm_dev_exit(idx); 989 996 return ret; 990 997 }
+2 -1
drivers/accel/amdxdna/aie2_pci.h
··· 272 272 int aie2_query_status(struct amdxdna_dev_hdl *ndev, char __user *buf, u32 size, u32 *cols_filled); 273 273 int aie2_register_asyn_event_msg(struct amdxdna_dev_hdl *ndev, dma_addr_t addr, u32 size, 274 274 void *handle, int (*cb)(void*, void __iomem *, size_t)); 275 - int aie2_config_cu(struct amdxdna_hwctx *hwctx); 275 + int aie2_config_cu(struct amdxdna_hwctx *hwctx, 276 + int (*notify_cb)(void *, void __iomem *, size_t)); 276 277 int aie2_execbuf(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, 277 278 int (*notify_cb)(void *, void __iomem *, size_t)); 278 279 int aie2_cmdlist_single_execbuf(struct amdxdna_hwctx *hwctx,
+24 -4
drivers/accel/amdxdna/aie2_smu.c
··· 11 11 12 12 #include "aie2_pci.h" 13 13 #include "amdxdna_pci_drv.h" 14 + #include "amdxdna_pm.h" 14 15 15 16 #define SMU_RESULT_OK 1 16 17 ··· 60 59 u32 freq; 61 60 int ret; 62 61 62 + ret = amdxdna_pm_resume_get(ndev->xdna); 63 + if (ret) 64 + return ret; 65 + 63 66 ret = aie2_smu_exec(ndev, AIE2_SMU_SET_MPNPUCLK_FREQ, 64 67 ndev->priv->dpm_clk_tbl[dpm_level].npuclk, &freq); 65 68 if (ret) { 66 69 XDNA_ERR(ndev->xdna, "Set npu clock to %d failed, ret %d\n", 67 70 ndev->priv->dpm_clk_tbl[dpm_level].npuclk, ret); 68 - return ret; 71 + goto suspend_put; 69 72 } 70 73 ndev->npuclk_freq = freq; 71 74 ··· 78 73 if (ret) { 79 74 XDNA_ERR(ndev->xdna, "Set h clock to %d failed, ret %d\n", 80 75 ndev->priv->dpm_clk_tbl[dpm_level].hclk, ret); 81 - return ret; 76 + goto suspend_put; 82 77 } 78 + 79 + amdxdna_pm_suspend_put(ndev->xdna); 83 80 ndev->hclk_freq = freq; 84 81 ndev->dpm_level = dpm_level; 85 82 ··· 89 82 ndev->npuclk_freq, ndev->hclk_freq); 90 83 91 84 return 0; 85 + 86 + suspend_put: 87 + amdxdna_pm_suspend_put(ndev->xdna); 88 + return ret; 92 89 } 93 90 94 91 int npu4_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level) 95 92 { 96 93 int ret; 97 94 95 + ret = amdxdna_pm_resume_get(ndev->xdna); 96 + if (ret) 97 + return ret; 98 + 98 99 ret = aie2_smu_exec(ndev, AIE2_SMU_SET_HARD_DPMLEVEL, dpm_level, NULL); 99 100 if (ret) { 100 101 XDNA_ERR(ndev->xdna, "Set hard dpm level %d failed, ret %d ", 101 102 dpm_level, ret); 102 - return ret; 103 + goto suspend_put; 103 104 } 104 105 105 106 ret = aie2_smu_exec(ndev, AIE2_SMU_SET_SOFT_DPMLEVEL, dpm_level, NULL); 106 107 if (ret) { 107 108 XDNA_ERR(ndev->xdna, "Set soft dpm level %d failed, ret %d", 108 109 dpm_level, ret); 109 - return ret; 110 + goto suspend_put; 110 111 } 111 112 113 + amdxdna_pm_suspend_put(ndev->xdna); 112 114 ndev->npuclk_freq = ndev->priv->dpm_clk_tbl[dpm_level].npuclk; 113 115 ndev->hclk_freq = ndev->priv->dpm_clk_tbl[dpm_level].hclk; 114 116 ndev->dpm_level = dpm_level; ··· 126 110 ndev->npuclk_freq, ndev->hclk_freq); 127 111 128 112 return 0; 113 + 114 + suspend_put: 115 + amdxdna_pm_suspend_put(ndev->xdna); 116 + return ret; 129 117 } 130 118 131 119 int aie2_smu_init(struct amdxdna_dev_hdl *ndev)
+29 -33
drivers/accel/amdxdna/amdxdna_ctx.c
··· 161 161 if (args->ext || args->ext_flags) 162 162 return -EINVAL; 163 163 164 - if (!drm_dev_enter(dev, &idx)) 165 - return -ENODEV; 166 - 167 164 hwctx = kzalloc(sizeof(*hwctx), GFP_KERNEL); 168 - if (!hwctx) { 169 - ret = -ENOMEM; 170 - goto exit; 171 - } 165 + if (!hwctx) 166 + return -ENOMEM; 172 167 173 168 if (copy_from_user(&hwctx->qos, u64_to_user_ptr(args->qos_p), sizeof(hwctx->qos))) { 174 169 XDNA_ERR(xdna, "Access QoS info failed"); 175 - ret = -EFAULT; 176 - goto free_hwctx; 170 + kfree(hwctx); 171 + return -EFAULT; 177 172 } 178 173 179 174 hwctx->client = client; ··· 176 181 hwctx->num_tiles = args->num_tiles; 177 182 hwctx->mem_size = args->mem_size; 178 183 hwctx->max_opc = args->max_opc; 184 + 185 + guard(mutex)(&xdna->dev_lock); 186 + 187 + if (!drm_dev_enter(dev, &idx)) { 188 + ret = -ENODEV; 189 + goto free_hwctx; 190 + } 191 + 192 + ret = xdna->dev_info->ops->hwctx_init(hwctx); 193 + if (ret) { 194 + XDNA_ERR(xdna, "Init hwctx failed, ret %d", ret); 195 + goto dev_exit; 196 + } 197 + 198 + hwctx->name = kasprintf(GFP_KERNEL, "hwctx.%d.%d", client->pid, hwctx->fw_ctx_id); 199 + if (!hwctx->name) { 200 + ret = -ENOMEM; 201 + goto fini_hwctx; 202 + } 203 + 179 204 ret = xa_alloc_cyclic(&client->hwctx_xa, &hwctx->id, hwctx, 180 205 XA_LIMIT(AMDXDNA_INVALID_CTX_HANDLE + 1, MAX_HWCTX_ID), 181 206 &client->next_hwctxid, GFP_KERNEL); 182 207 if (ret < 0) { 183 208 XDNA_ERR(xdna, "Allocate hwctx ID failed, ret %d", ret); 184 - goto free_hwctx; 185 - } 186 - 187 - hwctx->name = kasprintf(GFP_KERNEL, "hwctx.%d.%d", client->pid, hwctx->id); 188 - if (!hwctx->name) { 189 - ret = -ENOMEM; 190 - goto rm_id; 191 - } 192 - 193 - mutex_lock(&xdna->dev_lock); 194 - ret = xdna->dev_info->ops->hwctx_init(hwctx); 195 - if (ret) { 196 - mutex_unlock(&xdna->dev_lock); 197 - XDNA_ERR(xdna, "Init hwctx failed, ret %d", ret); 198 209 goto free_name; 199 210 } 211 + 200 212 args->handle = hwctx->id; 201 213 args->syncobj_handle = hwctx->syncobj_hdl; 202 - mutex_unlock(&xdna->dev_lock); 203 214 204 215 atomic64_set(&hwctx->job_submit_cnt, 0); 205 216 atomic64_set(&hwctx->job_free_cnt, 0); ··· 215 214 216 215 free_name: 217 216 kfree(hwctx->name); 218 - rm_id: 219 - xa_erase(&client->hwctx_xa, hwctx->id); 217 + fini_hwctx: 218 + xdna->dev_info->ops->hwctx_fini(hwctx); 219 + dev_exit: 220 + drm_dev_exit(idx); 220 221 free_hwctx: 221 222 kfree(hwctx); 222 - exit: 223 - drm_dev_exit(idx); 224 223 return ret; 225 224 } 226 225 ··· 432 431 goto unlock_srcu; 433 432 } 434 433 435 - if (hwctx->status != HWCTX_STAT_READY) { 436 - XDNA_ERR(xdna, "HW Context is not ready"); 437 - ret = -EINVAL; 438 - goto unlock_srcu; 439 - } 440 434 441 435 job->hwctx = hwctx; 442 436 job->mm = current->mm;
+8 -5
drivers/accel/amdxdna/amdxdna_mailbox.c
··· 194 194 { 195 195 MB_DBG(mb_chann, "msg_id 0x%x msg opcode 0x%x", 196 196 mb_msg->pkg.header.id, mb_msg->pkg.header.opcode); 197 - mb_msg->notify_cb(mb_msg->handle, NULL, 0); 197 + if (mb_msg->notify_cb) 198 + mb_msg->notify_cb(mb_msg->handle, NULL, 0); 198 199 kfree(mb_msg); 199 200 } 200 201 ··· 249 248 { 250 249 struct mailbox_msg *mb_msg; 251 250 int msg_id; 252 - int ret; 251 + int ret = 0; 253 252 254 253 msg_id = header->id; 255 254 if (!mailbox_validate_msgid(msg_id)) { ··· 266 265 267 266 MB_DBG(mb_chann, "opcode 0x%x size %d id 0x%x", 268 267 header->opcode, header->total_size, header->id); 269 - ret = mb_msg->notify_cb(mb_msg->handle, data, header->total_size); 270 - if (unlikely(ret)) 271 - MB_ERR(mb_chann, "Message callback ret %d", ret); 268 + if (mb_msg->notify_cb) { 269 + ret = mb_msg->notify_cb(mb_msg->handle, data, header->total_size); 270 + if (unlikely(ret)) 271 + MB_ERR(mb_chann, "Message callback ret %d", ret); 272 + } 272 273 273 274 kfree(mb_msg); 274 275 return ret;
+5 -51
drivers/accel/amdxdna/amdxdna_pci_drv.c
··· 13 13 #include <drm/gpu_scheduler.h> 14 14 #include <linux/iommu.h> 15 15 #include <linux/pci.h> 16 - #include <linux/pm_runtime.h> 17 16 18 17 #include "amdxdna_ctx.h" 19 18 #include "amdxdna_gem.h" 20 19 #include "amdxdna_pci_drv.h" 21 - 22 - #define AMDXDNA_AUTOSUSPEND_DELAY 5000 /* milliseconds */ 20 + #include "amdxdna_pm.h" 23 21 24 22 MODULE_FIRMWARE("amdnpu/1502_00/npu.sbin"); 25 23 MODULE_FIRMWARE("amdnpu/17f0_10/npu.sbin"); ··· 59 61 struct amdxdna_client *client; 60 62 int ret; 61 63 62 - ret = pm_runtime_resume_and_get(ddev->dev); 63 - if (ret) { 64 - XDNA_ERR(xdna, "Failed to get rpm, ret %d", ret); 65 - return ret; 66 - } 67 - 68 64 client = kzalloc(sizeof(*client), GFP_KERNEL); 69 - if (!client) { 70 - ret = -ENOMEM; 71 - goto put_rpm; 72 - } 65 + if (!client) 66 + return -ENOMEM; 73 67 74 68 client->pid = pid_nr(rcu_access_pointer(filp->pid)); 75 69 client->xdna = xdna; ··· 96 106 iommu_sva_unbind_device(client->sva); 97 107 failed: 98 108 kfree(client); 99 - put_rpm: 100 - pm_runtime_mark_last_busy(ddev->dev); 101 - pm_runtime_put_autosuspend(ddev->dev); 102 109 103 110 return ret; 104 111 } ··· 117 130 118 131 XDNA_DBG(xdna, "pid %d closed", client->pid); 119 132 kfree(client); 120 - pm_runtime_mark_last_busy(ddev->dev); 121 - pm_runtime_put_autosuspend(ddev->dev); 122 133 } 123 134 124 135 static int amdxdna_flush(struct file *f, fl_owner_t id) ··· 295 310 goto failed_dev_fini; 296 311 } 297 312 298 - pm_runtime_set_autosuspend_delay(dev, AMDXDNA_AUTOSUSPEND_DELAY); 299 - pm_runtime_use_autosuspend(dev); 300 - pm_runtime_allow(dev); 301 - 302 313 ret = drm_dev_register(&xdna->ddev, 0); 303 314 if (ret) { 304 315 XDNA_ERR(xdna, "DRM register failed, ret %d", ret); 305 - pm_runtime_forbid(dev); 306 316 goto failed_sysfs_fini; 307 317 } 308 318 309 - pm_runtime_mark_last_busy(dev); 310 - pm_runtime_put_autosuspend(dev); 311 319 return 0; 312 320 313 321 failed_sysfs_fini: ··· 317 339 static void amdxdna_remove(struct pci_dev *pdev) 318 340 { 319 341 struct amdxdna_dev *xdna = pci_get_drvdata(pdev); 320 - struct device *dev = &pdev->dev; 321 342 struct amdxdna_client *client; 322 343 323 344 destroy_workqueue(xdna->notifier_wq); 324 - 325 - pm_runtime_get_noresume(dev); 326 - pm_runtime_forbid(dev); 327 345 328 346 drm_dev_unplug(&xdna->ddev); 329 347 amdxdna_sysfs_fini(xdna); ··· 339 365 mutex_unlock(&xdna->dev_lock); 340 366 } 341 367 342 - static int amdxdna_pmops_suspend(struct device *dev) 343 - { 344 - struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev)); 345 - 346 - if (!xdna->dev_info->ops->suspend) 347 - return -EOPNOTSUPP; 348 - 349 - return xdna->dev_info->ops->suspend(xdna); 350 - } 351 - 352 - static int amdxdna_pmops_resume(struct device *dev) 353 - { 354 - struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev)); 355 - 356 - if (!xdna->dev_info->ops->resume) 357 - return -EOPNOTSUPP; 358 - 359 - return xdna->dev_info->ops->resume(xdna); 360 - } 361 - 362 368 static const struct dev_pm_ops amdxdna_pm_ops = { 363 - SYSTEM_SLEEP_PM_OPS(amdxdna_pmops_suspend, amdxdna_pmops_resume) 364 - RUNTIME_PM_OPS(amdxdna_pmops_suspend, amdxdna_pmops_resume, NULL) 369 + SYSTEM_SLEEP_PM_OPS(amdxdna_pm_suspend, amdxdna_pm_resume) 370 + RUNTIME_PM_OPS(amdxdna_pm_suspend, amdxdna_pm_resume, NULL) 365 371 }; 366 372 367 373 static struct pci_driver amdxdna_pci_driver = {
+2
drivers/accel/amdxdna/amdxdna_pci_drv.h
··· 6 6 #ifndef _AMDXDNA_PCI_DRV_H_ 7 7 #define _AMDXDNA_PCI_DRV_H_ 8 8 9 + #include <drm/drm_print.h> 9 10 #include <linux/workqueue.h> 10 11 #include <linux/xarray.h> 11 12 ··· 100 99 struct amdxdna_fw_ver fw_ver; 101 100 struct rw_semaphore notifier_lock; /* for mmu notifier*/ 102 101 struct workqueue_struct *notifier_wq; 102 + bool rpm_on; 103 103 }; 104 104 105 105 /*
+94
drivers/accel/amdxdna/amdxdna_pm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2025, Advanced Micro Devices, Inc. 4 + */ 5 + 6 + #include <drm/amdxdna_accel.h> 7 + #include <drm/drm_drv.h> 8 + #include <linux/pm_runtime.h> 9 + 10 + #include "amdxdna_pm.h" 11 + 12 + #define AMDXDNA_AUTOSUSPEND_DELAY 5000 /* milliseconds */ 13 + 14 + int amdxdna_pm_suspend(struct device *dev) 15 + { 16 + struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev)); 17 + int ret = -EOPNOTSUPP; 18 + bool rpm; 19 + 20 + if (xdna->dev_info->ops->suspend) { 21 + rpm = xdna->rpm_on; 22 + xdna->rpm_on = false; 23 + ret = xdna->dev_info->ops->suspend(xdna); 24 + xdna->rpm_on = rpm; 25 + } 26 + 27 + XDNA_DBG(xdna, "Suspend done ret %d", ret); 28 + return ret; 29 + } 30 + 31 + int amdxdna_pm_resume(struct device *dev) 32 + { 33 + struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev)); 34 + int ret = -EOPNOTSUPP; 35 + bool rpm; 36 + 37 + if (xdna->dev_info->ops->resume) { 38 + rpm = xdna->rpm_on; 39 + xdna->rpm_on = false; 40 + ret = xdna->dev_info->ops->resume(xdna); 41 + xdna->rpm_on = rpm; 42 + } 43 + 44 + XDNA_DBG(xdna, "Resume done ret %d", ret); 45 + return ret; 46 + } 47 + 48 + int amdxdna_pm_resume_get(struct amdxdna_dev *xdna) 49 + { 50 + struct device *dev = xdna->ddev.dev; 51 + int ret; 52 + 53 + if (!xdna->rpm_on) 54 + return 0; 55 + 56 + ret = pm_runtime_resume_and_get(dev); 57 + if (ret) { 58 + XDNA_ERR(xdna, "Resume failed: %d", ret); 59 + pm_runtime_set_suspended(dev); 60 + } 61 + 62 + return ret; 63 + } 64 + 65 + void amdxdna_pm_suspend_put(struct amdxdna_dev *xdna) 66 + { 67 + struct device *dev = xdna->ddev.dev; 68 + 69 + if (!xdna->rpm_on) 70 + return; 71 + 72 + pm_runtime_put_autosuspend(dev); 73 + } 74 + 75 + void amdxdna_pm_init(struct amdxdna_dev *xdna) 76 + { 77 + struct device *dev = xdna->ddev.dev; 78 + 79 + pm_runtime_set_active(dev); 80 + pm_runtime_set_autosuspend_delay(dev, AMDXDNA_AUTOSUSPEND_DELAY); 81 + pm_runtime_use_autosuspend(dev); 82 + pm_runtime_allow(dev); 83 + pm_runtime_put_autosuspend(dev); 84 + xdna->rpm_on = true; 85 + } 86 + 87 + void amdxdna_pm_fini(struct amdxdna_dev *xdna) 88 + { 89 + struct device *dev = xdna->ddev.dev; 90 + 91 + xdna->rpm_on = false; 92 + pm_runtime_get_noresume(dev); 93 + pm_runtime_forbid(dev); 94 + }
+18
drivers/accel/amdxdna/amdxdna_pm.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2025, Advanced Micro Devices, Inc. 4 + */ 5 + 6 + #ifndef _AMDXDNA_PM_H_ 7 + #define _AMDXDNA_PM_H_ 8 + 9 + #include "amdxdna_pci_drv.h" 10 + 11 + int amdxdna_pm_suspend(struct device *dev); 12 + int amdxdna_pm_resume(struct device *dev); 13 + int amdxdna_pm_resume_get(struct amdxdna_dev *xdna); 14 + void amdxdna_pm_suspend_put(struct amdxdna_dev *xdna); 15 + void amdxdna_pm_init(struct amdxdna_dev *xdna); 16 + void amdxdna_pm_fini(struct amdxdna_dev *xdna); 17 + 18 + #endif /* _AMDXDNA_PM_H_ */