Path: blob/master/drivers/accel/amdxdna/amdxdna_pci_drv.c
52282 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>1516#include "amdxdna_ctx.h"17#include "amdxdna_gem.h"18#include "amdxdna_pci_drv.h"19#include "amdxdna_pm.h"2021MODULE_FIRMWARE("amdnpu/1502_00/npu.sbin");22MODULE_FIRMWARE("amdnpu/17f0_10/npu.sbin");23MODULE_FIRMWARE("amdnpu/17f0_11/npu.sbin");24MODULE_FIRMWARE("amdnpu/17f0_20/npu.sbin");2526/*27* 0.0: Initial version28* 0.1: Support getting all hardware contexts by DRM_IOCTL_AMDXDNA_GET_ARRAY29* 0.2: Support getting last error hardware error30* 0.3: Support firmware debug buffer31* 0.4: Support getting resource information32* 0.5: Support getting telemetry data33* 0.6: Support preemption34*/35#define AMDXDNA_DRIVER_MAJOR 036#define AMDXDNA_DRIVER_MINOR 63738/*39* Bind the driver base on (vendor_id, device_id) pair and later use the40* (device_id, rev_id) pair as a key to select the devices. The devices with41* same device_id have very similar interface to host driver.42*/43static const struct pci_device_id pci_ids[] = {44{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1502) },45{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x17f0) },46{0}47};4849MODULE_DEVICE_TABLE(pci, pci_ids);5051static const struct amdxdna_device_id amdxdna_ids[] = {52{ 0x1502, 0x0, &dev_npu1_info },53{ 0x17f0, 0x10, &dev_npu4_info },54{ 0x17f0, 0x11, &dev_npu5_info },55{ 0x17f0, 0x20, &dev_npu6_info },56{0}57};5859static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp)60{61struct amdxdna_dev *xdna = to_xdna_dev(ddev);62struct amdxdna_client *client;63int ret;6465client = kzalloc(sizeof(*client), GFP_KERNEL);66if (!client)67return -ENOMEM;6869client->pid = pid_nr(rcu_access_pointer(filp->pid));70client->xdna = xdna;7172client->sva = iommu_sva_bind_device(xdna->ddev.dev, current->mm);73if (IS_ERR(client->sva)) {74ret = PTR_ERR(client->sva);75XDNA_ERR(xdna, "SVA bind device failed, ret %d", ret);76goto failed;77}78client->pasid = iommu_sva_get_pasid(client->sva);79if (client->pasid == IOMMU_PASID_INVALID) {80XDNA_ERR(xdna, "SVA get pasid failed");81ret = -ENODEV;82goto unbind_sva;83}84client->mm = current->mm;85mmgrab(client->mm);86init_srcu_struct(&client->hwctx_srcu);87xa_init_flags(&client->hwctx_xa, XA_FLAGS_ALLOC);88mutex_init(&client->mm_lock);8990mutex_lock(&xdna->dev_lock);91list_add_tail(&client->node, &xdna->client_list);92mutex_unlock(&xdna->dev_lock);9394filp->driver_priv = client;95client->filp = filp;9697XDNA_DBG(xdna, "pid %d opened", client->pid);98return 0;99100unbind_sva:101iommu_sva_unbind_device(client->sva);102failed:103kfree(client);104105return ret;106}107108static void amdxdna_client_cleanup(struct amdxdna_client *client)109{110list_del(&client->node);111amdxdna_hwctx_remove_all(client);112xa_destroy(&client->hwctx_xa);113cleanup_srcu_struct(&client->hwctx_srcu);114mutex_destroy(&client->mm_lock);115116if (client->dev_heap)117drm_gem_object_put(to_gobj(client->dev_heap));118119iommu_sva_unbind_device(client->sva);120mmdrop(client->mm);121122kfree(client);123}124125static void amdxdna_drm_close(struct drm_device *ddev, struct drm_file *filp)126{127struct amdxdna_client *client = filp->driver_priv;128struct amdxdna_dev *xdna = to_xdna_dev(ddev);129int idx;130131XDNA_DBG(xdna, "closing pid %d", client->pid);132133if (!drm_dev_enter(&xdna->ddev, &idx))134return;135136mutex_lock(&xdna->dev_lock);137amdxdna_client_cleanup(client);138mutex_unlock(&xdna->dev_lock);139140drm_dev_exit(idx);141}142143static int amdxdna_drm_get_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)144{145struct amdxdna_client *client = filp->driver_priv;146struct amdxdna_dev *xdna = to_xdna_dev(dev);147struct amdxdna_drm_get_info *args = data;148int ret;149150if (!xdna->dev_info->ops->get_aie_info)151return -EOPNOTSUPP;152153XDNA_DBG(xdna, "Request parameter %u", args->param);154mutex_lock(&xdna->dev_lock);155ret = xdna->dev_info->ops->get_aie_info(client, args);156mutex_unlock(&xdna->dev_lock);157return ret;158}159160static int amdxdna_drm_get_array_ioctl(struct drm_device *dev, void *data,161struct drm_file *filp)162{163struct amdxdna_client *client = filp->driver_priv;164struct amdxdna_dev *xdna = to_xdna_dev(dev);165struct amdxdna_drm_get_array *args = data;166167if (!xdna->dev_info->ops->get_array)168return -EOPNOTSUPP;169170if (args->pad || !args->num_element || !args->element_size)171return -EINVAL;172173guard(mutex)(&xdna->dev_lock);174return xdna->dev_info->ops->get_array(client, args);175}176177static int amdxdna_drm_set_state_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)178{179struct amdxdna_client *client = filp->driver_priv;180struct amdxdna_dev *xdna = to_xdna_dev(dev);181struct amdxdna_drm_set_state *args = data;182int ret;183184if (!xdna->dev_info->ops->set_aie_state)185return -EOPNOTSUPP;186187XDNA_DBG(xdna, "Request parameter %u", args->param);188mutex_lock(&xdna->dev_lock);189ret = xdna->dev_info->ops->set_aie_state(client, args);190mutex_unlock(&xdna->dev_lock);191192return ret;193}194195static const struct drm_ioctl_desc amdxdna_drm_ioctls[] = {196/* Context */197DRM_IOCTL_DEF_DRV(AMDXDNA_CREATE_HWCTX, amdxdna_drm_create_hwctx_ioctl, 0),198DRM_IOCTL_DEF_DRV(AMDXDNA_DESTROY_HWCTX, amdxdna_drm_destroy_hwctx_ioctl, 0),199DRM_IOCTL_DEF_DRV(AMDXDNA_CONFIG_HWCTX, amdxdna_drm_config_hwctx_ioctl, 0),200/* BO */201DRM_IOCTL_DEF_DRV(AMDXDNA_CREATE_BO, amdxdna_drm_create_bo_ioctl, 0),202DRM_IOCTL_DEF_DRV(AMDXDNA_GET_BO_INFO, amdxdna_drm_get_bo_info_ioctl, 0),203DRM_IOCTL_DEF_DRV(AMDXDNA_SYNC_BO, amdxdna_drm_sync_bo_ioctl, 0),204/* Execution */205DRM_IOCTL_DEF_DRV(AMDXDNA_EXEC_CMD, amdxdna_drm_submit_cmd_ioctl, 0),206/* AIE hardware */207DRM_IOCTL_DEF_DRV(AMDXDNA_GET_INFO, amdxdna_drm_get_info_ioctl, 0),208DRM_IOCTL_DEF_DRV(AMDXDNA_GET_ARRAY, amdxdna_drm_get_array_ioctl, 0),209DRM_IOCTL_DEF_DRV(AMDXDNA_SET_STATE, amdxdna_drm_set_state_ioctl, DRM_ROOT_ONLY),210};211212static const struct file_operations amdxdna_fops = {213.owner = THIS_MODULE,214.open = accel_open,215.release = drm_release,216.unlocked_ioctl = drm_ioctl,217.compat_ioctl = drm_compat_ioctl,218.poll = drm_poll,219.read = drm_read,220.llseek = noop_llseek,221.mmap = drm_gem_mmap,222.fop_flags = FOP_UNSIGNED_OFFSET,223};224225const struct drm_driver amdxdna_drm_drv = {226.driver_features = DRIVER_GEM | DRIVER_COMPUTE_ACCEL |227DRIVER_SYNCOBJ | DRIVER_SYNCOBJ_TIMELINE,228.fops = &amdxdna_fops,229.name = "amdxdna_accel_driver",230.desc = "AMD XDNA DRM implementation",231.major = AMDXDNA_DRIVER_MAJOR,232.minor = AMDXDNA_DRIVER_MINOR,233.open = amdxdna_drm_open,234.postclose = amdxdna_drm_close,235.ioctls = amdxdna_drm_ioctls,236.num_ioctls = ARRAY_SIZE(amdxdna_drm_ioctls),237238.gem_create_object = amdxdna_gem_create_object_cb,239.gem_prime_import = amdxdna_gem_prime_import,240};241242static const struct amdxdna_dev_info *243amdxdna_get_dev_info(struct pci_dev *pdev)244{245int i;246247for (i = 0; i < ARRAY_SIZE(amdxdna_ids); i++) {248if (pdev->device == amdxdna_ids[i].device &&249pdev->revision == amdxdna_ids[i].revision)250return amdxdna_ids[i].dev_info;251}252return NULL;253}254255static int amdxdna_probe(struct pci_dev *pdev, const struct pci_device_id *id)256{257struct device *dev = &pdev->dev;258struct amdxdna_dev *xdna;259int ret;260261xdna = devm_drm_dev_alloc(dev, &amdxdna_drm_drv, typeof(*xdna), ddev);262if (IS_ERR(xdna))263return PTR_ERR(xdna);264265xdna->dev_info = amdxdna_get_dev_info(pdev);266if (!xdna->dev_info)267return -ENODEV;268269drmm_mutex_init(&xdna->ddev, &xdna->dev_lock);270init_rwsem(&xdna->notifier_lock);271INIT_LIST_HEAD(&xdna->client_list);272pci_set_drvdata(pdev, xdna);273274if (IS_ENABLED(CONFIG_LOCKDEP)) {275fs_reclaim_acquire(GFP_KERNEL);276might_lock(&xdna->notifier_lock);277fs_reclaim_release(GFP_KERNEL);278}279280xdna->notifier_wq = alloc_ordered_workqueue("notifier_wq", WQ_MEM_RECLAIM);281if (!xdna->notifier_wq)282return -ENOMEM;283284mutex_lock(&xdna->dev_lock);285ret = xdna->dev_info->ops->init(xdna);286mutex_unlock(&xdna->dev_lock);287if (ret) {288XDNA_ERR(xdna, "Hardware init failed, ret %d", ret);289goto destroy_notifier_wq;290}291292ret = amdxdna_sysfs_init(xdna);293if (ret) {294XDNA_ERR(xdna, "Create amdxdna attrs failed: %d", ret);295goto failed_dev_fini;296}297298ret = drm_dev_register(&xdna->ddev, 0);299if (ret) {300XDNA_ERR(xdna, "DRM register failed, ret %d", ret);301goto failed_sysfs_fini;302}303304return 0;305306failed_sysfs_fini:307amdxdna_sysfs_fini(xdna);308failed_dev_fini:309mutex_lock(&xdna->dev_lock);310xdna->dev_info->ops->fini(xdna);311mutex_unlock(&xdna->dev_lock);312destroy_notifier_wq:313destroy_workqueue(xdna->notifier_wq);314return ret;315}316317static void amdxdna_remove(struct pci_dev *pdev)318{319struct amdxdna_dev *xdna = pci_get_drvdata(pdev);320struct amdxdna_client *client;321322destroy_workqueue(xdna->notifier_wq);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) {331amdxdna_client_cleanup(client);332333client = list_first_entry_or_null(&xdna->client_list,334struct amdxdna_client, node);335}336337xdna->dev_info->ops->fini(xdna);338mutex_unlock(&xdna->dev_lock);339}340341static const struct dev_pm_ops amdxdna_pm_ops = {342SYSTEM_SLEEP_PM_OPS(amdxdna_pm_suspend, amdxdna_pm_resume)343RUNTIME_PM_OPS(amdxdna_pm_suspend, amdxdna_pm_resume, NULL)344};345346static struct pci_driver amdxdna_pci_driver = {347.name = KBUILD_MODNAME,348.id_table = pci_ids,349.probe = amdxdna_probe,350.remove = amdxdna_remove,351.driver.pm = &amdxdna_pm_ops,352};353354module_pci_driver(amdxdna_pci_driver);355356MODULE_LICENSE("GPL");357MODULE_AUTHOR("XRT Team <[email protected]>");358MODULE_DESCRIPTION("amdxdna driver");359360361