diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2013-01-26 19:27:36 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2013-01-26 19:27:36 -0500 |
commit | 14b5cb37cc6172a54ce920c61784f44422ae306d (patch) | |
tree | 53e500c8aec98e645079e025c2525ce399052e1d /drivers/pci | |
parent | 708b59bfe1d1727451ca41f5dc4c17cf99dfaf51 (diff) | |
parent | fcbed0bcb216b9f134e8614f46e00649a179e042 (diff) |
Merge branch 'pci/yijing-ari' into next
* pci/yijing-ari:
PCI: shpchp: Iterate over all devices in slot, not functions 0-7
PCI: sgihp: Iterate over all devices in slot, not functions 0-7
PCI: cpcihp: Iterate over all devices in slot, not functions 0-7
PCI: pciehp: Iterate over all devices in slot, not functions 0-7
PCI: Consolidate "next-function" functions
PCI: Rename pci_enable_ari() to pci_configure_ari()
PCI: Enable ARI if dev and upstream bridge support it; disable otherwise
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/hotplug/cpci_hotplug_pci.c | 29 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_pci.c | 44 | ||||
-rw-r--r-- | drivers/pci/hotplug/sgi_hotplug.c | 63 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_pci.c | 36 | ||||
-rw-r--r-- | drivers/pci/pci.c | 21 | ||||
-rw-r--r-- | drivers/pci/pci.h | 2 | ||||
-rw-r--r-- | drivers/pci/probe.c | 50 |
7 files changed, 109 insertions, 136 deletions
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index dcc75c785443..d8add34177f2 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c | |||
@@ -252,8 +252,8 @@ int cpci_led_off(struct slot* slot) | |||
252 | 252 | ||
253 | int __ref cpci_configure_slot(struct slot *slot) | 253 | int __ref cpci_configure_slot(struct slot *slot) |
254 | { | 254 | { |
255 | struct pci_dev *dev; | ||
255 | struct pci_bus *parent; | 256 | struct pci_bus *parent; |
256 | int fn; | ||
257 | 257 | ||
258 | dbg("%s - enter", __func__); | 258 | dbg("%s - enter", __func__); |
259 | 259 | ||
@@ -282,18 +282,13 @@ int __ref cpci_configure_slot(struct slot *slot) | |||
282 | } | 282 | } |
283 | parent = slot->dev->bus; | 283 | parent = slot->dev->bus; |
284 | 284 | ||
285 | for (fn = 0; fn < 8; fn++) { | 285 | list_for_each_entry(dev, &parent->devices, bus_list) |
286 | struct pci_dev *dev; | 286 | if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn)) |
287 | |||
288 | dev = pci_get_slot(parent, | ||
289 | PCI_DEVFN(PCI_SLOT(slot->devfn), fn)); | ||
290 | if (!dev) | ||
291 | continue; | 287 | continue; |
292 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || | 288 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || |
293 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) | 289 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) |
294 | pci_hp_add_bridge(dev); | 290 | pci_hp_add_bridge(dev); |
295 | pci_dev_put(dev); | 291 | |
296 | } | ||
297 | 292 | ||
298 | pci_assign_unassigned_bridge_resources(parent->self); | 293 | pci_assign_unassigned_bridge_resources(parent->self); |
299 | 294 | ||
@@ -305,8 +300,7 @@ int __ref cpci_configure_slot(struct slot *slot) | |||
305 | 300 | ||
306 | int cpci_unconfigure_slot(struct slot* slot) | 301 | int cpci_unconfigure_slot(struct slot* slot) |
307 | { | 302 | { |
308 | int i; | 303 | struct pci_dev *dev, *temp; |
309 | struct pci_dev *dev; | ||
310 | 304 | ||
311 | dbg("%s - enter", __func__); | 305 | dbg("%s - enter", __func__); |
312 | if (!slot->dev) { | 306 | if (!slot->dev) { |
@@ -314,13 +308,12 @@ int cpci_unconfigure_slot(struct slot* slot) | |||
314 | return -ENODEV; | 308 | return -ENODEV; |
315 | } | 309 | } |
316 | 310 | ||
317 | for (i = 0; i < 8; i++) { | 311 | list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) { |
318 | dev = pci_get_slot(slot->bus, | 312 | if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn)) |
319 | PCI_DEVFN(PCI_SLOT(slot->devfn), i)); | 313 | continue; |
320 | if (dev) { | 314 | pci_dev_get(dev); |
321 | pci_stop_and_remove_bus_device(dev); | 315 | pci_stop_and_remove_bus_device(dev); |
322 | pci_dev_put(dev); | 316 | pci_dev_put(dev); |
323 | } | ||
324 | } | 317 | } |
325 | pci_dev_put(slot->dev); | 318 | pci_dev_put(slot->dev); |
326 | slot->dev = NULL; | 319 | slot->dev = NULL; |
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 09cecaf450c5..aac7a40e4a4a 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c | |||
@@ -39,7 +39,7 @@ int pciehp_configure_device(struct slot *p_slot) | |||
39 | struct pci_dev *dev; | 39 | struct pci_dev *dev; |
40 | struct pci_dev *bridge = p_slot->ctrl->pcie->port; | 40 | struct pci_dev *bridge = p_slot->ctrl->pcie->port; |
41 | struct pci_bus *parent = bridge->subordinate; | 41 | struct pci_bus *parent = bridge->subordinate; |
42 | int num, fn; | 42 | int num; |
43 | struct controller *ctrl = p_slot->ctrl; | 43 | struct controller *ctrl = p_slot->ctrl; |
44 | 44 | ||
45 | dev = pci_get_slot(parent, PCI_DEVFN(0, 0)); | 45 | dev = pci_get_slot(parent, PCI_DEVFN(0, 0)); |
@@ -57,28 +57,18 @@ int pciehp_configure_device(struct slot *p_slot) | |||
57 | return -ENODEV; | 57 | return -ENODEV; |
58 | } | 58 | } |
59 | 59 | ||
60 | for (fn = 0; fn < 8; fn++) { | 60 | list_for_each_entry(dev, &parent->devices, bus_list) |
61 | dev = pci_get_slot(parent, PCI_DEVFN(0, fn)); | ||
62 | if (!dev) | ||
63 | continue; | ||
64 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || | 61 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || |
65 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) | 62 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) |
66 | pci_hp_add_bridge(dev); | 63 | pci_hp_add_bridge(dev); |
67 | pci_dev_put(dev); | ||
68 | } | ||
69 | 64 | ||
70 | pci_assign_unassigned_bridge_resources(bridge); | 65 | pci_assign_unassigned_bridge_resources(bridge); |
71 | 66 | ||
72 | for (fn = 0; fn < 8; fn++) { | 67 | list_for_each_entry(dev, &parent->devices, bus_list) { |
73 | dev = pci_get_slot(parent, PCI_DEVFN(0, fn)); | 68 | if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) |
74 | if (!dev) | ||
75 | continue; | 69 | continue; |
76 | if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | 70 | |
77 | pci_dev_put(dev); | ||
78 | continue; | ||
79 | } | ||
80 | pci_configure_slot(dev); | 71 | pci_configure_slot(dev); |
81 | pci_dev_put(dev); | ||
82 | } | 72 | } |
83 | 73 | ||
84 | pci_bus_add_devices(parent); | 74 | pci_bus_add_devices(parent); |
@@ -89,9 +79,9 @@ int pciehp_configure_device(struct slot *p_slot) | |||
89 | int pciehp_unconfigure_device(struct slot *p_slot) | 79 | int pciehp_unconfigure_device(struct slot *p_slot) |
90 | { | 80 | { |
91 | int ret, rc = 0; | 81 | int ret, rc = 0; |
92 | int j; | ||
93 | u8 bctl = 0; | 82 | u8 bctl = 0; |
94 | u8 presence = 0; | 83 | u8 presence = 0; |
84 | struct pci_dev *dev, *temp; | ||
95 | struct pci_bus *parent = p_slot->ctrl->pcie->port->subordinate; | 85 | struct pci_bus *parent = p_slot->ctrl->pcie->port->subordinate; |
96 | u16 command; | 86 | u16 command; |
97 | struct controller *ctrl = p_slot->ctrl; | 87 | struct controller *ctrl = p_slot->ctrl; |
@@ -102,33 +92,31 @@ int pciehp_unconfigure_device(struct slot *p_slot) | |||
102 | if (ret) | 92 | if (ret) |
103 | presence = 0; | 93 | presence = 0; |
104 | 94 | ||
105 | for (j = 0; j < 8; j++) { | 95 | list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) { |
106 | struct pci_dev *temp = pci_get_slot(parent, PCI_DEVFN(0, j)); | 96 | pci_dev_get(dev); |
107 | if (!temp) | 97 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) { |
108 | continue; | 98 | pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl); |
109 | if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) { | ||
110 | pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); | ||
111 | if (bctl & PCI_BRIDGE_CTL_VGA) { | 99 | if (bctl & PCI_BRIDGE_CTL_VGA) { |
112 | ctrl_err(ctrl, | 100 | ctrl_err(ctrl, |
113 | "Cannot remove display device %s\n", | 101 | "Cannot remove display device %s\n", |
114 | pci_name(temp)); | 102 | pci_name(dev)); |
115 | pci_dev_put(temp); | 103 | pci_dev_put(dev); |
116 | rc = -EINVAL; | 104 | rc = -EINVAL; |
117 | break; | 105 | break; |
118 | } | 106 | } |
119 | } | 107 | } |
120 | pci_stop_and_remove_bus_device(temp); | 108 | pci_stop_and_remove_bus_device(dev); |
121 | /* | 109 | /* |
122 | * Ensure that no new Requests will be generated from | 110 | * Ensure that no new Requests will be generated from |
123 | * the device. | 111 | * the device. |
124 | */ | 112 | */ |
125 | if (presence) { | 113 | if (presence) { |
126 | pci_read_config_word(temp, PCI_COMMAND, &command); | 114 | pci_read_config_word(dev, PCI_COMMAND, &command); |
127 | command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR); | 115 | command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR); |
128 | command |= PCI_COMMAND_INTX_DISABLE; | 116 | command |= PCI_COMMAND_INTX_DISABLE; |
129 | pci_write_config_word(temp, PCI_COMMAND, command); | 117 | pci_write_config_word(dev, PCI_COMMAND, command); |
130 | } | 118 | } |
131 | pci_dev_put(temp); | 119 | pci_dev_put(dev); |
132 | } | 120 | } |
133 | 121 | ||
134 | return rc; | 122 | return rc; |
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index f3c419256d2a..24dace645871 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c | |||
@@ -334,7 +334,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
334 | struct slot *slot = bss_hotplug_slot->private; | 334 | struct slot *slot = bss_hotplug_slot->private; |
335 | struct pci_bus *new_bus = NULL; | 335 | struct pci_bus *new_bus = NULL; |
336 | struct pci_dev *dev; | 336 | struct pci_dev *dev; |
337 | int func, num_funcs; | 337 | int num_funcs; |
338 | int new_ppb = 0; | 338 | int new_ppb = 0; |
339 | int rc; | 339 | int rc; |
340 | char *ssdt = NULL; | 340 | char *ssdt = NULL; |
@@ -381,29 +381,26 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
381 | * to the Linux PCI interface and tell the drivers | 381 | * to the Linux PCI interface and tell the drivers |
382 | * about them. | 382 | * about them. |
383 | */ | 383 | */ |
384 | for (func = 0; func < num_funcs; func++) { | 384 | list_for_each_entry(dev, &slot->pci_bus->devices, bus_list) { |
385 | dev = pci_get_slot(slot->pci_bus, | 385 | if (PCI_SLOT(dev->devfn) != slot->device_num + 1) |
386 | PCI_DEVFN(slot->device_num + 1, | 386 | continue; |
387 | PCI_FUNC(func))); | 387 | |
388 | if (dev) { | 388 | /* Need to do slot fixup on PPB before fixup of children |
389 | /* Need to do slot fixup on PPB before fixup of children | 389 | * (PPB's pcidev_info needs to be in pcidev_info list |
390 | * (PPB's pcidev_info needs to be in pcidev_info list | 390 | * before child's SN_PCIDEV_INFO() call to setup |
391 | * before child's SN_PCIDEV_INFO() call to setup | 391 | * pdi_host_pcidev_info). |
392 | * pdi_host_pcidev_info). | 392 | */ |
393 | */ | 393 | pcibios_fixup_device_resources(dev); |
394 | pcibios_fixup_device_resources(dev); | 394 | if (SN_ACPI_BASE_SUPPORT()) |
395 | if (SN_ACPI_BASE_SUPPORT()) | 395 | sn_acpi_slot_fixup(dev); |
396 | sn_acpi_slot_fixup(dev); | 396 | else |
397 | else | 397 | sn_io_slot_fixup(dev); |
398 | sn_io_slot_fixup(dev); | 398 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { |
399 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | 399 | pci_hp_add_bridge(dev); |
400 | pci_hp_add_bridge(dev); | 400 | if (dev->subordinate) { |
401 | if (dev->subordinate) { | 401 | new_bus = dev->subordinate; |
402 | new_bus = dev->subordinate; | 402 | new_ppb = 1; |
403 | new_ppb = 1; | ||
404 | } | ||
405 | } | 403 | } |
406 | pci_dev_put(dev); | ||
407 | } | 404 | } |
408 | } | 405 | } |
409 | 406 | ||
@@ -481,8 +478,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
481 | static int disable_slot(struct hotplug_slot *bss_hotplug_slot) | 478 | static int disable_slot(struct hotplug_slot *bss_hotplug_slot) |
482 | { | 479 | { |
483 | struct slot *slot = bss_hotplug_slot->private; | 480 | struct slot *slot = bss_hotplug_slot->private; |
484 | struct pci_dev *dev; | 481 | struct pci_dev *dev, *temp; |
485 | int func; | ||
486 | int rc; | 482 | int rc; |
487 | acpi_owner_id ssdt_id = 0; | 483 | acpi_owner_id ssdt_id = 0; |
488 | 484 | ||
@@ -542,15 +538,14 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
542 | } | 538 | } |
543 | 539 | ||
544 | /* Free the SN resources assigned to the Linux device.*/ | 540 | /* Free the SN resources assigned to the Linux device.*/ |
545 | for (func = 0; func < 8; func++) { | 541 | list_for_each_entry_safe(dev, temp, &slot->pci_bus->devices, bus_list) { |
546 | dev = pci_get_slot(slot->pci_bus, | 542 | if (PCI_SLOT(dev->devfn) != slot->device_num + 1) |
547 | PCI_DEVFN(slot->device_num + 1, | 543 | continue; |
548 | PCI_FUNC(func))); | 544 | |
549 | if (dev) { | 545 | pci_dev_get(dev); |
550 | sn_bus_free_data(dev); | 546 | sn_bus_free_data(dev); |
551 | pci_stop_and_remove_bus_device(dev); | 547 | pci_stop_and_remove_bus_device(dev); |
552 | pci_dev_put(dev); | 548 | pci_dev_put(dev); |
553 | } | ||
554 | } | 549 | } |
555 | 550 | ||
556 | /* Remove the SSDT for the slot from the ACPI namespace */ | 551 | /* Remove the SSDT for the slot from the ACPI namespace */ |
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index c627ed9957d1..b0e83132542e 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c | |||
@@ -40,7 +40,7 @@ int __ref shpchp_configure_device(struct slot *p_slot) | |||
40 | struct controller *ctrl = p_slot->ctrl; | 40 | struct controller *ctrl = p_slot->ctrl; |
41 | struct pci_dev *bridge = ctrl->pci_dev; | 41 | struct pci_dev *bridge = ctrl->pci_dev; |
42 | struct pci_bus *parent = bridge->subordinate; | 42 | struct pci_bus *parent = bridge->subordinate; |
43 | int num, fn; | 43 | int num; |
44 | 44 | ||
45 | dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); | 45 | dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); |
46 | if (dev) { | 46 | if (dev) { |
@@ -57,24 +57,20 @@ int __ref shpchp_configure_device(struct slot *p_slot) | |||
57 | return -ENODEV; | 57 | return -ENODEV; |
58 | } | 58 | } |
59 | 59 | ||
60 | for (fn = 0; fn < 8; fn++) { | 60 | list_for_each_entry(dev, &parent->devices, bus_list) { |
61 | dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn)); | 61 | if (PCI_SLOT(dev->devfn) != p_slot->device) |
62 | if (!dev) | ||
63 | continue; | 62 | continue; |
64 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || | 63 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || |
65 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) | 64 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) |
66 | pci_hp_add_bridge(dev); | 65 | pci_hp_add_bridge(dev); |
67 | pci_dev_put(dev); | ||
68 | } | 66 | } |
69 | 67 | ||
70 | pci_assign_unassigned_bridge_resources(bridge); | 68 | pci_assign_unassigned_bridge_resources(bridge); |
71 | 69 | ||
72 | for (fn = 0; fn < 8; fn++) { | 70 | list_for_each_entry(dev, &parent->devices, bus_list) { |
73 | dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn)); | 71 | if (PCI_SLOT(dev->devfn) != p_slot->device) |
74 | if (!dev) | ||
75 | continue; | 72 | continue; |
76 | pci_configure_slot(dev); | 73 | pci_configure_slot(dev); |
77 | pci_dev_put(dev); | ||
78 | } | 74 | } |
79 | 75 | ||
80 | pci_bus_add_devices(parent); | 76 | pci_bus_add_devices(parent); |
@@ -85,32 +81,32 @@ int __ref shpchp_configure_device(struct slot *p_slot) | |||
85 | int shpchp_unconfigure_device(struct slot *p_slot) | 81 | int shpchp_unconfigure_device(struct slot *p_slot) |
86 | { | 82 | { |
87 | int rc = 0; | 83 | int rc = 0; |
88 | int j; | ||
89 | u8 bctl = 0; | 84 | u8 bctl = 0; |
90 | struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; | 85 | struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; |
86 | struct pci_dev *dev, *temp; | ||
91 | struct controller *ctrl = p_slot->ctrl; | 87 | struct controller *ctrl = p_slot->ctrl; |
92 | 88 | ||
93 | ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n", | 89 | ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n", |
94 | __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); | 90 | __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); |
95 | 91 | ||
96 | for (j = 0; j < 8 ; j++) { | 92 | list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) { |
97 | struct pci_dev *temp = pci_get_slot(parent, | 93 | if (PCI_SLOT(dev->devfn) != p_slot->device) |
98 | (p_slot->device << 3) | j); | ||
99 | if (!temp) | ||
100 | continue; | 94 | continue; |
101 | if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | 95 | |
102 | pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); | 96 | pci_dev_get(dev); |
97 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | ||
98 | pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl); | ||
103 | if (bctl & PCI_BRIDGE_CTL_VGA) { | 99 | if (bctl & PCI_BRIDGE_CTL_VGA) { |
104 | ctrl_err(ctrl, | 100 | ctrl_err(ctrl, |
105 | "Cannot remove display device %s\n", | 101 | "Cannot remove display device %s\n", |
106 | pci_name(temp)); | 102 | pci_name(dev)); |
107 | pci_dev_put(temp); | 103 | pci_dev_put(dev); |
108 | rc = -EINVAL; | 104 | rc = -EINVAL; |
109 | break; | 105 | break; |
110 | } | 106 | } |
111 | } | 107 | } |
112 | pci_stop_and_remove_bus_device(temp); | 108 | pci_stop_and_remove_bus_device(dev); |
113 | pci_dev_put(temp); | 109 | pci_dev_put(dev); |
114 | } | 110 | } |
115 | return rc; | 111 | return rc; |
116 | } | 112 | } |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 89dc8ac096ba..177a50ff6454 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -2042,10 +2042,13 @@ void pci_free_cap_save_buffers(struct pci_dev *dev) | |||
2042 | } | 2042 | } |
2043 | 2043 | ||
2044 | /** | 2044 | /** |
2045 | * pci_enable_ari - enable ARI forwarding if hardware support it | 2045 | * pci_configure_ari - enable or disable ARI forwarding |
2046 | * @dev: the PCI device | 2046 | * @dev: the PCI device |
2047 | * | ||
2048 | * If @dev and its upstream bridge both support ARI, enable ARI in the | ||
2049 | * bridge. Otherwise, disable ARI in the bridge. | ||
2047 | */ | 2050 | */ |
2048 | void pci_enable_ari(struct pci_dev *dev) | 2051 | void pci_configure_ari(struct pci_dev *dev) |
2049 | { | 2052 | { |
2050 | u32 cap; | 2053 | u32 cap; |
2051 | struct pci_dev *bridge; | 2054 | struct pci_dev *bridge; |
@@ -2053,9 +2056,6 @@ void pci_enable_ari(struct pci_dev *dev) | |||
2053 | if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn) | 2056 | if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn) |
2054 | return; | 2057 | return; |
2055 | 2058 | ||
2056 | if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI)) | ||
2057 | return; | ||
2058 | |||
2059 | bridge = dev->bus->self; | 2059 | bridge = dev->bus->self; |
2060 | if (!bridge) | 2060 | if (!bridge) |
2061 | return; | 2061 | return; |
@@ -2064,8 +2064,15 @@ void pci_enable_ari(struct pci_dev *dev) | |||
2064 | if (!(cap & PCI_EXP_DEVCAP2_ARI)) | 2064 | if (!(cap & PCI_EXP_DEVCAP2_ARI)) |
2065 | return; | 2065 | return; |
2066 | 2066 | ||
2067 | pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_ARI); | 2067 | if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI)) { |
2068 | bridge->ari_enabled = 1; | 2068 | pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2, |
2069 | PCI_EXP_DEVCTL2_ARI); | ||
2070 | bridge->ari_enabled = 1; | ||
2071 | } else { | ||
2072 | pcie_capability_clear_word(bridge, PCI_EXP_DEVCTL2, | ||
2073 | PCI_EXP_DEVCTL2_ARI); | ||
2074 | bridge->ari_enabled = 0; | ||
2075 | } | ||
2069 | } | 2076 | } |
2070 | 2077 | ||
2071 | /** | 2078 | /** |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index adfd172c5b9b..81b6a8752517 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -204,7 +204,7 @@ extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | |||
204 | extern int pci_resource_bar(struct pci_dev *dev, int resno, | 204 | extern int pci_resource_bar(struct pci_dev *dev, int resno, |
205 | enum pci_bar_type *type); | 205 | enum pci_bar_type *type); |
206 | extern int pci_bus_add_child(struct pci_bus *bus); | 206 | extern int pci_bus_add_child(struct pci_bus *bus); |
207 | extern void pci_enable_ari(struct pci_dev *dev); | 207 | extern void pci_configure_ari(struct pci_dev *dev); |
208 | /** | 208 | /** |
209 | * pci_ari_enabled - query ARI forwarding status | 209 | * pci_ari_enabled - query ARI forwarding status |
210 | * @bus: the PCI bus | 210 | * @bus: the PCI bus |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index bbe4be7fc685..b4a6ede8f17a 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -1285,7 +1285,7 @@ static void pci_init_capabilities(struct pci_dev *dev) | |||
1285 | pci_vpd_pci22_init(dev); | 1285 | pci_vpd_pci22_init(dev); |
1286 | 1286 | ||
1287 | /* Alternative Routing-ID Forwarding */ | 1287 | /* Alternative Routing-ID Forwarding */ |
1288 | pci_enable_ari(dev); | 1288 | pci_configure_ari(dev); |
1289 | 1289 | ||
1290 | /* Single Root I/O Virtualization */ | 1290 | /* Single Root I/O Virtualization */ |
1291 | pci_iov_init(dev); | 1291 | pci_iov_init(dev); |
@@ -1348,31 +1348,31 @@ struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn) | |||
1348 | } | 1348 | } |
1349 | EXPORT_SYMBOL(pci_scan_single_device); | 1349 | EXPORT_SYMBOL(pci_scan_single_device); |
1350 | 1350 | ||
1351 | static unsigned next_ari_fn(struct pci_dev *dev, unsigned fn) | 1351 | static unsigned next_fn(struct pci_bus *bus, struct pci_dev *dev, unsigned fn) |
1352 | { | 1352 | { |
1353 | u16 cap; | 1353 | int pos; |
1354 | unsigned pos, next_fn; | 1354 | u16 cap = 0; |
1355 | unsigned next_fn; | ||
1355 | 1356 | ||
1356 | if (!dev) | 1357 | if (pci_ari_enabled(bus)) { |
1357 | return 0; | 1358 | if (!dev) |
1359 | return 0; | ||
1360 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); | ||
1361 | if (!pos) | ||
1362 | return 0; | ||
1358 | 1363 | ||
1359 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); | 1364 | pci_read_config_word(dev, pos + PCI_ARI_CAP, &cap); |
1360 | if (!pos) | 1365 | next_fn = PCI_ARI_CAP_NFN(cap); |
1361 | return 0; | 1366 | if (next_fn <= fn) |
1362 | pci_read_config_word(dev, pos + 4, &cap); | 1367 | return 0; /* protect against malformed list */ |
1363 | next_fn = cap >> 8; | ||
1364 | if (next_fn <= fn) | ||
1365 | return 0; | ||
1366 | return next_fn; | ||
1367 | } | ||
1368 | 1368 | ||
1369 | static unsigned next_trad_fn(struct pci_dev *dev, unsigned fn) | 1369 | return next_fn; |
1370 | { | 1370 | } |
1371 | return (fn + 1) % 8; | 1371 | |
1372 | } | 1372 | /* dev may be NULL for non-contiguous multifunction devices */ |
1373 | if (!dev || dev->multifunction) | ||
1374 | return (fn + 1) % 8; | ||
1373 | 1375 | ||
1374 | static unsigned no_next_fn(struct pci_dev *dev, unsigned fn) | ||
1375 | { | ||
1376 | return 0; | 1376 | return 0; |
1377 | } | 1377 | } |
1378 | 1378 | ||
@@ -1405,7 +1405,6 @@ int pci_scan_slot(struct pci_bus *bus, int devfn) | |||
1405 | { | 1405 | { |
1406 | unsigned fn, nr = 0; | 1406 | unsigned fn, nr = 0; |
1407 | struct pci_dev *dev; | 1407 | struct pci_dev *dev; |
1408 | unsigned (*next_fn)(struct pci_dev *, unsigned) = no_next_fn; | ||
1409 | 1408 | ||
1410 | if (only_one_child(bus) && (devfn > 0)) | 1409 | if (only_one_child(bus) && (devfn > 0)) |
1411 | return 0; /* Already scanned the entire slot */ | 1410 | return 0; /* Already scanned the entire slot */ |
@@ -1416,12 +1415,7 @@ int pci_scan_slot(struct pci_bus *bus, int devfn) | |||
1416 | if (!dev->is_added) | 1415 | if (!dev->is_added) |
1417 | nr++; | 1416 | nr++; |
1418 | 1417 | ||
1419 | if (pci_ari_enabled(bus)) | 1418 | for (fn = next_fn(bus, dev, 0); fn > 0; fn = next_fn(bus, dev, fn)) { |
1420 | next_fn = next_ari_fn; | ||
1421 | else if (dev->multifunction) | ||
1422 | next_fn = next_trad_fn; | ||
1423 | |||
1424 | for (fn = next_fn(dev, 0); fn > 0; fn = next_fn(dev, fn)) { | ||
1425 | dev = pci_scan_single_device(bus, devfn + fn); | 1419 | dev = pci_scan_single_device(bus, devfn + fn); |
1426 | if (dev) { | 1420 | if (dev) { |
1427 | if (!dev->is_added) | 1421 | if (!dev->is_added) |