Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
host-bridge.c
Go to the documentation of this file.
1 /*
2  * host bridge related code
3  */
4 
5 #include <linux/kernel.h>
6 #include <linux/init.h>
7 #include <linux/pci.h>
8 #include <linux/module.h>
9 
10 #include "pci.h"
11 
12 static struct pci_bus *find_pci_root_bus(struct pci_dev *dev)
13 {
14  struct pci_bus *bus;
15 
16  bus = dev->bus;
17  while (bus->parent)
18  bus = bus->parent;
19 
20  return bus;
21 }
22 
23 static struct pci_host_bridge *find_pci_host_bridge(struct pci_dev *dev)
24 {
25  struct pci_bus *bus = find_pci_root_bus(dev);
26 
27  return to_pci_host_bridge(bus->bridge);
28 }
29 
31  void (*release_fn)(struct pci_host_bridge *),
32  void *release_data)
33 {
34  bridge->release_fn = release_fn;
35  bridge->release_data = release_data;
36 }
37 
38 static bool resource_contains(struct resource *res1, struct resource *res2)
39 {
40  return res1->start <= res2->start && res1->end >= res2->end;
41 }
42 
44  struct resource *res)
45 {
46  struct pci_host_bridge *bridge = find_pci_host_bridge(dev);
49 
50  list_for_each_entry(window, &bridge->windows, list) {
51  if (resource_type(res) != resource_type(window->res))
52  continue;
53 
54  if (resource_contains(window->res, res)) {
55  offset = window->offset;
56  break;
57  }
58  }
59 
60  region->start = res->start - offset;
61  region->end = res->end - offset;
62 }
64 
65 static bool region_contains(struct pci_bus_region *region1,
66  struct pci_bus_region *region2)
67 {
68  return region1->start <= region2->start && region1->end >= region2->end;
69 }
70 
71 void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
72  struct pci_bus_region *region)
73 {
74  struct pci_host_bridge *bridge = find_pci_host_bridge(dev);
77 
78  list_for_each_entry(window, &bridge->windows, list) {
79  struct pci_bus_region bus_region;
80 
81  if (resource_type(res) != resource_type(window->res))
82  continue;
83 
84  bus_region.start = window->res->start - window->offset;
85  bus_region.end = window->res->end - window->offset;
86 
87  if (region_contains(&bus_region, region)) {
88  offset = window->offset;
89  break;
90  }
91  }
92 
93  res->start = region->start + offset;
94  res->end = region->end + offset;
95 }