LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_pci.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 9 0.0 %
Date: 2023-07-19 18:55:55 Functions: 0 1 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2003 José Fonseca.
       3             :  * Copyright 2003 Leif Delgass.
       4             :  * All Rights Reserved.
       5             :  *
       6             :  * Permission is hereby granted, free of charge, to any person obtaining a
       7             :  * copy of this software and associated documentation files (the "Software"),
       8             :  * to deal in the Software without restriction, including without limitation
       9             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      10             :  * and/or sell copies of the Software, and to permit persons to whom the
      11             :  * Software is furnished to do so, subject to the following conditions:
      12             :  *
      13             :  * The above copyright notice and this permission notice (including the next
      14             :  * paragraph) shall be included in all copies or substantial portions of the
      15             :  * Software.
      16             :  *
      17             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      18             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      19             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
      20             :  * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
      21             :  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
      22             :  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      23             :  */
      24             : 
      25             : #include <linux/dma-mapping.h>
      26             : #include <linux/export.h>
      27             : #include <linux/list.h>
      28             : #include <linux/mutex.h>
      29             : #include <linux/pci.h>
      30             : #include <linux/slab.h>
      31             : 
      32             : #include <drm/drm.h>
      33             : #include <drm/drm_drv.h>
      34             : #include <drm/drm_print.h>
      35             : 
      36             : #include "drm_internal.h"
      37             : #include "drm_legacy.h"
      38             : 
      39             : #ifdef CONFIG_DRM_LEGACY
      40             : /* List of devices hanging off drivers with stealth attach. */
      41             : static LIST_HEAD(legacy_dev_list);
      42             : static DEFINE_MUTEX(legacy_dev_list_lock);
      43             : #endif
      44             : 
      45             : static int drm_get_pci_domain(struct drm_device *dev)
      46             : {
      47             : #ifndef __alpha__
      48             :         /* For historical reasons, drm_get_pci_domain() is busticated
      49             :          * on most archs and has to remain so for userspace interface
      50             :          * < 1.4, except on alpha which was right from the beginning
      51             :          */
      52             :         if (dev->if_version < 0x10004)
      53             :                 return 0;
      54             : #endif /* __alpha__ */
      55             : 
      56             :         return pci_domain_nr(to_pci_dev(dev->dev)->bus);
      57             : }
      58             : 
      59           0 : int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master)
      60             : {
      61           0 :         struct pci_dev *pdev = to_pci_dev(dev->dev);
      62             : 
      63           0 :         master->unique = kasprintf(GFP_KERNEL, "pci:%04x:%02x:%02x.%d",
      64             :                                         drm_get_pci_domain(dev),
      65           0 :                                         pdev->bus->number,
      66           0 :                                         PCI_SLOT(pdev->devfn),
      67           0 :                                         PCI_FUNC(pdev->devfn));
      68           0 :         if (!master->unique)
      69             :                 return -ENOMEM;
      70             : 
      71           0 :         master->unique_len = strlen(master->unique);
      72           0 :         return 0;
      73             : }
      74             : 
      75             : #ifdef CONFIG_DRM_LEGACY
      76             : 
      77             : static int drm_legacy_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
      78             : {
      79             :         struct pci_dev *pdev = to_pci_dev(dev->dev);
      80             : 
      81             :         if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
      82             :             (p->busnum & 0xff) != pdev->bus->number ||
      83             :             p->devnum != PCI_SLOT(pdev->devfn) || p->funcnum != PCI_FUNC(pdev->devfn))
      84             :                 return -EINVAL;
      85             : 
      86             :         p->irq = pdev->irq;
      87             : 
      88             :         DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
      89             :                   p->irq);
      90             :         return 0;
      91             : }
      92             : 
      93             : /**
      94             :  * drm_legacy_irq_by_busid - Get interrupt from bus ID
      95             :  * @dev: DRM device
      96             :  * @data: IOCTL parameter pointing to a drm_irq_busid structure
      97             :  * @file_priv: DRM file private.
      98             :  *
      99             :  * Finds the PCI device with the specified bus id and gets its IRQ number.
     100             :  * This IOCTL is deprecated, and will now return EINVAL for any busid not equal
     101             :  * to that of the device that this DRM instance attached to.
     102             :  *
     103             :  * Return: 0 on success or a negative error code on failure.
     104             :  */
     105             : int drm_legacy_irq_by_busid(struct drm_device *dev, void *data,
     106             :                             struct drm_file *file_priv)
     107             : {
     108             :         struct drm_irq_busid *p = data;
     109             : 
     110             :         if (!drm_core_check_feature(dev, DRIVER_LEGACY))
     111             :                 return -EOPNOTSUPP;
     112             : 
     113             :         /* UMS was only ever support on PCI devices. */
     114             :         if (WARN_ON(!dev_is_pci(dev->dev)))
     115             :                 return -EINVAL;
     116             : 
     117             :         if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
     118             :                 return -EOPNOTSUPP;
     119             : 
     120             :         return drm_legacy_pci_irq_by_busid(dev, p);
     121             : }
     122             : 
     123             : void drm_legacy_pci_agp_destroy(struct drm_device *dev)
     124             : {
     125             :         if (dev->agp) {
     126             :                 arch_phys_wc_del(dev->agp->agp_mtrr);
     127             :                 drm_legacy_agp_clear(dev);
     128             :                 kfree(dev->agp);
     129             :                 dev->agp = NULL;
     130             :         }
     131             : }
     132             : 
     133             : static void drm_legacy_pci_agp_init(struct drm_device *dev)
     134             : {
     135             :         if (drm_core_check_feature(dev, DRIVER_USE_AGP)) {
     136             :                 if (pci_find_capability(to_pci_dev(dev->dev), PCI_CAP_ID_AGP))
     137             :                         dev->agp = drm_legacy_agp_init(dev);
     138             :                 if (dev->agp) {
     139             :                         dev->agp->agp_mtrr = arch_phys_wc_add(
     140             :                                 dev->agp->agp_info.aper_base,
     141             :                                 dev->agp->agp_info.aper_size *
     142             :                                 1024 * 1024);
     143             :                 }
     144             :         }
     145             : }
     146             : 
     147             : static int drm_legacy_get_pci_dev(struct pci_dev *pdev,
     148             :                                   const struct pci_device_id *ent,
     149             :                                   const struct drm_driver *driver)
     150             : {
     151             :         struct drm_device *dev;
     152             :         int ret;
     153             : 
     154             :         DRM_DEBUG("\n");
     155             : 
     156             :         dev = drm_dev_alloc(driver, &pdev->dev);
     157             :         if (IS_ERR(dev))
     158             :                 return PTR_ERR(dev);
     159             : 
     160             :         ret = pci_enable_device(pdev);
     161             :         if (ret)
     162             :                 goto err_free;
     163             : 
     164             : #ifdef __alpha__
     165             :         dev->hose = pdev->sysdata;
     166             : #endif
     167             : 
     168             :         drm_legacy_pci_agp_init(dev);
     169             : 
     170             :         ret = drm_dev_register(dev, ent->driver_data);
     171             :         if (ret)
     172             :                 goto err_agp;
     173             : 
     174             :         if (drm_core_check_feature(dev, DRIVER_LEGACY)) {
     175             :                 mutex_lock(&legacy_dev_list_lock);
     176             :                 list_add_tail(&dev->legacy_dev_list, &legacy_dev_list);
     177             :                 mutex_unlock(&legacy_dev_list_lock);
     178             :         }
     179             : 
     180             :         return 0;
     181             : 
     182             : err_agp:
     183             :         drm_legacy_pci_agp_destroy(dev);
     184             :         pci_disable_device(pdev);
     185             : err_free:
     186             :         drm_dev_put(dev);
     187             :         return ret;
     188             : }
     189             : 
     190             : /**
     191             :  * drm_legacy_pci_init - shadow-attach a legacy DRM PCI driver
     192             :  * @driver: DRM device driver
     193             :  * @pdriver: PCI device driver
     194             :  *
     195             :  * This is only used by legacy dri1 drivers and deprecated.
     196             :  *
     197             :  * Return: 0 on success or a negative error code on failure.
     198             :  */
     199             : int drm_legacy_pci_init(const struct drm_driver *driver,
     200             :                         struct pci_driver *pdriver)
     201             : {
     202             :         struct pci_dev *pdev = NULL;
     203             :         const struct pci_device_id *pid;
     204             :         int i;
     205             : 
     206             :         DRM_DEBUG("\n");
     207             : 
     208             :         if (WARN_ON(!(driver->driver_features & DRIVER_LEGACY)))
     209             :                 return -EINVAL;
     210             : 
     211             :         /* If not using KMS, fall back to stealth mode manual scanning. */
     212             :         for (i = 0; pdriver->id_table[i].vendor != 0; i++) {
     213             :                 pid = &pdriver->id_table[i];
     214             : 
     215             :                 /* Loop around setting up a DRM device for each PCI device
     216             :                  * matching our ID and device class.  If we had the internal
     217             :                  * function that pci_get_subsys and pci_get_class used, we'd
     218             :                  * be able to just pass pid in instead of doing a two-stage
     219             :                  * thing.
     220             :                  */
     221             :                 pdev = NULL;
     222             :                 while ((pdev =
     223             :                         pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
     224             :                                        pid->subdevice, pdev)) != NULL) {
     225             :                         if ((pdev->class & pid->class_mask) != pid->class)
     226             :                                 continue;
     227             : 
     228             :                         /* stealth mode requires a manual probe */
     229             :                         pci_dev_get(pdev);
     230             :                         drm_legacy_get_pci_dev(pdev, pid, driver);
     231             :                 }
     232             :         }
     233             :         return 0;
     234             : }
     235             : EXPORT_SYMBOL(drm_legacy_pci_init);
     236             : 
     237             : /**
     238             :  * drm_legacy_pci_exit - unregister shadow-attach legacy DRM driver
     239             :  * @driver: DRM device driver
     240             :  * @pdriver: PCI device driver
     241             :  *
     242             :  * Unregister a DRM driver shadow-attached through drm_legacy_pci_init(). This
     243             :  * is deprecated and only used by dri1 drivers.
     244             :  */
     245             : void drm_legacy_pci_exit(const struct drm_driver *driver,
     246             :                          struct pci_driver *pdriver)
     247             : {
     248             :         struct drm_device *dev, *tmp;
     249             : 
     250             :         DRM_DEBUG("\n");
     251             : 
     252             :         if (!(driver->driver_features & DRIVER_LEGACY)) {
     253             :                 WARN_ON(1);
     254             :         } else {
     255             :                 mutex_lock(&legacy_dev_list_lock);
     256             :                 list_for_each_entry_safe(dev, tmp, &legacy_dev_list,
     257             :                                          legacy_dev_list) {
     258             :                         if (dev->driver == driver) {
     259             :                                 list_del(&dev->legacy_dev_list);
     260             :                                 drm_put_dev(dev);
     261             :                         }
     262             :                 }
     263             :                 mutex_unlock(&legacy_dev_list_lock);
     264             :         }
     265             :         DRM_INFO("Module unloaded\n");
     266             : }
     267             : EXPORT_SYMBOL(drm_legacy_pci_exit);
     268             : 
     269             : #endif

Generated by: LCOV version 1.14