diff --git a/kernel/nv-drm.c b/kernel/nv-drm.c index 2e4b867..059f258 100644 --- a/kernel/nv-drm.c +++ b/kernel/nv-drm.c @@ -51,6 +51,137 @@ #define nv_drm_pci_init drm_legacy_pci_init #define nv_drm_pci_exit drm_legacy_pci_exit #elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) +#include + +struct drm_agp_mem { + unsigned long handle; + struct agp_memory *memory; + unsigned long bound; + int pages; + struct list_head head; +}; + +/** + * drm_legacy_agp_clear - Clear AGP resource list + * @dev: DRM device + * + * Iterate over all AGP resources and remove them. But keep the AGP head + * intact so it can still be used. It is safe to call this if AGP is disabled or + * was already removed. + * + * Cleanup is only done for drivers who have DRIVER_LEGACY set. + */ +void drm_legacy_agp_clear(struct drm_device *dev) +{ + struct drm_agp_mem *entry, *tempe; + + if (!dev->agp) + return; + if (!drm_core_check_feature(dev, DRIVER_LEGACY)) + return; + + list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) { + if (entry->bound) + agp_unbind_memory(entry->memory); + agp_free_memory(entry->memory); + kfree(entry); + } + INIT_LIST_HEAD(&dev->agp->memory); + + if (dev->agp->acquired) + drm_agp_release(dev); + + dev->agp->acquired = 0; + dev->agp->enabled = 0; +} + +static void drm_pci_agp_init(struct drm_device *dev) +{ + if (drm_core_check_feature(dev, DRIVER_USE_AGP)) { + if (pci_find_capability(dev->pdev, PCI_CAP_ID_AGP)) + dev->agp = drm_agp_init(dev); + if (dev->agp) { + dev->agp->agp_mtrr = arch_phys_wc_add( + dev->agp->agp_info.aper_base, + dev->agp->agp_info.aper_size * + 1024 * 1024); + } + } +} + +void drm_pci_agp_destroy(struct drm_device *dev) +{ + if (dev->agp) { + arch_phys_wc_del(dev->agp->agp_mtrr); + drm_legacy_agp_clear(dev); + kfree(dev->agp); + dev->agp = NULL; + } +} + +/** + * drm_get_pci_dev - Register a PCI device with the DRM subsystem + * @pdev: PCI device + * @ent: entry from the PCI ID table that matches @pdev + * @driver: DRM device driver + * + * Attempt to gets inter module "drm" information. If we are first + * then register the character device and inter module information. + * Try and register, if we fail to register, backout previous work. + * + * NOTE: This function is deprecated, please use drm_dev_alloc() and + * drm_dev_register() instead and remove your &drm_driver.load callback. + * + * Return: 0 on success or a negative error code on failure. + */ +int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, + struct drm_driver *driver) +{ + struct drm_device *dev; + int ret; + + DRM_DEBUG("\n"); + + dev = drm_dev_alloc(driver, &pdev->dev); + if (IS_ERR(dev)) + return PTR_ERR(dev); + + ret = pci_enable_device(pdev); + if (ret) + goto err_free; + + dev->pdev = pdev; +#ifdef __alpha__ + dev->hose = pdev->sysdata; +#endif + + if (drm_core_check_feature(dev, DRIVER_MODESET)) + pci_set_drvdata(pdev, dev); + + drm_pci_agp_init(dev); + + ret = drm_dev_register(dev, ent->driver_data); + if (ret) + goto err_agp; + + /* No locking needed since shadow-attach is single-threaded since it may + * only be called from the per-driver module init hook. */ + if (drm_core_check_feature(dev, DRIVER_LEGACY)) + list_add_tail(&dev->legacy_dev_list, &driver->legacy_dev_list); + + return 0; + +err_agp: + drm_pci_agp_destroy(dev); + pci_disable_device(pdev); +err_free: + drm_dev_put(dev); + return ret; +} +#endif + int nv_drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) { struct pci_dev *pdev = NULL;