Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0 2 : : /* 3 : : * Host bridge related code 4 : : */ 5 : : 6 : : #include <linux/kernel.h> 7 : : #include <linux/pci.h> 8 : : #include <linux/module.h> 9 : : 10 : : #include "pci.h" 11 : : 12 : 141 : static struct pci_bus *find_pci_root_bus(struct pci_bus *bus) 13 : : { 14 [ - + - + : 141 : while (bus->parent) - + - + ] 15 : : bus = bus->parent; 16 : : 17 : 141 : return bus; 18 : : } 19 : : 20 : 123 : struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus) 21 : : { 22 : 57 : struct pci_bus *root_bus = find_pci_root_bus(bus); 23 : : 24 : 123 : return to_pci_host_bridge(root_bus->bridge); 25 : : } 26 : : 27 : 18 : struct device *pci_get_host_bridge_device(struct pci_dev *dev) 28 : : { 29 : 18 : struct pci_bus *root_bus = find_pci_root_bus(dev->bus); 30 : 18 : struct device *bridge = root_bus->bridge; 31 : : 32 : 18 : kobject_get(&bridge->kobj); 33 : 18 : return bridge; 34 : : } 35 : : 36 : 18 : void pci_put_host_bridge_device(struct device *dev) 37 : : { 38 : 18 : kobject_put(&dev->kobj); 39 : 18 : } 40 : : 41 : 3 : void pci_set_host_bridge_release(struct pci_host_bridge *bridge, 42 : : void (*release_fn)(struct pci_host_bridge *), 43 : : void *release_data) 44 : : { 45 : 3 : bridge->release_fn = release_fn; 46 : 3 : bridge->release_data = release_data; 47 : 3 : } 48 : : EXPORT_SYMBOL_GPL(pci_set_host_bridge_release); 49 : : 50 : 24 : void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region, 51 : : struct resource *res) 52 : : { 53 : 24 : struct pci_host_bridge *bridge = pci_find_host_bridge(bus); 54 : 24 : struct resource_entry *window; 55 : 24 : resource_size_t offset = 0; 56 : : 57 [ + - ]: 90 : resource_list_for_each_entry(window, &bridge->windows) { 58 [ + + + + ]: 138 : if (resource_contains(window->res, res)) { 59 : 24 : offset = window->offset; 60 : 24 : break; 61 : : } 62 : : } 63 : : 64 : 24 : region->start = res->start - offset; 65 : 24 : region->end = res->end - offset; 66 : 24 : } 67 : : EXPORT_SYMBOL(pcibios_resource_to_bus); 68 : : 69 : 66 : static bool region_contains(struct pci_bus_region *region1, 70 : : struct pci_bus_region *region2) 71 : : { 72 [ + + ]: 66 : return region1->start <= region2->start && region1->end >= region2->end; 73 : : } 74 : : 75 : 42 : void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res, 76 : : struct pci_bus_region *region) 77 : : { 78 : 42 : struct pci_host_bridge *bridge = pci_find_host_bridge(bus); 79 : 42 : struct resource_entry *window; 80 : 42 : resource_size_t offset = 0; 81 : : 82 [ + - ]: 108 : resource_list_for_each_entry(window, &bridge->windows) { 83 : 108 : struct pci_bus_region bus_region; 84 : : 85 [ + + ]: 108 : if (resource_type(res) != resource_type(window->res)) 86 : 42 : continue; 87 : : 88 : 66 : bus_region.start = window->res->start - window->offset; 89 : 66 : bus_region.end = window->res->end - window->offset; 90 : : 91 [ + - + + ]: 132 : if (region_contains(&bus_region, region)) { 92 : 42 : offset = window->offset; 93 : 42 : break; 94 : : } 95 : : } 96 : : 97 : 42 : res->start = region->start + offset; 98 : 42 : res->end = region->end + offset; 99 : 42 : } 100 : : EXPORT_SYMBOL(pcibios_bus_to_resource);