aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c85
-rw-r--r--drivers/pci/hotplug/pciehp.h10
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c69
-rw-r--r--drivers/pci/hotplug/shpchp.h14
-rw-r--r--drivers/pci/hotplug/shpchp_core.c15
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c1
-rw-r--r--include/linux/pci_hotplug.h2
7 files changed, 105 insertions, 91 deletions
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index f8c187a763bd..93e37f0666ab 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -30,6 +30,7 @@
30#include <linux/types.h> 30#include <linux/types.h>
31#include <linux/pci.h> 31#include <linux/pci.h>
32#include <linux/pci_hotplug.h> 32#include <linux/pci_hotplug.h>
33#include <linux/pci-acpi.h>
33#include <acpi/acpi.h> 34#include <acpi/acpi.h>
34#include <acpi/acpi_bus.h> 35#include <acpi/acpi_bus.h>
35#include <acpi/actypes.h> 36#include <acpi/actypes.h>
@@ -299,7 +300,7 @@ free_and_return:
299 * 300 *
300 * @handle - the handle of the hotplug controller. 301 * @handle - the handle of the hotplug controller.
301 */ 302 */
302acpi_status acpi_run_oshp(acpi_handle handle) 303static acpi_status acpi_run_oshp(acpi_handle handle)
303{ 304{
304 acpi_status status; 305 acpi_status status;
305 struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; 306 struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -322,9 +323,6 @@ acpi_status acpi_run_oshp(acpi_handle handle)
322 kfree(string.pointer); 323 kfree(string.pointer);
323 return status; 324 return status;
324} 325}
325EXPORT_SYMBOL_GPL(acpi_run_oshp);
326
327
328 326
329/* acpi_get_hp_params_from_firmware 327/* acpi_get_hp_params_from_firmware
330 * 328 *
@@ -374,6 +372,85 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus,
374} 372}
375EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); 373EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
376 374
375/**
376 * acpi_get_hp_hw_control_from_firmware
377 * @dev: the pci_dev of the bridge that has a hotplug controller
378 * @flags: requested control bits for _OSC
379 *
380 * Attempt to take hotplug control from firmware.
381 */
382int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags)
383{
384 acpi_status status;
385 acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
386 struct pci_dev *pdev = dev;
387 struct pci_bus *parent;
388 struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
389
390 flags &= (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL |
391 OSC_SHPC_NATIVE_HP_CONTROL |
392 OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
393 if (!flags) {
394 err("Invalid flags %u specified!\n", flags);
395 return -EINVAL;
396 }
397
398 /*
399 * Per PCI firmware specification, we should run the ACPI _OSC
400 * method to get control of hotplug hardware before using it. If
401 * an _OSC is missing, we look for an OSHP to do the same thing.
402 * To handle different BIOS behavior, we look for _OSC and OSHP
403 * within the scope of the hotplug controller and its parents,
404 * upto the host bridge under which this controller exists.
405 */
406 while (!handle) {
407 /*
408 * This hotplug controller was not listed in the ACPI name
409 * space at all. Try to get acpi handle of parent pci bus.
410 */
411 if (!pdev || !pdev->bus->parent)
412 break;
413 parent = pdev->bus->parent;
414 dbg("Could not find %s in acpi namespace, trying parent\n",
415 pci_name(pdev));
416 if (!parent->self)
417 /* Parent must be a host bridge */
418 handle = acpi_get_pci_rootbridge_handle(
419 pci_domain_nr(parent),
420 parent->number);
421 else
422 handle = DEVICE_ACPI_HANDLE(&(parent->self->dev));
423 pdev = parent->self;
424 }
425
426 while (handle) {
427 acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
428 dbg("Trying to get hotplug control for %s \n",
429 (char *)string.pointer);
430 status = pci_osc_control_set(handle, flags);
431 if (status == AE_NOT_FOUND)
432 status = acpi_run_oshp(handle);
433 if (ACPI_SUCCESS(status)) {
434 dbg("Gained control for hotplug HW for pci %s (%s)\n",
435 pci_name(dev), (char *)string.pointer);
436 kfree(string.pointer);
437 return 0;
438 }
439 if (acpi_root_bridge(handle))
440 break;
441 chandle = handle;
442 status = acpi_get_parent(chandle, &handle);
443 if (ACPI_FAILURE(status))
444 break;
445 }
446
447 dbg("Cannot get control of hotplug hardware for pci %s\n",
448 pci_name(dev));
449
450 kfree(string.pointer);
451 return -ENODEV;
452}
453EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware);
377 454
378/* acpi_root_bridge - check to see if this acpi object is a root bridge 455/* acpi_root_bridge - check to see if this acpi object is a root bridge
379 * 456 *
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 084b73efacb3..8492fab800cc 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -202,9 +202,13 @@ struct hpc_ops {
202#include <acpi/actypes.h> 202#include <acpi/actypes.h>
203#include <linux/pci-acpi.h> 203#include <linux/pci-acpi.h>
204 204
205extern int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev); 205static inline int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
206#define pciehp_get_hp_hw_control_from_firmware(dev) \ 206{
207 pciehp_acpi_get_hp_hw_control_from_firmware(dev) 207 u32 flags = (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL |
208 OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
209 return acpi_get_hp_hw_control_from_firmware(dev, flags);
210}
211
208static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, 212static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
209 struct hotplug_params *hpp) 213 struct hotplug_params *hpp)
210{ 214{
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 7e3a3d17c334..a48021d85f22 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -1009,75 +1009,6 @@ static struct hpc_ops pciehp_hpc_ops = {
1009 .check_lnk_status = hpc_check_lnk_status, 1009 .check_lnk_status = hpc_check_lnk_status,
1010}; 1010};
1011 1011
1012#ifdef CONFIG_ACPI
1013int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
1014{
1015 acpi_status status;
1016 acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
1017 struct pci_dev *pdev = dev;
1018 struct pci_bus *parent;
1019 struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
1020
1021 /*
1022 * Per PCI firmware specification, we should run the ACPI _OSC
1023 * method to get control of hotplug hardware before using it.
1024 * If an _OSC is missing, we look for an OSHP to do the same thing.
1025 * To handle different BIOS behavior, we look for _OSC and OSHP
1026 * within the scope of the hotplug controller and its parents, upto
1027 * the host bridge under which this controller exists.
1028 */
1029 while (!handle) {
1030 /*
1031 * This hotplug controller was not listed in the ACPI name
1032 * space at all. Try to get acpi handle of parent pci bus.
1033 */
1034 if (!pdev || !pdev->bus->parent)
1035 break;
1036 parent = pdev->bus->parent;
1037 dbg("Could not find %s in acpi namespace, trying parent\n",
1038 pci_name(pdev));
1039 if (!parent->self)
1040 /* Parent must be a host bridge */
1041 handle = acpi_get_pci_rootbridge_handle(
1042 pci_domain_nr(parent),
1043 parent->number);
1044 else
1045 handle = DEVICE_ACPI_HANDLE(
1046 &(parent->self->dev));
1047 pdev = parent->self;
1048 }
1049
1050 while (handle) {
1051 acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
1052 dbg("Trying to get hotplug control for %s \n",
1053 (char *)string.pointer);
1054 status = pci_osc_control_set(handle,
1055 OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL |
1056 OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
1057 if (status == AE_NOT_FOUND)
1058 status = acpi_run_oshp(handle);
1059 if (ACPI_SUCCESS(status)) {
1060 dbg("Gained control for hotplug HW for pci %s (%s)\n",
1061 pci_name(dev), (char *)string.pointer);
1062 kfree(string.pointer);
1063 return 0;
1064 }
1065 if (acpi_root_bridge(handle))
1066 break;
1067 chandle = handle;
1068 status = acpi_get_parent(chandle, &handle);
1069 if (ACPI_FAILURE(status))
1070 break;
1071 }
1072
1073 dbg("Cannot get control of hotplug hardware for pci %s\n",
1074 pci_name(dev));
1075
1076 kfree(string.pointer);
1077 return -1;
1078}
1079#endif
1080
1081static int pcie_init_hardware_part1(struct controller *ctrl, 1012static int pcie_init_hardware_part1(struct controller *ctrl,
1082 struct pcie_device *dev) 1013 struct pcie_device *dev)
1083{ 1014{
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index f66e8d6315ab..8a026f750deb 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -170,6 +170,7 @@ extern void shpchp_queue_pushbutton_work(struct work_struct *work);
170extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev); 170extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
171 171
172#ifdef CONFIG_ACPI 172#ifdef CONFIG_ACPI
173#include <linux/pci-acpi.h>
173static inline int get_hp_params_from_firmware(struct pci_dev *dev, 174static inline int get_hp_params_from_firmware(struct pci_dev *dev,
174 struct hotplug_params *hpp) 175 struct hotplug_params *hpp)
175{ 176{
@@ -177,14 +178,15 @@ static inline int get_hp_params_from_firmware(struct pci_dev *dev,
177 return -ENODEV; 178 return -ENODEV;
178 return 0; 179 return 0;
179} 180}
180#define get_hp_hw_control_from_firmware(pdev) \ 181
181 do { \ 182static inline int get_hp_hw_control_from_firmware(struct pci_dev *dev)
182 if (DEVICE_ACPI_HANDLE(&(pdev->dev))) \ 183{
183 acpi_run_oshp(DEVICE_ACPI_HANDLE(&(pdev->dev)));\ 184 u32 flags = OSC_SHPC_NATIVE_HP_CONTROL;
184 } while (0) 185 return acpi_get_hp_hw_control_from_firmware(dev, flags);
186}
185#else 187#else
186#define get_hp_params_from_firmware(dev, hpp) (-ENODEV) 188#define get_hp_params_from_firmware(dev, hpp) (-ENODEV)
187#define get_hp_hw_control_from_firmware(dev) do { } while (0) 189#define get_hp_hw_control_from_firmware(dev) (0)
188#endif 190#endif
189 191
190struct ctrl_reg { 192struct ctrl_reg {
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 0066b0be0928..df41ecc4e7fc 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -330,13 +330,14 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
330 330
331static int is_shpc_capable(struct pci_dev *dev) 331static int is_shpc_capable(struct pci_dev *dev)
332{ 332{
333 if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device == 333 if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device ==
334 PCI_DEVICE_ID_AMD_GOLAM_7450)) 334 PCI_DEVICE_ID_AMD_GOLAM_7450))
335 return 1; 335 return 1;
336 if (pci_find_capability(dev, PCI_CAP_ID_SHPC)) 336 if (!pci_find_capability(dev, PCI_CAP_ID_SHPC))
337 return 1; 337 return 0;
338 338 if (get_hp_hw_control_from_firmware(dev))
339 return 0; 339 return 0;
340 return 1;
340} 341}
341 342
342static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 343static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 7d770b2cd889..7a0bff364cd4 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -1084,7 +1084,6 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
1084 dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __func__, 1084 dbg("%s: HPC at b:d:f:irq=0x%x:%x:%x:%x\n", __func__,
1085 pdev->bus->number, PCI_SLOT(pdev->devfn), 1085 pdev->bus->number, PCI_SLOT(pdev->devfn),
1086 PCI_FUNC(pdev->devfn), pdev->irq); 1086 PCI_FUNC(pdev->devfn), pdev->irq);
1087 get_hp_hw_control_from_firmware(pdev);
1088 1087
1089 /* 1088 /*
1090 * If this is the first controller to be initialized, 1089 * If this is the first controller to be initialized,
diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
index 8f67e8f2a3cc..dbdcd1ad3c6a 100644
--- a/include/linux/pci_hotplug.h
+++ b/include/linux/pci_hotplug.h
@@ -227,9 +227,9 @@ struct hotplug_params {
227#include <acpi/acpi.h> 227#include <acpi/acpi.h>
228#include <acpi/acpi_bus.h> 228#include <acpi/acpi_bus.h>
229#include <acpi/actypes.h> 229#include <acpi/actypes.h>
230extern acpi_status acpi_run_oshp(acpi_handle handle);
231extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, 230extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus,
232 struct hotplug_params *hpp); 231 struct hotplug_params *hpp);
232int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags);
233int acpi_root_bridge(acpi_handle handle); 233int acpi_root_bridge(acpi_handle handle);
234#endif 234#endif
235#endif 235#endif