|
@@ -360,67 +360,13 @@ out:
|
|
|
}
|
|
|
EXPORT_SYMBOL(acpi_pci_osc_control_set);
|
|
|
|
|
|
-static int acpi_pci_root_add(struct acpi_device *device,
|
|
|
- const struct acpi_device_id *not_used)
|
|
|
+static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm,
|
|
|
+ int *clear_aspm)
|
|
|
{
|
|
|
- unsigned long long segment, bus;
|
|
|
- acpi_status status;
|
|
|
- int result;
|
|
|
- struct acpi_pci_root *root;
|
|
|
u32 flags, base_flags;
|
|
|
+ acpi_status status;
|
|
|
+ struct acpi_device *device = root->device;
|
|
|
acpi_handle handle = device->handle;
|
|
|
- bool no_aspm = false, clear_aspm = false;
|
|
|
-
|
|
|
- root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
|
|
|
- if (!root)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- segment = 0;
|
|
|
- status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL,
|
|
|
- &segment);
|
|
|
- if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
|
|
|
- dev_err(&device->dev, "can't evaluate _SEG\n");
|
|
|
- result = -ENODEV;
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
- /* Check _CRS first, then _BBN. If no _BBN, default to zero. */
|
|
|
- root->secondary.flags = IORESOURCE_BUS;
|
|
|
- status = try_get_root_bridge_busnr(handle, &root->secondary);
|
|
|
- if (ACPI_FAILURE(status)) {
|
|
|
- /*
|
|
|
- * We need both the start and end of the downstream bus range
|
|
|
- * to interpret _CBA (MMCONFIG base address), so it really is
|
|
|
- * supposed to be in _CRS. If we don't find it there, all we
|
|
|
- * can do is assume [_BBN-0xFF] or [0-0xFF].
|
|
|
- */
|
|
|
- root->secondary.end = 0xFF;
|
|
|
- dev_warn(&device->dev,
|
|
|
- FW_BUG "no secondary bus range in _CRS\n");
|
|
|
- status = acpi_evaluate_integer(handle, METHOD_NAME__BBN,
|
|
|
- NULL, &bus);
|
|
|
- if (ACPI_SUCCESS(status))
|
|
|
- root->secondary.start = bus;
|
|
|
- else if (status == AE_NOT_FOUND)
|
|
|
- root->secondary.start = 0;
|
|
|
- else {
|
|
|
- dev_err(&device->dev, "can't evaluate _BBN\n");
|
|
|
- result = -ENODEV;
|
|
|
- goto end;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- root->device = device;
|
|
|
- root->segment = segment & 0xFFFF;
|
|
|
- strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
|
|
|
- strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
|
|
|
- device->driver_data = root;
|
|
|
-
|
|
|
- pr_info(PREFIX "%s [%s] (domain %04x %pR)\n",
|
|
|
- acpi_device_name(device), acpi_device_bid(device),
|
|
|
- root->segment, &root->secondary);
|
|
|
-
|
|
|
- root->mcfg_addr = acpi_pci_root_get_mcfg_addr(handle);
|
|
|
|
|
|
/*
|
|
|
* All supported architectures that use ACPI have support for
|
|
@@ -441,7 +387,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
|
|
|
if (ACPI_FAILURE(status)) {
|
|
|
dev_info(&device->dev, "ACPI _OSC support "
|
|
|
"notification failed, disabling PCIe ASPM\n");
|
|
|
- no_aspm = true;
|
|
|
+ *no_aspm = 1;
|
|
|
flags = base_flags;
|
|
|
}
|
|
|
}
|
|
@@ -473,7 +419,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
|
|
|
* We have ASPM control, but the FADT indicates
|
|
|
* that it's unsupported. Clear it.
|
|
|
*/
|
|
|
- clear_aspm = true;
|
|
|
+ *clear_aspm = 1;
|
|
|
}
|
|
|
} else {
|
|
|
dev_info(&device->dev,
|
|
@@ -489,13 +435,77 @@ static int acpi_pci_root_add(struct acpi_device *device,
|
|
|
* flag here, to defer the action until after the ACPI
|
|
|
* root scan.
|
|
|
*/
|
|
|
- no_aspm = true;
|
|
|
+ *no_aspm = 1;
|
|
|
}
|
|
|
} else {
|
|
|
dev_info(&device->dev,
|
|
|
"Unable to request _OSC control "
|
|
|
"(_OSC support mask: 0x%02x)\n", flags);
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+static int acpi_pci_root_add(struct acpi_device *device,
|
|
|
+ const struct acpi_device_id *not_used)
|
|
|
+{
|
|
|
+ unsigned long long segment, bus;
|
|
|
+ acpi_status status;
|
|
|
+ int result;
|
|
|
+ struct acpi_pci_root *root;
|
|
|
+ acpi_handle handle = device->handle;
|
|
|
+ int no_aspm = 0, clear_aspm = 0;
|
|
|
+
|
|
|
+ root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
|
|
|
+ if (!root)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ segment = 0;
|
|
|
+ status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL,
|
|
|
+ &segment);
|
|
|
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
|
|
|
+ dev_err(&device->dev, "can't evaluate _SEG\n");
|
|
|
+ result = -ENODEV;
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Check _CRS first, then _BBN. If no _BBN, default to zero. */
|
|
|
+ root->secondary.flags = IORESOURCE_BUS;
|
|
|
+ status = try_get_root_bridge_busnr(handle, &root->secondary);
|
|
|
+ if (ACPI_FAILURE(status)) {
|
|
|
+ /*
|
|
|
+ * We need both the start and end of the downstream bus range
|
|
|
+ * to interpret _CBA (MMCONFIG base address), so it really is
|
|
|
+ * supposed to be in _CRS. If we don't find it there, all we
|
|
|
+ * can do is assume [_BBN-0xFF] or [0-0xFF].
|
|
|
+ */
|
|
|
+ root->secondary.end = 0xFF;
|
|
|
+ dev_warn(&device->dev,
|
|
|
+ FW_BUG "no secondary bus range in _CRS\n");
|
|
|
+ status = acpi_evaluate_integer(handle, METHOD_NAME__BBN,
|
|
|
+ NULL, &bus);
|
|
|
+ if (ACPI_SUCCESS(status))
|
|
|
+ root->secondary.start = bus;
|
|
|
+ else if (status == AE_NOT_FOUND)
|
|
|
+ root->secondary.start = 0;
|
|
|
+ else {
|
|
|
+ dev_err(&device->dev, "can't evaluate _BBN\n");
|
|
|
+ result = -ENODEV;
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ root->device = device;
|
|
|
+ root->segment = segment & 0xFFFF;
|
|
|
+ strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
|
|
|
+ strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
|
|
|
+ device->driver_data = root;
|
|
|
+
|
|
|
+ pr_info(PREFIX "%s [%s] (domain %04x %pR)\n",
|
|
|
+ acpi_device_name(device), acpi_device_bid(device),
|
|
|
+ root->segment, &root->secondary);
|
|
|
+
|
|
|
+ root->mcfg_addr = acpi_pci_root_get_mcfg_addr(handle);
|
|
|
+
|
|
|
+ negotiate_os_control(root, &no_aspm, &clear_aspm);
|
|
|
|
|
|
/*
|
|
|
* TBD: Need PCI interface for enumeration/configuration of roots.
|