Path: blob/master/drivers/accel/amdxdna/amdxdna_pci_drv.c
26428 views
// SPDX-License-Identifier: GPL-2.01/*2* Copyright (C) 2022-2024, Advanced Micro Devices, Inc.3*/45#include <drm/amdxdna_accel.h>6#include <drm/drm_accel.h>7#include <drm/drm_drv.h>8#include <drm/drm_gem.h>9#include <drm/drm_gem_shmem_helper.h>10#include <drm/drm_ioctl.h>11#include <drm/drm_managed.h>12#include <drm/gpu_scheduler.h>13#include <linux/iommu.h>14#include <linux/pci.h>15#include <linux/pm_runtime.h>1617#include "amdxdna_ctx.h"18#include "amdxdna_gem.h"19#include "amdxdna_pci_drv.h"2021#define AMDXDNA_AUTOSUSPEND_DELAY 5000 /* milliseconds */2223MODULE_FIRMWARE("amdnpu/1502_00/npu.sbin");24MODULE_FIRMWARE("amdnpu/17f0_10/npu.sbin");25MODULE_FIRMWARE("amdnpu/17f0_11/npu.sbin");26MODULE_FIRMWARE("amdnpu/17f0_20/npu.sbin");2728/*29* Bind the driver base on (vendor_id, device_id) pair and later use the30* (device_id, rev_id) pair as a key to select the devices. The devices with31* same device_id have very similar interface to host driver.32*/33static const struct pci_device_id pci_ids[] = {34{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1502) },35{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x17f0) },36{0}37};3839MODULE_DEVICE_TABLE(pci, pci_ids);4041static const struct amdxdna_device_id amdxdna_ids[] = {42{ 0x1502, 0x0, &dev_npu1_info },43{ 0x17f0, 0x0, &dev_npu2_info },44{ 0x17f0, 0x10, &dev_npu4_info },45{ 0x17f0, 0x11, &dev_npu5_info },46{ 0x17f0, 0x20, &dev_npu6_info },47{0}48};4950static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp)51{52struct amdxdna_dev *xdna = to_xdna_dev(ddev);53struct amdxdna_client *client;54int ret;5556ret = pm_runtime_resume_and_get(ddev->dev);57if (ret) {58XDNA_ERR(xdna, "Failed to get rpm, ret %d", ret);59return ret;60}6162client = kzalloc(sizeof(*client), GFP_KERNEL);63if (!client) {64ret = -ENOMEM;65goto put_rpm;66}6768client->pid = pid_nr(rcu_access_pointer(filp->pid));69client->xdna = xdna;7071client->sva = iommu_sva_bind_device(xdna->ddev.dev, current->mm);72if (IS_ERR(client->sva)) {73ret = PTR_ERR(client->sva);74XDNA_ERR(xdna, "SVA bind device failed, ret %d", ret);75goto failed;76}77client->pasid = iommu_sva_get_pasid(client->sva);78if (client->pasid == IOMMU_PASID_INVALID) {79XDNA_ERR(xdna, "SVA get pasid failed");80ret = -ENODEV;81goto unbind_sva;82}83mutex_init(&client->hwctx_lock);84init_srcu_struct(&client->hwctx_srcu);85xa_init_flags(&client->hwctx_xa, XA_FLAGS_ALLOC);86mutex_init(&client->mm_lock);8788mutex_lock(&xdna->dev_lock);89list_add_tail(&client->node, &xdna->client_list);90mutex_unlock(&xdna->dev_lock);9192filp->driver_priv = client;93client->filp = filp;9495XDNA_DBG(xdna, "pid %d opened", client->pid);96return 0;9798unbind_sva:99iommu_sva_unbind_device(client->sva);100failed:101kfree(client);102put_rpm:103pm_runtime_mark_last_busy(ddev->dev);104pm_runtime_put_autosuspend(ddev->dev);105106return ret;107}108109static void amdxdna_drm_close(struct drm_device *ddev, struct drm_file *filp)110{111struct amdxdna_client *client = filp->driver_priv;112struct amdxdna_dev *xdna = to_xdna_dev(ddev);113114XDNA_DBG(xdna, "closing pid %d", client->pid);115116xa_destroy(&client->hwctx_xa);117cleanup_srcu_struct(&client->hwctx_srcu);118mutex_destroy(&client->hwctx_lock);119mutex_destroy(&client->mm_lock);120if (client->dev_heap)121drm_gem_object_put(to_gobj(client->dev_heap));122123iommu_sva_unbind_device(client->sva);124125XDNA_DBG(xdna, "pid %d closed", client->pid);126kfree(client);127pm_runtime_mark_last_busy(ddev->dev);128pm_runtime_put_autosuspend(ddev->dev);129}130131static int amdxdna_flush(struct file *f, fl_owner_t id)132{133struct drm_file *filp = f->private_data;134struct amdxdna_client *client = filp->driver_priv;135struct amdxdna_dev *xdna = client->xdna;136int idx;137138XDNA_DBG(xdna, "PID %d flushing...", client->pid);139if (!drm_dev_enter(&xdna->ddev, &idx))140return 0;141142mutex_lock(&xdna->dev_lock);143list_del_init(&client->node);144mutex_unlock(&xdna->dev_lock);145amdxdna_hwctx_remove_all(client);146147drm_dev_exit(idx);148return 0;149}150151static int amdxdna_drm_get_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)152{153struct amdxdna_client *client = filp->driver_priv;154struct amdxdna_dev *xdna = to_xdna_dev(dev);155struct amdxdna_drm_get_info *args = data;156int ret;157158if (!xdna->dev_info->ops->get_aie_info)159return -EOPNOTSUPP;160161XDNA_DBG(xdna, "Request parameter %u", args->param);162mutex_lock(&xdna->dev_lock);163ret = xdna->dev_info->ops->get_aie_info(client, args);164mutex_unlock(&xdna->dev_lock);165return ret;166}167168static int amdxdna_drm_set_state_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)169{170struct amdxdna_client *client = filp->driver_priv;171struct amdxdna_dev *xdna = to_xdna_dev(dev);172struct amdxdna_drm_set_state *args = data;173int ret;174175if (!xdna->dev_info->ops->set_aie_state)176return -EOPNOTSUPP;177178XDNA_DBG(xdna, "Request parameter %u", args->param);179mutex_lock(&xdna->dev_lock);180ret = xdna->dev_info->ops->set_aie_state(client, args);181mutex_unlock(&xdna->dev_lock);182183return ret;184}185186static const struct drm_ioctl_desc amdxdna_drm_ioctls[] = {187/* Context */188DRM_IOCTL_DEF_DRV(AMDXDNA_CREATE_HWCTX, amdxdna_drm_create_hwctx_ioctl, 0),189DRM_IOCTL_DEF_DRV(AMDXDNA_DESTROY_HWCTX, amdxdna_drm_destroy_hwctx_ioctl, 0),190DRM_IOCTL_DEF_DRV(AMDXDNA_CONFIG_HWCTX, amdxdna_drm_config_hwctx_ioctl, 0),191/* BO */192DRM_IOCTL_DEF_DRV(AMDXDNA_CREATE_BO, amdxdna_drm_create_bo_ioctl, 0),193DRM_IOCTL_DEF_DRV(AMDXDNA_GET_BO_INFO, amdxdna_drm_get_bo_info_ioctl, 0),194DRM_IOCTL_DEF_DRV(AMDXDNA_SYNC_BO, amdxdna_drm_sync_bo_ioctl, 0),195/* Execution */196DRM_IOCTL_DEF_DRV(AMDXDNA_EXEC_CMD, amdxdna_drm_submit_cmd_ioctl, 0),197/* AIE hardware */198DRM_IOCTL_DEF_DRV(AMDXDNA_GET_INFO, amdxdna_drm_get_info_ioctl, 0),199DRM_IOCTL_DEF_DRV(AMDXDNA_SET_STATE, amdxdna_drm_set_state_ioctl, DRM_ROOT_ONLY),200};201202static const struct file_operations amdxdna_fops = {203.owner = THIS_MODULE,204.open = accel_open,205.release = drm_release,206.flush = amdxdna_flush,207.unlocked_ioctl = drm_ioctl,208.compat_ioctl = drm_compat_ioctl,209.poll = drm_poll,210.read = drm_read,211.llseek = noop_llseek,212.mmap = drm_gem_mmap,213.fop_flags = FOP_UNSIGNED_OFFSET,214};215216const struct drm_driver amdxdna_drm_drv = {217.driver_features = DRIVER_GEM | DRIVER_COMPUTE_ACCEL |218DRIVER_SYNCOBJ | DRIVER_SYNCOBJ_TIMELINE,219.fops = &amdxdna_fops,220.name = "amdxdna_accel_driver",221.desc = "AMD XDNA DRM implementation",222.open = amdxdna_drm_open,223.postclose = amdxdna_drm_close,224.ioctls = amdxdna_drm_ioctls,225.num_ioctls = ARRAY_SIZE(amdxdna_drm_ioctls),226227.gem_create_object = amdxdna_gem_create_object_cb,228.gem_prime_import = amdxdna_gem_prime_import,229};230231static const struct amdxdna_dev_info *232amdxdna_get_dev_info(struct pci_dev *pdev)233{234int i;235236for (i = 0; i < ARRAY_SIZE(amdxdna_ids); i++) {237if (pdev->device == amdxdna_ids[i].device &&238pdev->revision == amdxdna_ids[i].revision)239return amdxdna_ids[i].dev_info;240}241return NULL;242}243244static int amdxdna_probe(struct pci_dev *pdev, const struct pci_device_id *id)245{246struct device *dev = &pdev->dev;247struct amdxdna_dev *xdna;248int ret;249250xdna = devm_drm_dev_alloc(dev, &amdxdna_drm_drv, typeof(*xdna), ddev);251if (IS_ERR(xdna))252return PTR_ERR(xdna);253254xdna->dev_info = amdxdna_get_dev_info(pdev);255if (!xdna->dev_info)256return -ENODEV;257258drmm_mutex_init(&xdna->ddev, &xdna->dev_lock);259init_rwsem(&xdna->notifier_lock);260INIT_LIST_HEAD(&xdna->client_list);261pci_set_drvdata(pdev, xdna);262263if (IS_ENABLED(CONFIG_LOCKDEP)) {264fs_reclaim_acquire(GFP_KERNEL);265might_lock(&xdna->notifier_lock);266fs_reclaim_release(GFP_KERNEL);267}268269xdna->notifier_wq = alloc_ordered_workqueue("notifier_wq", 0);270if (!xdna->notifier_wq)271return -ENOMEM;272273mutex_lock(&xdna->dev_lock);274ret = xdna->dev_info->ops->init(xdna);275mutex_unlock(&xdna->dev_lock);276if (ret) {277XDNA_ERR(xdna, "Hardware init failed, ret %d", ret);278goto destroy_notifier_wq;279}280281ret = amdxdna_sysfs_init(xdna);282if (ret) {283XDNA_ERR(xdna, "Create amdxdna attrs failed: %d", ret);284goto failed_dev_fini;285}286287pm_runtime_set_autosuspend_delay(dev, AMDXDNA_AUTOSUSPEND_DELAY);288pm_runtime_use_autosuspend(dev);289pm_runtime_allow(dev);290291ret = drm_dev_register(&xdna->ddev, 0);292if (ret) {293XDNA_ERR(xdna, "DRM register failed, ret %d", ret);294pm_runtime_forbid(dev);295goto failed_sysfs_fini;296}297298pm_runtime_mark_last_busy(dev);299pm_runtime_put_autosuspend(dev);300return 0;301302failed_sysfs_fini:303amdxdna_sysfs_fini(xdna);304failed_dev_fini:305mutex_lock(&xdna->dev_lock);306xdna->dev_info->ops->fini(xdna);307mutex_unlock(&xdna->dev_lock);308destroy_notifier_wq:309destroy_workqueue(xdna->notifier_wq);310return ret;311}312313static void amdxdna_remove(struct pci_dev *pdev)314{315struct amdxdna_dev *xdna = pci_get_drvdata(pdev);316struct device *dev = &pdev->dev;317struct amdxdna_client *client;318319destroy_workqueue(xdna->notifier_wq);320321pm_runtime_get_noresume(dev);322pm_runtime_forbid(dev);323324drm_dev_unplug(&xdna->ddev);325amdxdna_sysfs_fini(xdna);326327mutex_lock(&xdna->dev_lock);328client = list_first_entry_or_null(&xdna->client_list,329struct amdxdna_client, node);330while (client) {331list_del_init(&client->node);332mutex_unlock(&xdna->dev_lock);333334amdxdna_hwctx_remove_all(client);335336mutex_lock(&xdna->dev_lock);337client = list_first_entry_or_null(&xdna->client_list,338struct amdxdna_client, node);339}340341xdna->dev_info->ops->fini(xdna);342mutex_unlock(&xdna->dev_lock);343}344345static int amdxdna_dev_suspend_nolock(struct amdxdna_dev *xdna)346{347if (xdna->dev_info->ops->suspend)348xdna->dev_info->ops->suspend(xdna);349350return 0;351}352353static int amdxdna_dev_resume_nolock(struct amdxdna_dev *xdna)354{355if (xdna->dev_info->ops->resume)356return xdna->dev_info->ops->resume(xdna);357358return 0;359}360361static int amdxdna_pmops_suspend(struct device *dev)362{363struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev));364struct amdxdna_client *client;365366mutex_lock(&xdna->dev_lock);367list_for_each_entry(client, &xdna->client_list, node)368amdxdna_hwctx_suspend(client);369370amdxdna_dev_suspend_nolock(xdna);371mutex_unlock(&xdna->dev_lock);372373return 0;374}375376static int amdxdna_pmops_resume(struct device *dev)377{378struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev));379struct amdxdna_client *client;380int ret;381382XDNA_INFO(xdna, "firmware resuming...");383mutex_lock(&xdna->dev_lock);384ret = amdxdna_dev_resume_nolock(xdna);385if (ret) {386XDNA_ERR(xdna, "resume NPU firmware failed");387mutex_unlock(&xdna->dev_lock);388return ret;389}390391XDNA_INFO(xdna, "hardware context resuming...");392list_for_each_entry(client, &xdna->client_list, node)393amdxdna_hwctx_resume(client);394mutex_unlock(&xdna->dev_lock);395396return 0;397}398399static int amdxdna_rpmops_suspend(struct device *dev)400{401struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev));402int ret;403404mutex_lock(&xdna->dev_lock);405ret = amdxdna_dev_suspend_nolock(xdna);406mutex_unlock(&xdna->dev_lock);407408XDNA_DBG(xdna, "Runtime suspend done ret: %d", ret);409return ret;410}411412static int amdxdna_rpmops_resume(struct device *dev)413{414struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev));415int ret;416417mutex_lock(&xdna->dev_lock);418ret = amdxdna_dev_resume_nolock(xdna);419mutex_unlock(&xdna->dev_lock);420421XDNA_DBG(xdna, "Runtime resume done ret: %d", ret);422return ret;423}424425static const struct dev_pm_ops amdxdna_pm_ops = {426SYSTEM_SLEEP_PM_OPS(amdxdna_pmops_suspend, amdxdna_pmops_resume)427RUNTIME_PM_OPS(amdxdna_rpmops_suspend, amdxdna_rpmops_resume, NULL)428};429430static struct pci_driver amdxdna_pci_driver = {431.name = KBUILD_MODNAME,432.id_table = pci_ids,433.probe = amdxdna_probe,434.remove = amdxdna_remove,435.driver.pm = &amdxdna_pm_ops,436};437438module_pci_driver(amdxdna_pci_driver);439440MODULE_LICENSE("GPL");441MODULE_AUTHOR("XRT Team <[email protected]>");442MODULE_DESCRIPTION("amdxdna driver");443444445