static int acpi_processor_get_lpi_info(struct acpi_processor *pr) { int ret, i; acpi_status status; acpi_handle handle = pr->handle, pr_ahandle; struct acpi_device *d = NULL; struct acpi_lpi_states_array info[2], *tmp, *prev, *curr; if (!osc_pc_lpi_support_confirmed) return -EOPNOTSUPP; if (!acpi_has_method(handle, "_LPI")) return -EINVAL; flat_state_cnt = 0; prev = &info[0]; curr = &info[1]; handle = pr->handle; ret = acpi_processor_evaluate_lpi(handle, prev); if (ret) return ret; flatten_lpi_states(pr, prev, NULL); status = acpi_get_parent(handle, &pr_ahandle); while (ACPI_SUCCESS(status)) { acpi_bus_get_device(pr_ahandle, &d); handle = pr_ahandle; if (strcmp(acpi_device_hid(d), ACPI_PROCESSOR_CONTAINER_HID)) break; /* can be optional ? */ if (!acpi_has_method(handle, "_LPI")) break; ret = acpi_processor_evaluate_lpi(handle, curr); if (ret) break; /* flatten all the LPI states in this level of hierarchy */ flatten_lpi_states(pr, curr, prev); tmp = prev, prev = curr, curr = tmp; status = acpi_get_parent(handle, &pr_ahandle); } pr->power.count = flat_state_cnt; /* reset the index after flattening */ for (i = 0; i < pr->power.count; i++) pr->power.lpi_states[i].index = i; /* Tell driver that _LPI is supported. */ pr->flags.has_lpi = 1; pr->flags.power = 1; return 0; }
static int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) { acpi_handle phandle; struct acpi_device *pdev; if (acpi_get_parent(handle, &phandle)) { return -ENODEV; } if (acpi_bus_get_device(phandle, &pdev)) { return -ENODEV; } if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) { return -ENODEV; } if (processor_cntl_external() && acpi_driver_data(*device)) processor_notify_external(acpi_driver_data(*device), PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD); return 0; }
static int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) { acpi_handle phandle; struct acpi_device *pdev; struct acpi_processor *pr; ACPI_FUNCTION_TRACE("acpi_processor_device_add"); if (acpi_get_parent(handle, &phandle)) { return_VALUE(-ENODEV); } if (acpi_bus_get_device(phandle, &pdev)) { return_VALUE(-ENODEV); } if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) { return_VALUE(-ENODEV); } acpi_bus_start(*device); pr = acpi_driver_data(*device); if (!pr) return_VALUE(-ENODEV); if ((pr->id >= 0) && (pr->id < NR_CPUS)) { kobject_hotplug(&(*device)->kobj, KOBJ_ONLINE); } return_VALUE(0); }
/* pci_get_hp_params * * @dev - the pci_dev for which we want parameters * @hpp - allocated by the caller */ int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp) { acpi_status status; acpi_handle handle, phandle; struct pci_bus *pbus; handle = NULL; for (pbus = dev->bus; pbus; pbus = pbus->parent) { handle = acpi_pci_get_bridge_handle(pbus); if (handle) break; } /* * _HPP settings apply to all child buses, until another _HPP is * encountered. If we don't find an _HPP for the input pci dev, * look for it in the parent device scope since that would apply to * this pci dev. */ while (handle) { status = acpi_run_hpx(handle, hpp); if (ACPI_SUCCESS(status)) return 0; status = acpi_run_hpp(handle, hpp); if (ACPI_SUCCESS(status)) return 0; if (acpi_is_root_bridge(handle)) break; status = acpi_get_parent(handle, &phandle); if (ACPI_FAILURE(status)) break; handle = phandle; } return -ENODEV; }
static int container_device_add(struct acpi_device **device, acpi_handle handle) { acpi_handle phandle; struct acpi_device *pdev; int result; ACPI_FUNCTION_TRACE("container_device_add"); if (acpi_get_parent(handle, &phandle)) { return_VALUE(-ENODEV); } if (acpi_bus_get_device(phandle, &pdev)) { return_VALUE(-ENODEV); } if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE)) { return_VALUE(-ENODEV); } result = acpi_bus_scan(*device); return_VALUE(result); }
static int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) { acpi_handle phandle; struct acpi_device *pdev; struct acpi_processor *pr; if (acpi_get_parent(handle, &phandle)) { return -ENODEV; } if (acpi_bus_get_device(phandle, &pdev)) { return -ENODEV; } if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) { return -ENODEV; } acpi_bus_start(*device); pr = acpi_driver_data(*device); if (!pr) return -ENODEV; if ((pr->id >= 0) && (pr->id < nr_cpu_ids)) { kobject_uevent(&(*device)->dev.kobj, KOBJ_ONLINE); } return 0; }
static int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) { acpi_handle phandle; struct acpi_device *pdev; struct acpi_processor *pr; if (acpi_get_parent(handle, &phandle)) { return -ENODEV; } if (acpi_bus_get_device(phandle, &pdev)) { return -ENODEV; } if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) { return -ENODEV; } acpi_bus_start(*device); pr = acpi_driver_data(*device); if (!pr) return -ENODEV; if (processor_cntl_external()) processor_notify_external(pr, PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD); if ((pr->id >= 0) && (pr->id < NR_CPUS)) { kobject_uevent(&(*device)->kobj, KOBJ_ONLINE); } return 0; }
int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) { acpi_status status; acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); struct pci_dev *pdev = dev; u8 *path_name; /* * Per PCI firmware specification, we should run the ACPI _OSC * method to get control of hotplug hardware before using it. * If an _OSC is missing, we look for an OSHP to do the same thing. * To handle different BIOS behavior, we look for _OSC and OSHP * within the scope of the hotplug controller and its parents, upto * the host bridge under which this controller exists. */ while (!handle) { /* * This hotplug controller was not listed in the ACPI name * space at all. Try to get acpi handle of parent pci bus. */ if (!pdev || !pdev->bus->parent) break; dbg("Could not find %s in acpi namespace, trying parent\n", pci_name(pdev)); if (!pdev->bus->parent->self) /* Parent must be a host bridge */ handle = acpi_get_pci_rootbridge_handle( pci_domain_nr(pdev->bus->parent), pdev->bus->parent->number); else handle = DEVICE_ACPI_HANDLE( &(pdev->bus->parent->self->dev)); pdev = pdev->bus->parent->self; } while (handle) { path_name = acpi_path_name(handle); dbg("Trying to get hotplug control for %s \n", path_name); status = pci_osc_control_set(handle, OSC_PCI_EXPRESS_NATIVE_HP_CONTROL); if (status == AE_NOT_FOUND) status = acpi_run_oshp(handle); if (ACPI_SUCCESS(status)) { dbg("Gained control for hotplug HW for pci %s (%s)\n", pci_name(dev), path_name); return 0; } if (is_root_bridge(handle)) break; chandle = handle; status = acpi_get_parent(chandle, &handle); if (ACPI_FAILURE(status)) break; } err("Cannot get control of hotplug hardware for pci %s\n", pci_name(dev)); return -1; }
static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle) { acpi_status status; acpi_handle child_handle; acpi_handle parent_handle; acpi_handle next_child_handle; acpi_handle dummy; u32 level; ACPI_FUNCTION_TRACE(ns_delete_subtree); parent_handle = start_handle; child_handle = NULL; level = 1; while (level > 0) { status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle, child_handle, &next_child_handle); child_handle = next_child_handle; if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS (acpi_get_next_object (ACPI_TYPE_ANY, child_handle, NULL, &dummy))) { level++; parent_handle = child_handle; child_handle = NULL; } } else { level--; acpi_ns_delete_children(child_handle); child_handle = parent_handle; status = acpi_get_parent(parent_handle, &parent_handle); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } } acpi_ns_remove_node(child_handle); return_ACPI_STATUS(AE_OK); }
/* TODO: Change code to take advantage of driver model more */ static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */ acpi_handle chandle, /* current node */ struct acpi_pci_id **id, int *is_bridge, u8 * bus_number) { acpi_handle handle; struct acpi_pci_id *pci_id = *id; acpi_status status; unsigned long temp; acpi_object_type type; u8 tu8; acpi_get_parent(chandle, &handle); if (handle != rhandle) { acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge, bus_number); status = acpi_get_type(handle, &type); if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE)) return; status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &temp); if (ACPI_SUCCESS(status)) { pci_id->device = ACPI_HIWORD(ACPI_LODWORD(temp)); pci_id->function = ACPI_LOWORD(ACPI_LODWORD(temp)); if (*is_bridge) pci_id->bus = *bus_number; /* any nicer way to get bus number of bridge ? */ status = acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8, 8); if (ACPI_SUCCESS(status) && ((tu8 & 0x7f) == 1 || (tu8 & 0x7f) == 2)) { status = acpi_os_read_pci_configuration(pci_id, 0x18, &tu8, 8); if (!ACPI_SUCCESS(status)) { /* Certainly broken... FIX ME */ return; } *is_bridge = 1; pci_id->bus = tu8; status = acpi_os_read_pci_configuration(pci_id, 0x19, &tu8, 8); if (ACPI_SUCCESS(status)) { *bus_number = tu8; } } else *is_bridge = 0; } } }
static acpi_status __init zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) { acpi_handle handle, parent; acpi_status status; struct acpi_device_info *info; u64 lba_hpa, sba_hpa, length; int match; status = hp_acpi_csr_space(obj, &lba_hpa, &length); if (ACPI_FAILURE(status)) return AE_OK; /* keep looking for another bridge */ /* Look for an enclosing IOC scope and find its CSR space */ handle = obj; do { status = acpi_get_object_info(handle, &info); if (ACPI_SUCCESS(status) && (info->valid & ACPI_VALID_HID)) { /* TBD check _CID also */ match = (strcmp(info->hardware_id.string, "HWP0001") == 0); kfree(info); if (match) { status = hp_acpi_csr_space(handle, &sba_hpa, &length); if (ACPI_SUCCESS(status)) break; else { printk(KERN_ERR PFX "Detected HP ZX1 " "AGP LBA but no IOC.\n"); return AE_OK; } } } status = acpi_get_parent(handle, &parent); handle = parent; } while (ACPI_SUCCESS(status)); if (ACPI_FAILURE(status)) return AE_OK; /* found no enclosing IOC */ if (hp_zx1_setup(sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa)) return AE_OK; #ifdef CONFIG_DEBUG_PRINTK printk(KERN_INFO PFX "Detected HP ZX1 %s AGP chipset " "(ioc=%llx, lba=%llx)\n", (char *)context, sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa); #else ; #endif hp_zx1_gart_found = 1; return AE_CTRL_TERMINATE; /* we only support one bridge; quit looking */ }
/** * acpi_pcihp_check_ejectable - check if handle is ejectable ACPI PCI slot * @pbus: the PCI bus of the PCI slot corresponding to 'handle' * @handle: ACPI handle to check * * Return 1 if handle is ejectable PCI slot, 0 otherwise. */ int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle) { acpi_handle bridge_handle, parent_handle; bridge_handle = acpi_pci_get_bridge_handle(pbus); if (!bridge_handle) return 0; if ((ACPI_FAILURE(acpi_get_parent(handle, &parent_handle)))) return 0; if (bridge_handle != parent_handle) return 0; return pcihp_is_ejectable(handle); }
static acpi_status __init zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) { acpi_handle handle, parent; acpi_status status; struct acpi_buffer buffer; struct acpi_device_info *info; u64 lba_hpa, sba_hpa, length; int match; status = hp_acpi_csr_space(obj, &lba_hpa, &length); if (ACPI_FAILURE(status)) return AE_OK; /* keep looking for another bridge */ /* Look for an enclosing IOC scope and find its CSR space */ handle = obj; do { buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; status = acpi_get_object_info(handle, &buffer); if (ACPI_SUCCESS(status)) { /* TBD check _CID also */ info = buffer.pointer; info->hardware_id.value[sizeof(info->hardware_id)-1] = '\0'; match = (strcmp(info->hardware_id.value, "HWP0001") == 0); kfree(info); if (match) { status = hp_acpi_csr_space(handle, &sba_hpa, &length); if (ACPI_SUCCESS(status)) break; else { printk(KERN_ERR PFX "Detected HP ZX1 " "AGP LBA but no IOC.\n"); return AE_OK; } } } status = acpi_get_parent(handle, &parent); handle = parent; } while (ACPI_SUCCESS(status)); if (hp_zx1_setup(sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa)) return AE_OK; printk(KERN_INFO PFX "Detected HP ZX1 %s AGP chipset " "(ioc=%llx, lba=%llx)\n", (char *)context, sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa); hp_zx1_gart_found = 1; return AE_CTRL_TERMINATE; /* we only support one bridge; quit looking */ }
static int xgbe_acpi_support(struct xgbe_prv_data *pdata) { struct acpi_device *adev = pdata->adev; struct device *dev = pdata->dev; u32 property; acpi_handle handle; acpi_status status; unsigned long long data; int cca; int ret; /* Obtain the system clock setting */ ret = device_property_read_u32(dev, XGBE_ACPI_DMA_FREQ, &property); if (ret) { dev_err(dev, "unable to obtain %s property\n", XGBE_ACPI_DMA_FREQ); return ret; } pdata->sysclk_rate = property; /* Obtain the PTP clock setting */ ret = device_property_read_u32(dev, XGBE_ACPI_PTP_FREQ, &property); if (ret) { dev_err(dev, "unable to obtain %s property\n", XGBE_ACPI_PTP_FREQ); return ret; } pdata->ptpclk_rate = property; /* Retrieve the device cache coherency value */ handle = adev->handle; do { status = acpi_evaluate_integer(handle, "_CCA", NULL, &data); if (!ACPI_FAILURE(status)) { cca = data; break; } status = acpi_get_parent(handle, &handle); } while (!ACPI_FAILURE(status)); if (ACPI_FAILURE(status)) { dev_err(dev, "error obtaining acpi coherency value\n"); return -EINVAL; } pdata->coherent = !!cca; return 0; }
static acpi_status __init zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) { acpi_handle handle, parent; acpi_status status; struct acpi_device_info *info; u64 lba_hpa, sba_hpa, length; int match; status = hp_acpi_csr_space(obj, &lba_hpa, &length); if (ACPI_FAILURE(status)) return AE_OK; handle = obj; do { status = acpi_get_object_info(handle, &info); if (ACPI_SUCCESS(status)) { info->hardware_id.string[sizeof(info->hardware_id.length)-1] = '\0'; match = (strcmp(info->hardware_id.string, "HWP0001") == 0); kfree(info); if (match) { status = hp_acpi_csr_space(handle, &sba_hpa, &length); if (ACPI_SUCCESS(status)) break; else { printk(KERN_ERR PFX "Detected HP ZX1 " "AGP LBA but no IOC.\n"); return AE_OK; } } } status = acpi_get_parent(handle, &parent); handle = parent; } while (ACPI_SUCCESS(status)); if (hp_zx1_setup(sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa)) return AE_OK; printk(KERN_INFO PFX "Detected HP ZX1 %s AGP chipset " "(ioc=%llx, lba=%llx)\n", (char *)context, sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa); hp_zx1_gart_found = 1; return AE_CTRL_TERMINATE; }
int acpi_get_pxm(acpi_handle h) { unsigned long long pxm; acpi_status status; acpi_handle handle; acpi_handle phandle = h; do { handle = phandle; status = acpi_evaluate_integer(handle, "_PXM", NULL, &pxm); if (ACPI_SUCCESS(status)) return pxm; status = acpi_get_parent(handle, &phandle); } while (ACPI_SUCCESS(status)); return -1; }
static int acpi_memory_get_device(acpi_handle handle, struct acpi_memory_device **mem_device) { acpi_status status; acpi_handle phandle; struct acpi_device *device = NULL; struct acpi_device *pdevice = NULL; ACPI_FUNCTION_TRACE("acpi_memory_get_device"); if (!acpi_bus_get_device(handle, &device) && device) goto end; status = acpi_get_parent(handle, &phandle); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error in acpi_get_parent\n")); return_VALUE(-EINVAL); } /* Get the parent device */ status = acpi_bus_get_device(phandle, &pdevice); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error in acpi_bus_get_device\n")); return_VALUE(-EINVAL); } /* * Now add the notified device. This creates the acpi_device * and invokes .add function */ status = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error in acpi_bus_add\n")); return_VALUE(-EINVAL); } end: *mem_device = acpi_driver_data(device); if (!(*mem_device)) { printk(KERN_ERR "\n driver data not found"); return_VALUE(-ENODEV); } return_VALUE(0); }
static int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) { acpi_handle phandle; struct acpi_device *pdev; if (acpi_get_parent(handle, &phandle)) return -ENODEV; if (acpi_bus_get_device(phandle, &pdev)) return -ENODEV; if (acpi_bus_scan(handle)) return -ENODEV; return 0; }
static acpi_status acpi_hw_build_pci_list(acpi_handle root_pci_device, acpi_handle pci_region, struct acpi_pci_device **return_list_head) { acpi_handle current_device; acpi_handle parent_device; acpi_status status; struct acpi_pci_device *list_element; struct acpi_pci_device *list_head = NULL; /* * Ascend namespace branch until the root_pci_device is reached, building * a list of device nodes. Loop will exit when either the PCI device is * found, or the root of the namespace is reached. */ current_device = pci_region; while (1) { status = acpi_get_parent(current_device, &parent_device); if (ACPI_FAILURE(status)) { return (status); } /* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */ if (parent_device == root_pci_device) { *return_list_head = list_head; return (AE_OK); } list_element = ACPI_ALLOCATE(sizeof(struct acpi_pci_device)); if (!list_element) { return (AE_NO_MEMORY); } /* Put new element at the head of the list */ list_element->next = list_head; list_element->device = parent_device; list_head = list_element; current_device = parent_device; } }
static int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) { acpi_handle phandle; struct acpi_device *pdev; if (acpi_get_parent(handle, &phandle)) { return -ENODEV; } if (acpi_bus_get_device(phandle, &pdev)) { return -ENODEV; } if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) { return -ENODEV; } return 0; }
/* acpi_get_hp_params_from_firmware * * @bus - the pci_bus of the bus on which the device is newly added * @hpp - allocated by the caller */ acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, struct hotplug_params *hpp) { acpi_status status = AE_NOT_FOUND; acpi_handle handle, phandle; struct pci_bus *pbus = bus; struct pci_dev *pdev; do { pdev = pbus->self; if (!pdev) { handle = acpi_get_pci_rootbridge_handle( pci_domain_nr(pbus), pbus->number); break; } handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); pbus = pbus->parent; } while (!handle); /* * _HPP settings apply to all child buses, until another _HPP is * encountered. If we don't find an _HPP for the input pci dev, * look for it in the parent device scope since that would apply to * this pci dev. If we don't find any _HPP, use hardcoded defaults */ while (handle) { status = acpi_run_hpx(handle, hpp); if (ACPI_SUCCESS(status)) break; status = acpi_run_hpp(handle, hpp); if (ACPI_SUCCESS(status)) break; if (acpi_root_bridge(handle)) break; status = acpi_get_parent(handle, &phandle); if (ACPI_FAILURE(status)) break; handle = phandle; } return status; }
static int container_device_add(struct acpi_device **device, acpi_handle handle) { acpi_handle phandle; struct acpi_device *pdev; int result; if (acpi_get_parent(handle, &phandle)) { return -ENODEV; } if (acpi_bus_get_device(phandle, &pdev)) { return -ENODEV; } if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE)) { return -ENODEV; } result = acpi_bus_start(*device); return result; }
/** * acpi_get_hp_hw_control_from_firmware * @dev: the pci_dev of the bridge that has a hotplug controller * * Attempt to take hotplug control from firmware. */ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev) { const struct pci_host_bridge *host; const struct acpi_pci_root *root; acpi_status status; acpi_handle chandle, handle; struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; /* * If there's no ACPI host bridge (i.e., ACPI support is compiled * into the kernel but the hardware platform doesn't support ACPI), * there's nothing to do here. */ host = pci_find_host_bridge(pdev->bus); root = acpi_pci_find_root(ACPI_HANDLE(&host->dev)); if (!root) return 0; /* * If _OSC exists, it determines whether we're allowed to manage * the SHPC. We executed it while enumerating the host bridge. */ if (root->osc_support_set) { if (host->native_shpc_hotplug) return 0; return -ENODEV; } /* * In the absence of _OSC, we're always allowed to manage the SHPC. * However, if an OSHP method is present, we must execute it so the * firmware can transfer control to the OS, e.g., direct interrupts * to the OS instead of to the firmware. * * N.B. The PCI Firmware Spec (r3.2, sec 4.8) does not endorse * searching up the ACPI hierarchy, so the loops below are suspect. */ handle = ACPI_HANDLE(&pdev->dev); if (!handle) { /* * This hotplug controller was not listed in the ACPI name * space at all. Try to get ACPI handle of parent PCI bus. */ struct pci_bus *pbus; for (pbus = pdev->bus; pbus; pbus = pbus->parent) { handle = acpi_pci_get_bridge_handle(pbus); if (handle) break; } } while (handle) { acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); pci_info(pdev, "Requesting control of SHPC hotplug via OSHP (%s)\n", (char *)string.pointer); status = acpi_run_oshp(handle); if (ACPI_SUCCESS(status)) goto got_one; if (acpi_is_root_bridge(handle)) break; chandle = handle; status = acpi_get_parent(chandle, &handle); if (ACPI_FAILURE(status)) break; } pci_info(pdev, "Cannot get control of SHPC hotplug\n"); kfree(string.pointer); return -ENODEV; got_one: pci_info(pdev, "Gained control of SHPC hotplug (%s)\n", (char *)string.pointer); kfree(string.pointer); return 0; }
static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle) { acpi_status status; acpi_handle child_handle; acpi_handle parent_handle; acpi_handle next_child_handle; acpi_handle dummy; u32 level; ACPI_FUNCTION_TRACE(ns_delete_subtree); parent_handle = start_handle; child_handle = NULL; level = 1; /* * Traverse the tree of objects until we bubble back up * to where we started. */ while (level > 0) { /* Attempt to get the next object in this scope */ status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle, child_handle, &next_child_handle); child_handle = next_child_handle; /* Did we get a new object? */ if (ACPI_SUCCESS(status)) { /* Check if this object has any children */ if (ACPI_SUCCESS (acpi_get_next_object (ACPI_TYPE_ANY, child_handle, NULL, &dummy))) { /* * There is at least one child of this object, * visit the object */ level++; parent_handle = child_handle; child_handle = NULL; } } else { /* * No more children in this object, go back up to * the object's parent */ level--; /* Delete all children now */ acpi_ns_delete_children(child_handle); child_handle = parent_handle; status = acpi_get_parent(parent_handle, &parent_handle); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } } /* Now delete the starting object, and we are done */ acpi_ns_delete_node(child_handle); return_ACPI_STATUS(AE_OK); }
void bm_print_object ( acpi_handle handle) { acpi_buffer buffer; acpi_handle parent; acpi_object_type type; buffer.length = 256; buffer.pointer = acpi_os_callocate(buffer.length); if (!buffer.pointer) { return; } acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); acpi_get_parent(handle, &parent); acpi_get_type(handle, &type); /* * TBD: Hack to get around scope identification problem. */ if (type == ACPI_TYPE_ANY) { if (ACPI_SUCCESS(acpi_get_next_object(ACPI_TYPE_ANY, handle, 0, NULL))) { type = INTERNAL_TYPE_SCOPE; } } switch (type) { case INTERNAL_TYPE_SCOPE: acpi_os_printf("SCOPE: "); break; case ACPI_TYPE_INTEGER: acpi_os_printf("SIMPLE (number): "); break; case ACPI_TYPE_STRING: acpi_os_printf("SIMPLE (string): "); break; case ACPI_TYPE_BUFFER: acpi_os_printf("SIMPLE (buffer): "); break; case ACPI_TYPE_PACKAGE: acpi_os_printf("SIMPLE (package): "); break; case ACPI_TYPE_FIELD_UNIT: acpi_os_printf("FIELD UNIT: "); break; case ACPI_TYPE_DEVICE: acpi_os_printf("DEVICE: "); break; case ACPI_TYPE_EVENT: acpi_os_printf("EVENT: "); break; case ACPI_TYPE_METHOD: acpi_os_printf("CONTROL METHOD: "); break; case ACPI_TYPE_MUTEX: acpi_os_printf("MUTEX: "); break; case ACPI_TYPE_REGION: acpi_os_printf("OPERATION REGION: "); break; case ACPI_TYPE_POWER: acpi_os_printf("POWER RESOURCE: "); break; case ACPI_TYPE_PROCESSOR: acpi_os_printf("PROCESSOR: "); break; case ACPI_TYPE_THERMAL: acpi_os_printf("THERMAL ZONE: "); break; case ACPI_TYPE_BUFFER_FIELD: acpi_os_printf("BUFFER FIELD: "); break; case ACPI_TYPE_DDB_HANDLE: acpi_os_printf("DDB HANDLE: "); break; default: acpi_os_printf("OTHER (%d): ", type); break; } acpi_os_printf("Object[%p][%s] parent[%p].\n", handle, (char*)buffer.pointer, parent); acpi_os_free(buffer.pointer); }
acpi_status bm_enumerate_namespace (void) { acpi_status status = AE_OK; acpi_handle parent_handle = ACPI_ROOT_OBJECT; acpi_handle child_handle = NULL; BM_NODE *parent = NULL; BM_NODE *child = NULL; acpi_object_type acpi_type = 0; u32 level = 1; FUNCTION_TRACE("bm_enumerate_namespace"); parent = node_list.nodes[0]; /* * Enumerate ACPI Namespace: * ------------------------- * Parse through the ACPI namespace, identify all 'devices', * and create a new entry for each in our collection. */ while (level > 0) { /* * Get the next object at this level. */ status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle, child_handle, &child_handle); if (ACPI_SUCCESS(status)) { /* * TBD: This is a hack to get around the problem * identifying scope objects. Scopes * somehow need to be uniquely identified. */ status = acpi_get_type(child_handle, &acpi_type); if (ACPI_SUCCESS(status) && (acpi_type == ACPI_TYPE_ANY)) { status = acpi_get_next_object(ACPI_TYPE_ANY, child_handle, 0, NULL); if (ACPI_SUCCESS(status)) { acpi_type = INTERNAL_TYPE_SCOPE; } } /* * Device? * ------- * If this object is a 'device', insert into the * ACPI Bus Manager's local hierarchy and search * the object's scope for any child devices (a * depth-first search). */ switch (acpi_type) { case INTERNAL_TYPE_SCOPE: case ACPI_TYPE_DEVICE: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_THERMAL: case ACPI_TYPE_POWER: status = bm_add_namespace_device(child_handle, acpi_type, parent, &child); if (ACPI_SUCCESS(status)) { status = acpi_get_next_object(ACPI_TYPE_ANY, child_handle, 0, NULL); if (ACPI_SUCCESS(status)) { level++; parent_handle = child_handle; child_handle = 0; parent = child; } } break; } } /* * Scope Exhausted: * ---------------- * No more children in this object's scope, Go back up * in the namespace tree to the object's parent. */ else { level--; child_handle = parent_handle; acpi_get_parent(parent_handle, &parent_handle); if (parent) { parent = parent->parent; } else { return_ACPI_STATUS(AE_NULL_ENTRY); } } } return_ACPI_STATUS(AE_OK); }
static int xen_add_device(struct device *dev) { int r; struct pci_dev *pci_dev = to_pci_dev(dev); #ifdef CONFIG_PCI_IOV struct pci_dev *physfn = pci_dev->physfn; #endif if (pci_seg_supported) { struct physdev_pci_device_add add = { .seg = pci_domain_nr(pci_dev->bus), .bus = pci_dev->bus->number, .devfn = pci_dev->devfn }; #ifdef CONFIG_ACPI acpi_handle handle; #endif #ifdef CONFIG_PCI_IOV if (pci_dev->is_virtfn) { add.flags = XEN_PCI_DEV_VIRTFN; add.physfn.bus = physfn->bus->number; add.physfn.devfn = physfn->devfn; } else #endif if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn)) add.flags = XEN_PCI_DEV_EXTFN; #ifdef CONFIG_ACPI handle = DEVICE_ACPI_HANDLE(&pci_dev->dev); if (!handle) handle = DEVICE_ACPI_HANDLE(pci_dev->bus->bridge); #ifdef CONFIG_PCI_IOV if (!handle && pci_dev->is_virtfn) handle = DEVICE_ACPI_HANDLE(physfn->bus->bridge); #endif if (handle) { acpi_status status; do { unsigned long long pxm; status = acpi_evaluate_integer(handle, "_PXM", NULL, &pxm); if (ACPI_SUCCESS(status)) { add.optarr[0] = pxm; add.flags |= XEN_PCI_DEV_PXM; break; } status = acpi_get_parent(handle, &handle); } while (ACPI_SUCCESS(status)); } #endif /* CONFIG_ACPI */ r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_add, &add); if (r != -ENOSYS) return r; pci_seg_supported = false; } if (pci_domain_nr(pci_dev->bus)) r = -ENOSYS; #ifdef CONFIG_PCI_IOV else if (pci_dev->is_virtfn) { struct physdev_manage_pci_ext manage_pci_ext = { .bus = pci_dev->bus->number, .devfn = pci_dev->devfn, .is_virtfn = 1, .physfn.bus = physfn->bus->number, .physfn.devfn = physfn->devfn, }; r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext, &manage_pci_ext); } #endif else if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn)) { struct physdev_manage_pci_ext manage_pci_ext = { .bus = pci_dev->bus->number, .devfn = pci_dev->devfn, .is_extfn = 1, }; r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext, &manage_pci_ext); } else { struct physdev_manage_pci manage_pci = { .bus = pci_dev->bus->number, .devfn = pci_dev->devfn, }; r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add, &manage_pci); } return r; } static int xen_remove_device(struct device *dev) { int r; struct pci_dev *pci_dev = to_pci_dev(dev); if (pci_seg_supported) { struct physdev_pci_device device = { .seg = pci_domain_nr(pci_dev->bus), .bus = pci_dev->bus->number, .devfn = pci_dev->devfn }; r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_remove, &device); } else if (pci_domain_nr(pci_dev->bus)) r = -ENOSYS; else { struct physdev_manage_pci manage_pci = { .bus = pci_dev->bus->number, .devfn = pci_dev->devfn }; r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_remove, &manage_pci); } return r; } static int xen_pci_notifier(struct notifier_block *nb, unsigned long action, void *data) { struct device *dev = data; int r = 0; switch (action) { case BUS_NOTIFY_ADD_DEVICE: r = xen_add_device(dev); break; case BUS_NOTIFY_DEL_DEVICE: r = xen_remove_device(dev); break; default: return NOTIFY_DONE; } if (r) dev_err(dev, "Failed to %s - passthrough or MSI/MSI-X might fail!\n", action == BUS_NOTIFY_ADD_DEVICE ? "add" : (action == BUS_NOTIFY_DEL_DEVICE ? "delete" : "?")); return NOTIFY_OK; } static struct notifier_block device_nb = { .notifier_call = xen_pci_notifier, }; static int __init register_xen_pci_notifier(void) { if (!xen_initial_domain()) return 0; return bus_register_notifier(&pci_bus_type, &device_nb); } arch_initcall(register_xen_pci_notifier);