Path: blob/master/drivers/accel/amdxdna/amdxdna_pci_drv.c
29278 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* 0.0: Initial version30* 0.1: Support getting all hardware contexts by DRM_IOCTL_AMDXDNA_GET_ARRAY31*/32#define AMDXDNA_DRIVER_MAJOR 033#define AMDXDNA_DRIVER_MINOR 13435/*36* Bind the driver base on (vendor_id, device_id) pair and later use the37* (device_id, rev_id) pair as a key to select the devices. The devices with38* same device_id have very similar interface to host driver.39*/40static const struct pci_device_id pci_ids[] = {41{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1502) },42{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x17f0) },43{0}44};4546MODULE_DEVICE_TABLE(pci, pci_ids);4748static const struct amdxdna_device_id amdxdna_ids[] = {49{ 0x1502, 0x0, &dev_npu1_info },50{ 0x17f0, 0x0, &dev_npu2_info },51{ 0x17f0, 0x10, &dev_npu4_info },52{ 0x17f0, 0x11, &dev_npu5_info },53{ 0x17f0, 0x20, &dev_npu6_info },54{0}55};5657static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp)58{59struct amdxdna_dev *xdna = to_xdna_dev(ddev);60struct amdxdna_client *client;61int ret;6263ret = pm_runtime_resume_and_get(ddev->dev);64if (ret) {65XDNA_ERR(xdna, "Failed to get rpm, ret %d", ret);66return ret;67}6869client = kzalloc(sizeof(*client), GFP_KERNEL);70if (!client) {71ret = -ENOMEM;72goto put_rpm;73}7475client->pid = pid_nr(rcu_access_pointer(filp->pid));76client->xdna = xdna;7778client->sva = iommu_sva_bind_device(xdna->ddev.dev, current->mm);79if (IS_ERR(client->sva)) {80ret = PTR_ERR(client->sva);81XDNA_ERR(xdna, "SVA bind device failed, ret %d", ret);82goto failed;83}84client->pasid = iommu_sva_get_pasid(client->sva);85if (client->pasid == IOMMU_PASID_INVALID) {86XDNA_ERR(xdna, "SVA get pasid failed");87ret = -ENODEV;88goto unbind_sva;89}90init_srcu_struct(&client->hwctx_srcu);91xa_init_flags(&client->hwctx_xa, XA_FLAGS_ALLOC);92mutex_init(&client->mm_lock);9394mutex_lock(&xdna->dev_lock);95list_add_tail(&client->node, &xdna->client_list);96mutex_unlock(&xdna->dev_lock);9798filp->driver_priv = client;99client->filp = filp;100101XDNA_DBG(xdna, "pid %d opened", client->pid);102return 0;103104unbind_sva:105iommu_sva_unbind_device(client->sva);106failed:107kfree(client);108put_rpm:109pm_runtime_mark_last_busy(ddev->dev);110pm_runtime_put_autosuspend(ddev->dev);111112return ret;113}114115static void amdxdna_drm_close(struct drm_device *ddev, struct drm_file *filp)116{117struct amdxdna_client *client = filp->driver_priv;118struct amdxdna_dev *xdna = to_xdna_dev(ddev);119120XDNA_DBG(xdna, "closing pid %d", client->pid);121122xa_destroy(&client->hwctx_xa);123cleanup_srcu_struct(&client->hwctx_srcu);124mutex_destroy(&client->mm_lock);125if (client->dev_heap)126drm_gem_object_put(to_gobj(client->dev_heap));127128iommu_sva_unbind_device(client->sva);129130XDNA_DBG(xdna, "pid %d closed", client->pid);131kfree(client);132pm_runtime_mark_last_busy(ddev->dev);133pm_runtime_put_autosuspend(ddev->dev);134}135136static int amdxdna_flush(struct file *f, fl_owner_t id)137{138struct drm_file *filp = f->private_data;139struct amdxdna_client *client = filp->driver_priv;140struct amdxdna_dev *xdna = client->xdna;141int idx;142143XDNA_DBG(xdna, "PID %d flushing...", client->pid);144if (!drm_dev_enter(&xdna->ddev, &idx))145return 0;146147mutex_lock(&xdna->dev_lock);148list_del_init(&client->node);149amdxdna_hwctx_remove_all(client);150mutex_unlock(&xdna->dev_lock);151152drm_dev_exit(idx);153return 0;154}155156static int amdxdna_drm_get_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)157{158struct amdxdna_client *client = filp->driver_priv;159struct amdxdna_dev *xdna = to_xdna_dev(dev);160struct amdxdna_drm_get_info *args = data;161int ret;162163if (!xdna->dev_info->ops->get_aie_info)164return -EOPNOTSUPP;165166XDNA_DBG(xdna, "Request parameter %u", args->param);167mutex_lock(&xdna->dev_lock);168ret = xdna->dev_info->ops->get_aie_info(client, args);169mutex_unlock(&xdna->dev_lock);170return ret;171}172173static int amdxdna_drm_get_array_ioctl(struct drm_device *dev, void *data,174struct drm_file *filp)175{176struct amdxdna_client *client = filp->driver_priv;177struct amdxdna_dev *xdna = to_xdna_dev(dev);178struct amdxdna_drm_get_array *args = data;179180if (!xdna->dev_info->ops->get_array)181return -EOPNOTSUPP;182183if (args->pad || !args->num_element || !args->element_size)184return -EINVAL;185186guard(mutex)(&xdna->dev_lock);187return xdna->dev_info->ops->get_array(client, args);188}189190static int amdxdna_drm_set_state_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)191{192struct amdxdna_client *client = filp->driver_priv;193struct amdxdna_dev *xdna = to_xdna_dev(dev);194struct amdxdna_drm_set_state *args = data;195int ret;196197if (!xdna->dev_info->ops->set_aie_state)198return -EOPNOTSUPP;199200XDNA_DBG(xdna, "Request parameter %u", args->param);201mutex_lock(&xdna->dev_lock);202ret = xdna->dev_info->ops->set_aie_state(client, args);203mutex_unlock(&xdna->dev_lock);204205return ret;206}207208static const struct drm_ioctl_desc amdxdna_drm_ioctls[] = {209/* Context */210DRM_IOCTL_DEF_DRV(AMDXDNA_CREATE_HWCTX, amdxdna_drm_create_hwctx_ioctl, 0),211DRM_IOCTL_DEF_DRV(AMDXDNA_DESTROY_HWCTX, amdxdna_drm_destroy_hwctx_ioctl, 0),212DRM_IOCTL_DEF_DRV(AMDXDNA_CONFIG_HWCTX, amdxdna_drm_config_hwctx_ioctl, 0),213/* BO */214DRM_IOCTL_DEF_DRV(AMDXDNA_CREATE_BO, amdxdna_drm_create_bo_ioctl, 0),215DRM_IOCTL_DEF_DRV(AMDXDNA_GET_BO_INFO, amdxdna_drm_get_bo_info_ioctl, 0),216DRM_IOCTL_DEF_DRV(AMDXDNA_SYNC_BO, amdxdna_drm_sync_bo_ioctl, 0),217/* Execution */218DRM_IOCTL_DEF_DRV(AMDXDNA_EXEC_CMD, amdxdna_drm_submit_cmd_ioctl, 0),219/* AIE hardware */220DRM_IOCTL_DEF_DRV(AMDXDNA_GET_INFO, amdxdna_drm_get_info_ioctl, 0),221DRM_IOCTL_DEF_DRV(AMDXDNA_GET_ARRAY, amdxdna_drm_get_array_ioctl, 0),222DRM_IOCTL_DEF_DRV(AMDXDNA_SET_STATE, amdxdna_drm_set_state_ioctl, DRM_ROOT_ONLY),223};224225static const struct file_operations amdxdna_fops = {226.owner = THIS_MODULE,227.open = accel_open,228.release = drm_release,229.flush = amdxdna_flush,230.unlocked_ioctl = drm_ioctl,231.compat_ioctl = drm_compat_ioctl,232.poll = drm_poll,233.read = drm_read,234.llseek = noop_llseek,235.mmap = drm_gem_mmap,236.fop_flags = FOP_UNSIGNED_OFFSET,237};238239const struct drm_driver amdxdna_drm_drv = {240.driver_features = DRIVER_GEM | DRIVER_COMPUTE_ACCEL |241DRIVER_SYNCOBJ | DRIVER_SYNCOBJ_TIMELINE,242.fops = &amdxdna_fops,243.name = "amdxdna_accel_driver",244.desc = "AMD XDNA DRM implementation",245.major = AMDXDNA_DRIVER_MAJOR,246.minor = AMDXDNA_DRIVER_MINOR,247.open = amdxdna_drm_open,248.postclose = amdxdna_drm_close,249.ioctls = amdxdna_drm_ioctls,250.num_ioctls = ARRAY_SIZE(amdxdna_drm_ioctls),251252.gem_create_object = amdxdna_gem_create_object_cb,253.gem_prime_import = amdxdna_gem_prime_import,254};255256static const struct amdxdna_dev_info *257amdxdna_get_dev_info(struct pci_dev *pdev)258{259int i;260261for (i = 0; i < ARRAY_SIZE(amdxdna_ids); i++) {262if (pdev->device == amdxdna_ids[i].device &&263pdev->revision == amdxdna_ids[i].revision)264return amdxdna_ids[i].dev_info;265}266return NULL;267}268269static int amdxdna_probe(struct pci_dev *pdev, const struct pci_device_id *id)270{271struct device *dev = &pdev->dev;272struct amdxdna_dev *xdna;273int ret;274275xdna = devm_drm_dev_alloc(dev, &amdxdna_drm_drv, typeof(*xdna), ddev);276if (IS_ERR(xdna))277return PTR_ERR(xdna);278279xdna->dev_info = amdxdna_get_dev_info(pdev);280if (!xdna->dev_info)281return -ENODEV;282283drmm_mutex_init(&xdna->ddev, &xdna->dev_lock);284init_rwsem(&xdna->notifier_lock);285INIT_LIST_HEAD(&xdna->client_list);286pci_set_drvdata(pdev, xdna);287288if (IS_ENABLED(CONFIG_LOCKDEP)) {289fs_reclaim_acquire(GFP_KERNEL);290might_lock(&xdna->notifier_lock);291fs_reclaim_release(GFP_KERNEL);292}293294xdna->notifier_wq = alloc_ordered_workqueue("notifier_wq", 0);295if (!xdna->notifier_wq)296return -ENOMEM;297298mutex_lock(&xdna->dev_lock);299ret = xdna->dev_info->ops->init(xdna);300mutex_unlock(&xdna->dev_lock);301if (ret) {302XDNA_ERR(xdna, "Hardware init failed, ret %d", ret);303goto destroy_notifier_wq;304}305306ret = amdxdna_sysfs_init(xdna);307if (ret) {308XDNA_ERR(xdna, "Create amdxdna attrs failed: %d", ret);309goto failed_dev_fini;310}311312pm_runtime_set_autosuspend_delay(dev, AMDXDNA_AUTOSUSPEND_DELAY);313pm_runtime_use_autosuspend(dev);314pm_runtime_allow(dev);315316ret = drm_dev_register(&xdna->ddev, 0);317if (ret) {318XDNA_ERR(xdna, "DRM register failed, ret %d", ret);319pm_runtime_forbid(dev);320goto failed_sysfs_fini;321}322323pm_runtime_mark_last_busy(dev);324pm_runtime_put_autosuspend(dev);325return 0;326327failed_sysfs_fini:328amdxdna_sysfs_fini(xdna);329failed_dev_fini:330mutex_lock(&xdna->dev_lock);331xdna->dev_info->ops->fini(xdna);332mutex_unlock(&xdna->dev_lock);333destroy_notifier_wq:334destroy_workqueue(xdna->notifier_wq);335return ret;336}337338static void amdxdna_remove(struct pci_dev *pdev)339{340struct amdxdna_dev *xdna = pci_get_drvdata(pdev);341struct device *dev = &pdev->dev;342struct amdxdna_client *client;343344destroy_workqueue(xdna->notifier_wq);345346pm_runtime_get_noresume(dev);347pm_runtime_forbid(dev);348349drm_dev_unplug(&xdna->ddev);350amdxdna_sysfs_fini(xdna);351352mutex_lock(&xdna->dev_lock);353client = list_first_entry_or_null(&xdna->client_list,354struct amdxdna_client, node);355while (client) {356list_del_init(&client->node);357amdxdna_hwctx_remove_all(client);358359client = list_first_entry_or_null(&xdna->client_list,360struct amdxdna_client, node);361}362363xdna->dev_info->ops->fini(xdna);364mutex_unlock(&xdna->dev_lock);365}366367static int amdxdna_pmops_suspend(struct device *dev)368{369struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev));370371if (!xdna->dev_info->ops->suspend)372return -EOPNOTSUPP;373374return xdna->dev_info->ops->suspend(xdna);375}376377static int amdxdna_pmops_resume(struct device *dev)378{379struct amdxdna_dev *xdna = pci_get_drvdata(to_pci_dev(dev));380381if (!xdna->dev_info->ops->resume)382return -EOPNOTSUPP;383384return xdna->dev_info->ops->resume(xdna);385}386387static const struct dev_pm_ops amdxdna_pm_ops = {388SYSTEM_SLEEP_PM_OPS(amdxdna_pmops_suspend, amdxdna_pmops_resume)389RUNTIME_PM_OPS(amdxdna_pmops_suspend, amdxdna_pmops_resume, NULL)390};391392static struct pci_driver amdxdna_pci_driver = {393.name = KBUILD_MODNAME,394.id_table = pci_ids,395.probe = amdxdna_probe,396.remove = amdxdna_remove,397.driver.pm = &amdxdna_pm_ops,398};399400module_pci_driver(amdxdna_pci_driver);401402MODULE_LICENSE("GPL");403MODULE_AUTHOR("XRT Team <[email protected]>");404MODULE_DESCRIPTION("amdxdna driver");405406407