diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-21 19:24:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-21 19:24:54 -0400 |
commit | 3bb07f1b73ea6313b843807063e183e168c9182a (patch) | |
tree | f0e2ab77b8bc993a843a0edede00668c589863cc /drivers | |
parent | 6326c71fd2fb3bef5fa33951479298b683da35fe (diff) | |
parent | 5420e46d4d79bcd5d5952df98d022c8412385d32 (diff) |
Merge tag 'pci-for-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI changes from Bjorn Helgaas:
- Host bridge cleanups from Yinghai
- Disable Bus Master bit on PCI device shutdown (kexec-related)
- Stratus ftServer fix
- pci_dev_reset() locking fix
- IvyBridge graphics erratum workaround
* tag 'pci-for-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (21 commits)
microblaze/PCI: fix "io_offset undeclared" error
x86/PCI: only check for spinlock being held in SMP kernels
resources: add resource_overlaps()
PCI: fix uninitialized variable 'cap_mask'
MAINTAINERS: update PCI git tree and patchwork
PCI: disable Bus Master on PCI device shutdown
PCI: work around IvyBridge internal graphics FLR erratum
x86/PCI: fix unused variable warning in amd_bus.c
PCI: move mutex locking out of pci_dev_reset function
PCI: work around Stratus ftServer broken PCIe hierarchy
x86/PCI: merge pcibios_scan_root() and pci_scan_bus_on_node()
x86/PCI: dynamically allocate pci_root_info for native host bridge drivers
x86/PCI: embed pci_sysdata into pci_root_info on ACPI path
x86/PCI: embed name into pci_root_info struct
x86/PCI: add host bridge resource release for _CRS path
x86/PCI: refactor get_current_resources()
PCI: add host bridge release support
PCI: add generic device into pci_host_bridge struct
PCI: rename pci_host_bridge() to find_pci_root_bridge()
x86/PCI: fix memleak with get_current_resources()
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pci/Makefile | 2 | ||||
-rw-r--r-- | drivers/pci/host-bridge.c | 96 | ||||
-rw-r--r-- | drivers/pci/pci-driver.c | 6 | ||||
-rw-r--r-- | drivers/pci/pci.c | 30 | ||||
-rw-r--r-- | drivers/pci/pcie/portdrv_core.c | 2 | ||||
-rw-r--r-- | drivers/pci/probe.c | 154 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 58 |
7 files changed, 224 insertions, 124 deletions
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 165274c064bc..01c001f3b766 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for the PCI bus specific drivers. | 2 | # Makefile for the PCI bus specific drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += access.o bus.o probe.o remove.o pci.o \ | 5 | obj-y += access.o bus.o probe.o host-bridge.o remove.o pci.o \ |
6 | pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ | 6 | pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ |
7 | irq.o vpd.o | 7 | irq.o vpd.o |
8 | obj-$(CONFIG_PROC_FS) += proc.o | 8 | obj-$(CONFIG_PROC_FS) += proc.o |
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c new file mode 100644 index 000000000000..a68dc613a5be --- /dev/null +++ b/drivers/pci/host-bridge.c | |||
@@ -0,0 +1,96 @@ | |||
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 | |||
30 | void pci_set_host_bridge_release(struct pci_host_bridge *bridge, | ||
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 | |||
43 | void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, | ||
44 | struct resource *res) | ||
45 | { | ||
46 | struct pci_host_bridge *bridge = find_pci_host_bridge(dev); | ||
47 | struct pci_host_bridge_window *window; | ||
48 | resource_size_t offset = 0; | ||
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 | } | ||
63 | EXPORT_SYMBOL(pcibios_resource_to_bus); | ||
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); | ||
75 | struct pci_host_bridge_window *window; | ||
76 | resource_size_t offset = 0; | ||
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 | } | ||
96 | EXPORT_SYMBOL(pcibios_bus_to_resource); | ||
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 6b54b23b990b..bf0cee629b60 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -421,6 +421,12 @@ static void pci_device_shutdown(struct device *dev) | |||
421 | pci_msix_shutdown(pci_dev); | 421 | pci_msix_shutdown(pci_dev); |
422 | 422 | ||
423 | /* | 423 | /* |
424 | * Turn off Bus Master bit on the device to tell it to not | ||
425 | * continue to do DMA | ||
426 | */ | ||
427 | pci_disable_device(pci_dev); | ||
428 | |||
429 | /* | ||
424 | * Devices may be enabled to wake up by runtime PM, but they need not | 430 | * Devices may be enabled to wake up by runtime PM, but they need not |
425 | * be supposed to wake up the system from its "power off" state (e.g. | 431 | * be supposed to wake up the system from its "power off" state (e.g. |
426 | * ACPI S5). Therefore disable wakeup for all devices that aren't | 432 | * ACPI S5). Therefore disable wakeup for all devices that aren't |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 111569ccab43..8f169002dc7e 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/device.h> | 23 | #include <linux/device.h> |
24 | #include <linux/pm_runtime.h> | 24 | #include <linux/pm_runtime.h> |
25 | #include <asm-generic/pci-bridge.h> | ||
25 | #include <asm/setup.h> | 26 | #include <asm/setup.h> |
26 | #include "pci.h" | 27 | #include "pci.h" |
27 | 28 | ||
@@ -3164,18 +3165,12 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe) | |||
3164 | return 0; | 3165 | return 0; |
3165 | } | 3166 | } |
3166 | 3167 | ||
3167 | static int pci_dev_reset(struct pci_dev *dev, int probe) | 3168 | static int __pci_dev_reset(struct pci_dev *dev, int probe) |
3168 | { | 3169 | { |
3169 | int rc; | 3170 | int rc; |
3170 | 3171 | ||
3171 | might_sleep(); | 3172 | might_sleep(); |
3172 | 3173 | ||
3173 | if (!probe) { | ||
3174 | pci_cfg_access_lock(dev); | ||
3175 | /* block PM suspend, driver probe, etc. */ | ||
3176 | device_lock(&dev->dev); | ||
3177 | } | ||
3178 | |||
3179 | rc = pci_dev_specific_reset(dev, probe); | 3174 | rc = pci_dev_specific_reset(dev, probe); |
3180 | if (rc != -ENOTTY) | 3175 | if (rc != -ENOTTY) |
3181 | goto done; | 3176 | goto done; |
@@ -3194,14 +3189,27 @@ static int pci_dev_reset(struct pci_dev *dev, int probe) | |||
3194 | 3189 | ||
3195 | rc = pci_parent_bus_reset(dev, probe); | 3190 | rc = pci_parent_bus_reset(dev, probe); |
3196 | done: | 3191 | done: |
3192 | return rc; | ||
3193 | } | ||
3194 | |||
3195 | static int pci_dev_reset(struct pci_dev *dev, int probe) | ||
3196 | { | ||
3197 | int rc; | ||
3198 | |||
3199 | if (!probe) { | ||
3200 | pci_cfg_access_lock(dev); | ||
3201 | /* block PM suspend, driver probe, etc. */ | ||
3202 | device_lock(&dev->dev); | ||
3203 | } | ||
3204 | |||
3205 | rc = __pci_dev_reset(dev, probe); | ||
3206 | |||
3197 | if (!probe) { | 3207 | if (!probe) { |
3198 | device_unlock(&dev->dev); | 3208 | device_unlock(&dev->dev); |
3199 | pci_cfg_access_unlock(dev); | 3209 | pci_cfg_access_unlock(dev); |
3200 | } | 3210 | } |
3201 | |||
3202 | return rc; | 3211 | return rc; |
3203 | } | 3212 | } |
3204 | |||
3205 | /** | 3213 | /** |
3206 | * __pci_reset_function - reset a PCI device function | 3214 | * __pci_reset_function - reset a PCI device function |
3207 | * @dev: PCI device to reset | 3215 | * @dev: PCI device to reset |
@@ -3246,7 +3254,7 @@ EXPORT_SYMBOL_GPL(__pci_reset_function); | |||
3246 | */ | 3254 | */ |
3247 | int __pci_reset_function_locked(struct pci_dev *dev) | 3255 | int __pci_reset_function_locked(struct pci_dev *dev) |
3248 | { | 3256 | { |
3249 | return pci_dev_reset(dev, 1); | 3257 | return __pci_dev_reset(dev, 0); |
3250 | } | 3258 | } |
3251 | EXPORT_SYMBOL_GPL(__pci_reset_function_locked); | 3259 | EXPORT_SYMBOL_GPL(__pci_reset_function_locked); |
3252 | 3260 | ||
@@ -3893,6 +3901,8 @@ static int __init pci_setup(char *str) | |||
3893 | pcie_bus_config = PCIE_BUS_PERFORMANCE; | 3901 | pcie_bus_config = PCIE_BUS_PERFORMANCE; |
3894 | } else if (!strncmp(str, "pcie_bus_peer2peer", 18)) { | 3902 | } else if (!strncmp(str, "pcie_bus_peer2peer", 18)) { |
3895 | pcie_bus_config = PCIE_BUS_PEER2PEER; | 3903 | pcie_bus_config = PCIE_BUS_PEER2PEER; |
3904 | } else if (!strncmp(str, "pcie_scan_all", 13)) { | ||
3905 | pci_add_flags(PCI_SCAN_ALL_PCIE_DEVS); | ||
3896 | } else { | 3906 | } else { |
3897 | printk(KERN_ERR "PCI: Unknown option `%s'\n", | 3907 | printk(KERN_ERR "PCI: Unknown option `%s'\n", |
3898 | str); | 3908 | str); |
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 2f589a54f9bd..75915b30ad19 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c | |||
@@ -249,7 +249,7 @@ static int get_port_device_capability(struct pci_dev *dev) | |||
249 | int services = 0, pos; | 249 | int services = 0, pos; |
250 | u16 reg16; | 250 | u16 reg16; |
251 | u32 reg32; | 251 | u32 reg32; |
252 | int cap_mask; | 252 | int cap_mask = 0; |
253 | int err; | 253 | int err; |
254 | 254 | ||
255 | if (pcie_ports_disabled) | 255 | if (pcie_ports_disabled) |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 5e1ca3c58a7d..658ac977cb56 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -10,18 +10,16 @@ | |||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/cpumask.h> | 11 | #include <linux/cpumask.h> |
12 | #include <linux/pci-aspm.h> | 12 | #include <linux/pci-aspm.h> |
13 | #include <asm-generic/pci-bridge.h> | ||
13 | #include "pci.h" | 14 | #include "pci.h" |
14 | 15 | ||
15 | #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ | 16 | #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ |
16 | #define CARDBUS_RESERVE_BUSNR 3 | 17 | #define CARDBUS_RESERVE_BUSNR 3 |
17 | 18 | ||
18 | static LIST_HEAD(pci_host_bridges); | ||
19 | |||
20 | /* Ugh. Need to stop exporting this to modules. */ | 19 | /* Ugh. Need to stop exporting this to modules. */ |
21 | LIST_HEAD(pci_root_buses); | 20 | LIST_HEAD(pci_root_buses); |
22 | EXPORT_SYMBOL(pci_root_buses); | 21 | EXPORT_SYMBOL(pci_root_buses); |
23 | 22 | ||
24 | |||
25 | static int find_anything(struct device *dev, void *data) | 23 | static int find_anything(struct device *dev, void *data) |
26 | { | 24 | { |
27 | return 1; | 25 | return 1; |
@@ -44,82 +42,6 @@ int no_pci_devices(void) | |||
44 | } | 42 | } |
45 | EXPORT_SYMBOL(no_pci_devices); | 43 | EXPORT_SYMBOL(no_pci_devices); |
46 | 44 | ||
47 | static struct pci_host_bridge *pci_host_bridge(struct pci_dev *dev) | ||
48 | { | ||
49 | struct pci_bus *bus; | ||
50 | struct pci_host_bridge *bridge; | ||
51 | |||
52 | bus = dev->bus; | ||
53 | while (bus->parent) | ||
54 | bus = bus->parent; | ||
55 | |||
56 | list_for_each_entry(bridge, &pci_host_bridges, list) { | ||
57 | if (bridge->bus == bus) | ||
58 | return bridge; | ||
59 | } | ||
60 | |||
61 | return NULL; | ||
62 | } | ||
63 | |||
64 | static bool resource_contains(struct resource *res1, struct resource *res2) | ||
65 | { | ||
66 | return res1->start <= res2->start && res1->end >= res2->end; | ||
67 | } | ||
68 | |||
69 | void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, | ||
70 | struct resource *res) | ||
71 | { | ||
72 | struct pci_host_bridge *bridge = pci_host_bridge(dev); | ||
73 | struct pci_host_bridge_window *window; | ||
74 | resource_size_t offset = 0; | ||
75 | |||
76 | list_for_each_entry(window, &bridge->windows, list) { | ||
77 | if (resource_type(res) != resource_type(window->res)) | ||
78 | continue; | ||
79 | |||
80 | if (resource_contains(window->res, res)) { | ||
81 | offset = window->offset; | ||
82 | break; | ||
83 | } | ||
84 | } | ||
85 | |||
86 | region->start = res->start - offset; | ||
87 | region->end = res->end - offset; | ||
88 | } | ||
89 | EXPORT_SYMBOL(pcibios_resource_to_bus); | ||
90 | |||
91 | static bool region_contains(struct pci_bus_region *region1, | ||
92 | struct pci_bus_region *region2) | ||
93 | { | ||
94 | return region1->start <= region2->start && region1->end >= region2->end; | ||
95 | } | ||
96 | |||
97 | void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, | ||
98 | struct pci_bus_region *region) | ||
99 | { | ||
100 | struct pci_host_bridge *bridge = pci_host_bridge(dev); | ||
101 | struct pci_host_bridge_window *window; | ||
102 | struct pci_bus_region bus_region; | ||
103 | resource_size_t offset = 0; | ||
104 | |||
105 | list_for_each_entry(window, &bridge->windows, list) { | ||
106 | if (resource_type(res) != resource_type(window->res)) | ||
107 | continue; | ||
108 | |||
109 | bus_region.start = window->res->start - window->offset; | ||
110 | bus_region.end = window->res->end - window->offset; | ||
111 | |||
112 | if (region_contains(&bus_region, region)) { | ||
113 | offset = window->offset; | ||
114 | break; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | res->start = region->start + offset; | ||
119 | res->end = region->end + offset; | ||
120 | } | ||
121 | EXPORT_SYMBOL(pcibios_bus_to_resource); | ||
122 | |||
123 | /* | 45 | /* |
124 | * PCI Bus Class | 46 | * PCI Bus Class |
125 | */ | 47 | */ |
@@ -501,6 +423,19 @@ static struct pci_bus * pci_alloc_bus(void) | |||
501 | return b; | 423 | return b; |
502 | } | 424 | } |
503 | 425 | ||
426 | static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b) | ||
427 | { | ||
428 | struct pci_host_bridge *bridge; | ||
429 | |||
430 | bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); | ||
431 | if (bridge) { | ||
432 | INIT_LIST_HEAD(&bridge->windows); | ||
433 | bridge->bus = b; | ||
434 | } | ||
435 | |||
436 | return bridge; | ||
437 | } | ||
438 | |||
504 | static unsigned char pcix_bus_speed[] = { | 439 | static unsigned char pcix_bus_speed[] = { |
505 | PCI_SPEED_UNKNOWN, /* 0 */ | 440 | PCI_SPEED_UNKNOWN, /* 0 */ |
506 | PCI_SPEED_66MHz_PCIX, /* 1 */ | 441 | PCI_SPEED_66MHz_PCIX, /* 1 */ |
@@ -1201,7 +1136,14 @@ int pci_cfg_space_size(struct pci_dev *dev) | |||
1201 | 1136 | ||
1202 | static void pci_release_bus_bridge_dev(struct device *dev) | 1137 | static void pci_release_bus_bridge_dev(struct device *dev) |
1203 | { | 1138 | { |
1204 | kfree(dev); | 1139 | struct pci_host_bridge *bridge = to_pci_host_bridge(dev); |
1140 | |||
1141 | if (bridge->release_fn) | ||
1142 | bridge->release_fn(bridge); | ||
1143 | |||
1144 | pci_free_resource_list(&bridge->windows); | ||
1145 | |||
1146 | kfree(bridge); | ||
1205 | } | 1147 | } |
1206 | 1148 | ||
1207 | struct pci_dev *alloc_pci_dev(void) | 1149 | struct pci_dev *alloc_pci_dev(void) |
@@ -1395,10 +1337,13 @@ static unsigned no_next_fn(struct pci_dev *dev, unsigned fn) | |||
1395 | static int only_one_child(struct pci_bus *bus) | 1337 | static int only_one_child(struct pci_bus *bus) |
1396 | { | 1338 | { |
1397 | struct pci_dev *parent = bus->self; | 1339 | struct pci_dev *parent = bus->self; |
1340 | |||
1398 | if (!parent || !pci_is_pcie(parent)) | 1341 | if (!parent || !pci_is_pcie(parent)) |
1399 | return 0; | 1342 | return 0; |
1400 | if (parent->pcie_type == PCI_EXP_TYPE_ROOT_PORT || | 1343 | if (parent->pcie_type == PCI_EXP_TYPE_ROOT_PORT) |
1401 | parent->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) | 1344 | return 1; |
1345 | if (parent->pcie_type == PCI_EXP_TYPE_DOWNSTREAM && | ||
1346 | !pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS)) | ||
1402 | return 1; | 1347 | return 1; |
1403 | return 0; | 1348 | return 0; |
1404 | } | 1349 | } |
@@ -1650,28 +1595,19 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, | |||
1650 | int error; | 1595 | int error; |
1651 | struct pci_host_bridge *bridge; | 1596 | struct pci_host_bridge *bridge; |
1652 | struct pci_bus *b, *b2; | 1597 | struct pci_bus *b, *b2; |
1653 | struct device *dev; | ||
1654 | struct pci_host_bridge_window *window, *n; | 1598 | struct pci_host_bridge_window *window, *n; |
1655 | struct resource *res; | 1599 | struct resource *res; |
1656 | resource_size_t offset; | 1600 | resource_size_t offset; |
1657 | char bus_addr[64]; | 1601 | char bus_addr[64]; |
1658 | char *fmt; | 1602 | char *fmt; |
1659 | 1603 | ||
1660 | bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); | ||
1661 | if (!bridge) | ||
1662 | return NULL; | ||
1663 | 1604 | ||
1664 | b = pci_alloc_bus(); | 1605 | b = pci_alloc_bus(); |
1665 | if (!b) | 1606 | if (!b) |
1666 | goto err_bus; | 1607 | return NULL; |
1667 | |||
1668 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
1669 | if (!dev) | ||
1670 | goto err_dev; | ||
1671 | 1608 | ||
1672 | b->sysdata = sysdata; | 1609 | b->sysdata = sysdata; |
1673 | b->ops = ops; | 1610 | b->ops = ops; |
1674 | |||
1675 | b2 = pci_find_bus(pci_domain_nr(b), bus); | 1611 | b2 = pci_find_bus(pci_domain_nr(b), bus); |
1676 | if (b2) { | 1612 | if (b2) { |
1677 | /* If we already got to this bus through a different bridge, ignore it */ | 1613 | /* If we already got to this bus through a different bridge, ignore it */ |
@@ -1679,13 +1615,17 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, | |||
1679 | goto err_out; | 1615 | goto err_out; |
1680 | } | 1616 | } |
1681 | 1617 | ||
1682 | dev->parent = parent; | 1618 | bridge = pci_alloc_host_bridge(b); |
1683 | dev->release = pci_release_bus_bridge_dev; | 1619 | if (!bridge) |
1684 | dev_set_name(dev, "pci%04x:%02x", pci_domain_nr(b), bus); | 1620 | goto err_out; |
1685 | error = device_register(dev); | 1621 | |
1622 | bridge->dev.parent = parent; | ||
1623 | bridge->dev.release = pci_release_bus_bridge_dev; | ||
1624 | dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus); | ||
1625 | error = device_register(&bridge->dev); | ||
1686 | if (error) | 1626 | if (error) |
1687 | goto dev_reg_err; | 1627 | goto bridge_dev_reg_err; |
1688 | b->bridge = get_device(dev); | 1628 | b->bridge = get_device(&bridge->dev); |
1689 | device_enable_async_suspend(b->bridge); | 1629 | device_enable_async_suspend(b->bridge); |
1690 | pci_set_bus_of_node(b); | 1630 | pci_set_bus_of_node(b); |
1691 | 1631 | ||
@@ -1704,9 +1644,6 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, | |||
1704 | 1644 | ||
1705 | b->number = b->secondary = bus; | 1645 | b->number = b->secondary = bus; |
1706 | 1646 | ||
1707 | bridge->bus = b; | ||
1708 | INIT_LIST_HEAD(&bridge->windows); | ||
1709 | |||
1710 | if (parent) | 1647 | if (parent) |
1711 | dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev)); | 1648 | dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev)); |
1712 | else | 1649 | else |
@@ -1732,25 +1669,18 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, | |||
1732 | } | 1669 | } |
1733 | 1670 | ||
1734 | down_write(&pci_bus_sem); | 1671 | down_write(&pci_bus_sem); |
1735 | list_add_tail(&bridge->list, &pci_host_bridges); | ||
1736 | list_add_tail(&b->node, &pci_root_buses); | 1672 | list_add_tail(&b->node, &pci_root_buses); |
1737 | up_write(&pci_bus_sem); | 1673 | up_write(&pci_bus_sem); |
1738 | 1674 | ||
1739 | return b; | 1675 | return b; |
1740 | 1676 | ||
1741 | class_dev_reg_err: | 1677 | class_dev_reg_err: |
1742 | device_unregister(dev); | 1678 | put_device(&bridge->dev); |
1743 | dev_reg_err: | 1679 | device_unregister(&bridge->dev); |
1744 | down_write(&pci_bus_sem); | 1680 | bridge_dev_reg_err: |
1745 | list_del(&bridge->list); | 1681 | kfree(bridge); |
1746 | list_del(&b->node); | ||
1747 | up_write(&pci_bus_sem); | ||
1748 | err_out: | 1682 | err_out: |
1749 | kfree(dev); | ||
1750 | err_dev: | ||
1751 | kfree(b); | 1683 | kfree(b); |
1752 | err_bus: | ||
1753 | kfree(bridge); | ||
1754 | return NULL; | 1684 | return NULL; |
1755 | } | 1685 | } |
1756 | 1686 | ||
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 953ec3f08470..2a7521677541 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -3097,16 +3097,74 @@ static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe) | |||
3097 | return 0; | 3097 | return 0; |
3098 | } | 3098 | } |
3099 | 3099 | ||
3100 | #include "../gpu/drm/i915/i915_reg.h" | ||
3101 | #define MSG_CTL 0x45010 | ||
3102 | #define NSDE_PWR_STATE 0xd0100 | ||
3103 | #define IGD_OPERATION_TIMEOUT 10000 /* set timeout 10 seconds */ | ||
3104 | |||
3105 | static int reset_ivb_igd(struct pci_dev *dev, int probe) | ||
3106 | { | ||
3107 | void __iomem *mmio_base; | ||
3108 | unsigned long timeout; | ||
3109 | u32 val; | ||
3110 | |||
3111 | if (probe) | ||
3112 | return 0; | ||
3113 | |||
3114 | mmio_base = pci_iomap(dev, 0, 0); | ||
3115 | if (!mmio_base) | ||
3116 | return -ENOMEM; | ||
3117 | |||
3118 | iowrite32(0x00000002, mmio_base + MSG_CTL); | ||
3119 | |||
3120 | /* | ||
3121 | * Clobbering SOUTH_CHICKEN2 register is fine only if the next | ||
3122 | * driver loaded sets the right bits. However, this's a reset and | ||
3123 | * the bits have been set by i915 previously, so we clobber | ||
3124 | * SOUTH_CHICKEN2 register directly here. | ||
3125 | */ | ||
3126 | iowrite32(0x00000005, mmio_base + SOUTH_CHICKEN2); | ||
3127 | |||
3128 | val = ioread32(mmio_base + PCH_PP_CONTROL) & 0xfffffffe; | ||
3129 | iowrite32(val, mmio_base + PCH_PP_CONTROL); | ||
3130 | |||
3131 | timeout = jiffies + msecs_to_jiffies(IGD_OPERATION_TIMEOUT); | ||
3132 | do { | ||
3133 | val = ioread32(mmio_base + PCH_PP_STATUS); | ||
3134 | if ((val & 0xb0000000) == 0) | ||
3135 | goto reset_complete; | ||
3136 | msleep(10); | ||
3137 | } while (time_before(jiffies, timeout)); | ||
3138 | dev_warn(&dev->dev, "timeout during reset\n"); | ||
3139 | |||
3140 | reset_complete: | ||
3141 | iowrite32(0x00000002, mmio_base + NSDE_PWR_STATE); | ||
3142 | |||
3143 | pci_iounmap(dev, mmio_base); | ||
3144 | return 0; | ||
3145 | } | ||
3146 | |||
3100 | #define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed | 3147 | #define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed |
3148 | #define PCI_DEVICE_ID_INTEL_IVB_M_VGA 0x0156 | ||
3149 | #define PCI_DEVICE_ID_INTEL_IVB_M2_VGA 0x0166 | ||
3101 | 3150 | ||
3102 | static const struct pci_dev_reset_methods pci_dev_reset_methods[] = { | 3151 | static const struct pci_dev_reset_methods pci_dev_reset_methods[] = { |
3103 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF, | 3152 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF, |
3104 | reset_intel_82599_sfp_virtfn }, | 3153 | reset_intel_82599_sfp_virtfn }, |
3154 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_M_VGA, | ||
3155 | reset_ivb_igd }, | ||
3156 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_M2_VGA, | ||
3157 | reset_ivb_igd }, | ||
3105 | { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, | 3158 | { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, |
3106 | reset_intel_generic_dev }, | 3159 | reset_intel_generic_dev }, |
3107 | { 0 } | 3160 | { 0 } |
3108 | }; | 3161 | }; |
3109 | 3162 | ||
3163 | /* | ||
3164 | * These device-specific reset methods are here rather than in a driver | ||
3165 | * because when a host assigns a device to a guest VM, the host may need | ||
3166 | * to reset the device but probably doesn't have a driver for it. | ||
3167 | */ | ||
3110 | int pci_dev_specific_reset(struct pci_dev *dev, int probe) | 3168 | int pci_dev_specific_reset(struct pci_dev *dev, int probe) |
3111 | { | 3169 | { |
3112 | const struct pci_dev_reset_methods *i; | 3170 | const struct pci_dev_reset_methods *i; |