static void decode_hpp(struct acpiphp_bridge *bridge)
{
acpi_status status;
- struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER,
- .pointer = NULL};
- union acpi_object *package;
- int i;
-
- /* default numbers */
- bridge->hpp.cache_line_size = 0x10;
- bridge->hpp.latency_timer = 0x40;
- bridge->hpp.enable_SERR = 0;
- bridge->hpp.enable_PERR = 0;
-
- status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer);
+ status = acpi_get_hp_params_from_firmware(bridge->pci_dev, &bridge->hpp);
if (ACPI_FAILURE(status)) {
- dbg("_HPP evaluation failed\n");
- return;
+ /* use default numbers */
+ bridge->hpp.cache_line_size = 0x10;
+ bridge->hpp.latency_timer = 0x40;
+ bridge->hpp.enable_serr = 0;
+ bridge->hpp.enable_perr = 0;
}
-
- package = (union acpi_object *) buffer.pointer;
-
- if (!package || package->type != ACPI_TYPE_PACKAGE ||
- package->package.count != 4 || !package->package.elements) {
- err("invalid _HPP object; ignoring\n");
- goto err_exit;
- }
-
- for (i = 0; i < 4; i++) {
- if (package->package.elements[i].type != ACPI_TYPE_INTEGER) {
- err("invalid _HPP parameter type; ignoring\n");
- goto err_exit;
- }
- }
-
- bridge->hpp.cache_line_size = package->package.elements[0].integer.value;
- bridge->hpp.latency_timer = package->package.elements[1].integer.value;
- bridge->hpp.enable_SERR = package->package.elements[2].integer.value;
- bridge->hpp.enable_PERR = package->package.elements[3].integer.value;
-
- dbg("_HPP parameter = (%02x, %02x, %02x, %02x)\n",
- bridge->hpp.cache_line_size,
- bridge->hpp.latency_timer,
- bridge->hpp.enable_SERR,
- bridge->hpp.enable_PERR);
-
- bridge->flags |= BRIDGE_HAS_HPP;
-
- err_exit:
- kfree(buffer.pointer);
}
+
/* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */
static void init_bridge_misc(struct acpiphp_bridge *bridge)
{
}
-
-/**
- * get_func - get a pointer to acpiphp_func given a slot, device
- * @slot: slot to search
- * @dev: pci_dev struct to match.
- *
- * This function will increase the reference count of pci_dev,
- * so callers should call pci_dev_put when complete.
- *
- */
-static struct acpiphp_func *
-get_func(struct acpiphp_slot *slot, struct pci_dev *dev)
-{
- struct acpiphp_func *func = NULL;
- struct pci_bus *bus = slot->bridge->pci_bus;
- struct pci_dev *pdev;
-
- list_for_each_entry(func, &slot->funcs, sibling) {
- pdev = pci_get_slot(bus, PCI_DEVFN(slot->device,
- func->function));
- if (pdev) {
- if (pdev == dev)
- break;
- pci_dev_put(pdev);
- }
- }
- return func;
-}
-
-
/**
* acpiphp_bus_add - add a new bus to acpi subsystem
* @func: acpiphp_func of the bridge
}
+/**
+ * acpiphp_bus_trim - trim a bus from acpi subsystem
+ * @handle: handle to acpi namespace
+ *
+ */
+int acpiphp_bus_trim(acpi_handle handle)
+{
+ struct acpi_device *device;
+ int retval;
+
+ retval = acpi_bus_get_device(handle, &device);
+ if (retval) {
+ dbg("acpi_device not found\n");
+ return retval;
+ }
+
+ retval = acpi_bus_trim(device, 1);
+ if (retval)
+ err("cannot remove from acpi list\n");
+
+ return retval;
+}
/**
* enable_device - enable, configure a slot
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
max = pci_scan_bridge(bus, dev, max, pass);
- if (pass && dev->subordinate) {
+ if (pass && dev->subordinate)
pci_bus_size_bridges(dev->subordinate);
- func = get_func(slot, dev);
- if (func) {
- acpiphp_bus_add(func);
- /* side effect of get_func */
- pci_dev_put(dev);
- }
- }
}
}
}
+ list_for_each (l, &slot->funcs) {
+ func = list_entry(l, struct acpiphp_func, sibling);
+ acpiphp_bus_add(func);
+ }
+
pci_bus_assign_resources(bus);
acpiphp_sanitize_bus(bus);
pci_enable_bridges(bus);
list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling);
+
+ acpiphp_bus_trim(func->handle);
+ /* try to remove anyway.
+ * acpiphp_bus_add might have been failed */
+
if (!func->pci_dev)
continue;
pci_write_config_byte(dev, PCI_LATENCY_TIMER,
bridge->hpp.latency_timer);
pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
- if (bridge->hpp.enable_SERR)
+ if (bridge->hpp.enable_serr)
pci_cmd |= PCI_COMMAND_SERR;
else
pci_cmd &= ~PCI_COMMAND_SERR;
- if (bridge->hpp.enable_PERR)
+ if (bridge->hpp.enable_perr)
pci_cmd |= PCI_COMMAND_PARITY;
else
pci_cmd &= ~PCI_COMMAND_PARITY;
pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
bridge->hpp.latency_timer);
pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
- if (bridge->hpp.enable_SERR)
+ if (bridge->hpp.enable_serr)
pci_bctl |= PCI_BRIDGE_CTL_SERR;
else
pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
- if (bridge->hpp.enable_PERR)
+ if (bridge->hpp.enable_perr)
pci_bctl |= PCI_BRIDGE_CTL_PARITY;
else
pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
memset(&bridge, 0, sizeof(bridge));
bridge.handle = handle;
+ bridge.pci_dev = bus->self;
decode_hpp(&bridge);
list_for_each_entry(dev, &bus->devices, bus_list)
program_hpp(dev, &bridge);
}
}
-static int is_root_bridge(acpi_handle handle)
-{
- acpi_status status;
- struct acpi_device_info *info;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- int i;
-
- status = acpi_get_object_info(handle, &buffer);
- if (ACPI_SUCCESS(status)) {
- info = buffer.pointer;
- if ((info->valid & ACPI_VALID_HID) &&
- !strcmp(PCI_ROOT_HID_STRING,
- info->hardware_id.value)) {
- acpi_os_free(buffer.pointer);
- return 1;
- }
- if (info->valid & ACPI_VALID_CID) {
- for (i=0; i < info->compatibility_id.count; i++) {
- if (!strcmp(PCI_ROOT_HID_STRING,
- info->compatibility_id.id[i].value)) {
- acpi_os_free(buffer.pointer);
- return 1;
- }
- }
- }
- }
- return 0;
-}
static acpi_status
find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
{
int *count = (int *)context;
- if (is_root_bridge(handle)) {
+ if (acpi_root_bridge(handle)) {
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
handle_hotplug_event_bridge, NULL);
(*count)++;