LCOV - code coverage report
Current view: top level - drivers/pci - remove.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 82 0.0 %
Date: 2022-03-28 13:20:08 Functions: 0 10 0.0 %
Branches: 0 28 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : #include <linux/pci.h>
       3                 :            : #include <linux/module.h>
       4                 :            : #include "pci.h"
       5                 :            : 
       6                 :          0 : static void pci_free_resources(struct pci_dev *dev)
       7                 :            : {
       8                 :          0 :         int i;
       9                 :            : 
      10         [ #  # ]:          0 :         for (i = 0; i < PCI_NUM_RESOURCES; i++) {
      11                 :          0 :                 struct resource *res = dev->resource + i;
      12         [ #  # ]:          0 :                 if (res->parent)
      13                 :          0 :                         release_resource(res);
      14                 :            :         }
      15                 :          0 : }
      16                 :            : 
      17                 :          0 : static void pci_stop_dev(struct pci_dev *dev)
      18                 :            : {
      19                 :          0 :         pci_pme_active(dev, false);
      20                 :            : 
      21         [ #  # ]:          0 :         if (pci_dev_is_added(dev)) {
      22                 :          0 :                 device_release_driver(&dev->dev);
      23                 :          0 :                 pci_proc_detach_device(dev);
      24                 :          0 :                 pci_remove_sysfs_dev_files(dev);
      25                 :            : 
      26                 :          0 :                 pci_dev_assign_added(dev, false);
      27                 :            :         }
      28                 :          0 : }
      29                 :            : 
      30                 :          0 : static void pci_destroy_dev(struct pci_dev *dev)
      31                 :            : {
      32         [ #  # ]:          0 :         if (!dev->dev.kobj.parent)
      33                 :            :                 return;
      34                 :            : 
      35                 :          0 :         device_del(&dev->dev);
      36                 :            : 
      37                 :          0 :         down_write(&pci_bus_sem);
      38                 :          0 :         list_del(&dev->bus_list);
      39                 :          0 :         up_write(&pci_bus_sem);
      40                 :            : 
      41                 :          0 :         pcie_aspm_exit_link_state(dev);
      42                 :          0 :         pci_bridge_d3_update(dev);
      43                 :          0 :         pci_free_resources(dev);
      44                 :          0 :         put_device(&dev->dev);
      45                 :            : }
      46                 :            : 
      47                 :          0 : void pci_remove_bus(struct pci_bus *bus)
      48                 :            : {
      49                 :          0 :         pci_proc_detach_bus(bus);
      50                 :            : 
      51                 :          0 :         down_write(&pci_bus_sem);
      52                 :          0 :         list_del(&bus->node);
      53                 :          0 :         pci_bus_release_busn_res(bus);
      54                 :          0 :         up_write(&pci_bus_sem);
      55         [ #  # ]:          0 :         pci_remove_legacy_files(bus);
      56                 :            : 
      57         [ #  # ]:          0 :         if (bus->ops->remove_bus)
      58                 :          0 :                 bus->ops->remove_bus(bus);
      59                 :            : 
      60                 :          0 :         pcibios_remove_bus(bus);
      61                 :          0 :         device_unregister(&bus->dev);
      62                 :          0 : }
      63                 :            : EXPORT_SYMBOL(pci_remove_bus);
      64                 :            : 
      65                 :          0 : static void pci_stop_bus_device(struct pci_dev *dev)
      66                 :            : {
      67                 :          0 :         struct pci_bus *bus = dev->subordinate;
      68                 :          0 :         struct pci_dev *child, *tmp;
      69                 :            : 
      70                 :            :         /*
      71                 :            :          * Stopping an SR-IOV PF device removes all the associated VFs,
      72                 :            :          * which will update the bus->devices list and confuse the
      73                 :            :          * iterator.  Therefore, iterate in reverse so we remove the VFs
      74                 :            :          * first, then the PF.
      75                 :            :          */
      76         [ #  # ]:          0 :         if (bus) {
      77         [ #  # ]:          0 :                 list_for_each_entry_safe_reverse(child, tmp,
      78                 :            :                                                  &bus->devices, bus_list)
      79                 :          0 :                         pci_stop_bus_device(child);
      80                 :            :         }
      81                 :            : 
      82                 :          0 :         pci_stop_dev(dev);
      83                 :          0 : }
      84                 :            : 
      85                 :          0 : static void pci_remove_bus_device(struct pci_dev *dev)
      86                 :            : {
      87                 :          0 :         struct pci_bus *bus = dev->subordinate;
      88                 :          0 :         struct pci_dev *child, *tmp;
      89                 :            : 
      90         [ #  # ]:          0 :         if (bus) {
      91         [ #  # ]:          0 :                 list_for_each_entry_safe(child, tmp,
      92                 :            :                                          &bus->devices, bus_list)
      93                 :          0 :                         pci_remove_bus_device(child);
      94                 :            : 
      95                 :          0 :                 pci_remove_bus(bus);
      96                 :          0 :                 dev->subordinate = NULL;
      97                 :            :         }
      98                 :            : 
      99                 :          0 :         pci_destroy_dev(dev);
     100                 :          0 : }
     101                 :            : 
     102                 :            : /**
     103                 :            :  * pci_stop_and_remove_bus_device - remove a PCI device and any children
     104                 :            :  * @dev: the device to remove
     105                 :            :  *
     106                 :            :  * Remove a PCI device from the device lists, informing the drivers
     107                 :            :  * that the device has been removed.  We also remove any subordinate
     108                 :            :  * buses and children in a depth-first manner.
     109                 :            :  *
     110                 :            :  * For each device we remove, delete the device structure from the
     111                 :            :  * device lists, remove the /proc entry, and notify userspace
     112                 :            :  * (/sbin/hotplug).
     113                 :            :  */
     114                 :          0 : void pci_stop_and_remove_bus_device(struct pci_dev *dev)
     115                 :            : {
     116                 :          0 :         pci_stop_bus_device(dev);
     117                 :          0 :         pci_remove_bus_device(dev);
     118                 :          0 : }
     119                 :            : EXPORT_SYMBOL(pci_stop_and_remove_bus_device);
     120                 :            : 
     121                 :          0 : void pci_stop_and_remove_bus_device_locked(struct pci_dev *dev)
     122                 :            : {
     123                 :          0 :         pci_lock_rescan_remove();
     124                 :          0 :         pci_stop_and_remove_bus_device(dev);
     125                 :          0 :         pci_unlock_rescan_remove();
     126                 :          0 : }
     127                 :            : EXPORT_SYMBOL_GPL(pci_stop_and_remove_bus_device_locked);
     128                 :            : 
     129                 :          0 : void pci_stop_root_bus(struct pci_bus *bus)
     130                 :            : {
     131                 :          0 :         struct pci_dev *child, *tmp;
     132                 :          0 :         struct pci_host_bridge *host_bridge;
     133                 :            : 
     134         [ #  # ]:          0 :         if (!pci_is_root_bus(bus))
     135                 :            :                 return;
     136                 :            : 
     137                 :          0 :         host_bridge = to_pci_host_bridge(bus->bridge);
     138         [ #  # ]:          0 :         list_for_each_entry_safe_reverse(child, tmp,
     139                 :            :                                          &bus->devices, bus_list)
     140                 :          0 :                 pci_stop_bus_device(child);
     141                 :            : 
     142                 :            :         /* stop the host bridge */
     143                 :          0 :         device_release_driver(&host_bridge->dev);
     144                 :            : }
     145                 :            : EXPORT_SYMBOL_GPL(pci_stop_root_bus);
     146                 :            : 
     147                 :          0 : void pci_remove_root_bus(struct pci_bus *bus)
     148                 :            : {
     149                 :          0 :         struct pci_dev *child, *tmp;
     150                 :          0 :         struct pci_host_bridge *host_bridge;
     151                 :            : 
     152         [ #  # ]:          0 :         if (!pci_is_root_bus(bus))
     153                 :            :                 return;
     154                 :            : 
     155                 :          0 :         host_bridge = to_pci_host_bridge(bus->bridge);
     156         [ #  # ]:          0 :         list_for_each_entry_safe(child, tmp,
     157                 :            :                                  &bus->devices, bus_list)
     158                 :          0 :                 pci_remove_bus_device(child);
     159                 :          0 :         pci_remove_bus(bus);
     160                 :          0 :         host_bridge->bus = NULL;
     161                 :            : 
     162                 :            :         /* remove the host bridge */
     163                 :          0 :         device_unregister(&host_bridge->dev);
     164                 :            : }
     165                 :            : EXPORT_SYMBOL_GPL(pci_remove_root_bus);

Generated by: LCOV version 1.14