int acpi_pci_bind_root ( struct acpi_device *device, struct acpi_pci_id *id, struct pci_bus *bus) { int result = 0; acpi_status status = AE_OK; struct acpi_pci_data *data = NULL; char *pathname = NULL; struct acpi_buffer buffer = {0, NULL}; ACPI_FUNCTION_TRACE("acpi_pci_bind_root"); pathname = (char *)kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL); if(!pathname) return_VALUE(-ENOMEM); memset(pathname, 0, ACPI_PATHNAME_MAX); buffer.length = ACPI_PATHNAME_MAX; buffer.pointer = pathname; if (!device || !id || !bus) { kfree(pathname); return_VALUE(-EINVAL); } data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); if (!data) { kfree(pathname); return_VALUE(-ENOMEM); } memset(data, 0, sizeof(struct acpi_pci_data)); data->id = *id; data->bus = bus; device->ops.bind = acpi_pci_bind; device->ops.unbind = acpi_pci_unbind; acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to " "%02x:%02x\n", pathname, id->segment, id->bus)); status = acpi_attach_data(device->handle, acpi_pci_data_handler, data); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to attach ACPI-PCI context to device %s\n", pathname)); result = -ENODEV; goto end; } end: kfree(pathname); if (result != 0) kfree(data); return_VALUE(result); }
/** * amdgpu_atpx_detect - detect whether we have PX * * Check if we have a PX system (all asics). * Returns true if we have a PX system, false if not. */ static bool amdgpu_atpx_detect(void) { char acpi_method_name[255] = { 0 }; struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name}; struct pci_dev *pdev = NULL; bool has_atpx = false; int vga_count = 0; while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { vga_count++; has_atpx |= (amdgpu_atpx_pci_probe_handle(pdev) == true); } while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { vga_count++; has_atpx |= (amdgpu_atpx_pci_probe_handle(pdev) == true); } if (has_atpx && vga_count == 2) { acpi_get_name(amdgpu_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer); printk(KERN_INFO "vga_switcheroo: detected switching method %s handle\n", acpi_method_name); amdgpu_atpx_priv.atpx_detected = true; amdgpu_atpx_init(); return true; } return false; }
static int acpi_power_get_state(acpi_handle handle, int *state) { acpi_status status = AE_OK; unsigned long long sta = 0; char node_name[5]; struct acpi_buffer buffer = { sizeof(node_name), node_name }; if (!handle || !state) return -EINVAL; status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); if (ACPI_FAILURE(status)) return -ENODEV; *state = (sta & 0x01)?ACPI_POWER_RESOURCE_STATE_ON: ACPI_POWER_RESOURCE_STATE_OFF; acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", node_name, *state ? "on" : "off")); return 0; }
/** * radeon_atpx_detect - detect whether we have PX * * Check if we have a PX system (all asics). * Returns true if we have a PX system, false if not. */ static bool radeon_atpx_detect(void) { char acpi_method_name[255] = { 0 }; struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name}; struct pci_dev *pdev = NULL; bool has_atpx = false; int vga_count = 0; while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { vga_count++; has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true); } if (has_atpx && vga_count == 2) { acpi_get_name(radeon_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer); printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n", acpi_method_name); radeon_atpx_priv.atpx_detected = true; /* * On some systems hotplug events are generated for the device * being switched off when ATPX is executed. They cause ACPI * hotplug to trigger and attempt to remove the device from * the system, which causes it to break down. Prevent that from * happening by setting the no_hotplug flag for the involved * ACPI device objects. */ acpi_bus_no_hotplug(radeon_atpx_priv.dhandle); acpi_bus_no_hotplug(radeon_atpx_priv.other_handle); return true; } return false; }
/** * radeon_atpx_detect - detect whether we have PX * * Check if we have a PX system (all asics). * Returns true if we have a PX system, false if not. */ static bool radeon_atpx_detect(void) { char acpi_method_name[255] = { 0 }; struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name}; struct pci_dev *pdev = NULL; bool has_atpx = false; int vga_count = 0; while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { vga_count++; has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true); } /* some newer PX laptops mark the dGPU as a non-VGA display device */ while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { vga_count++; has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true); } if (has_atpx && vga_count == 2) { acpi_get_name(radeon_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer); printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n", acpi_method_name); radeon_atpx_priv.atpx_detected = true; return true; } return false; }
acpi_status bm_pr_print ( BM_POWER_RESOURCE *pr) { acpi_buffer buffer; PROC_NAME("bm_pr_print"); if (!pr) { return(AE_BAD_PARAMETER); } buffer.length = 256; buffer.pointer = acpi_os_callocate(buffer.length); if (!buffer.pointer) { return(AE_NO_MEMORY); } acpi_get_name(pr->acpi_handle, ACPI_FULL_PATHNAME, &buffer); acpi_os_printf("Power Resource: found\n"); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------\n")); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| Power_resource[%02x]:[%p] %s\n", pr->device_handle, pr->acpi_handle, (char*)buffer.pointer)); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| system_level[S%d] resource_order[%d]\n", pr->system_level, pr->resource_order)); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| state[D%d] reference_count[%d]\n", pr->state, pr->reference_count)); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------\n")); acpi_os_free(buffer.pointer); return(AE_OK); }
static int meh_show(struct seq_file *seqfp, void *p) { struct pci_dev *pdev = NULL; while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) { struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; acpi_handle handle; #ifdef ACPI_HANDLE /* since Linux 3.8 */ handle = ACPI_HANDLE(&pdev->dev); #else /* removed since Linux 3.13 */ handle = DEVICE_ACPI_HANDLE(&pdev->dev); #endif seq_printf(seqfp, "%s ", dev_name(&pdev->dev)); seq_printf(seqfp, "%06x ", pdev->class); if (handle) { acpi_get_name(handle, ACPI_FULL_PATHNAME, &buf); seq_printf(seqfp, "%s\n", (char *)buf.pointer); } else { seq_printf(seqfp, "\n"); } } return 0; }
void pr_print ( PR_CONTEXT *processor) { #ifdef ACPI_DEBUG acpi_buffer buffer; FUNCTION_TRACE("pr_print"); buffer.length = 256; buffer.pointer = acpi_os_callocate(buffer.length); if (!buffer.pointer) { return; } /* * Get the full pathname for this ACPI object. */ acpi_get_name(processor->acpi_handle, ACPI_FULL_PATHNAME, &buffer); /* * Print out basic processor information. */ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------\n")); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| Processor[%02x]:[%p] uid[%02x] %s\n", processor->device_handle, processor->acpi_handle, processor->uid, (char*)buffer.pointer)); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| power: %cC0 %cC1 %cC2[%d] %cC3[%d]\n", (processor->power.state[0].is_valid?'+':'-'), (processor->power.state[1].is_valid?'+':'-'), (processor->power.state[2].is_valid?'+':'-'), processor->power.state[2].latency, (processor->power.state[3].is_valid?'+':'-'), processor->power.state[3].latency)); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| performance: states[%d]\n", processor->performance.state_count)); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------\n")); acpi_os_free(buffer.pointer); #endif /* ACPI_DEBUG */ return; }
static int __init bbswitch_init(void) { struct proc_dir_entry *acpi_entry; struct pci_dev *pdev = NULL; int class = PCI_CLASS_DISPLAY_VGA << 8; while ((pdev = pci_get_class(class, pdev)) != NULL) { struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; acpi_handle handle; handle = DEVICE_ACPI_HANDLE(&pdev->dev); if (!handle) continue; if (pdev->vendor != PCI_VENDOR_ID_INTEL) { dis_dev = pdev; dis_handle = handle; acpi_get_name(handle, ACPI_FULL_PATHNAME, &buf); printk(KERN_INFO "bbswitch: Found discrete VGA device %s: %s\n", dev_name(&pdev->dev), (char *)buf.pointer); } kfree(buf.pointer); } if (dis_dev == NULL) { printk(KERN_ERR "bbswitch: No discrete VGA device found\n"); return -ENODEV; } if (has_dsm_func(acpi_optimus_dsm_muid, 0x100, 0x1A)) { dsm_type = DSM_TYPE_OPTIMUS; printk(KERN_INFO "bbswitch: detected an Optimus _DSM function\n"); } else if (has_dsm_func(acpi_nvidia_dsm_muid, 0x102, 0x3)) { dsm_type = DSM_TYPE_NVIDIA; printk(KERN_INFO "bbswitch: detected a nVidia _DSM function\n"); } else { printk(KERN_ERR "bbswitch: No suitable _DSM call found.\n"); return -ENODEV; } acpi_entry = create_proc_entry("bbswitch", 0660, acpi_root_dir); if (acpi_entry == NULL) { printk(KERN_ERR "bbswitch: Couldn't create proc entry\n"); return -ENOMEM; } printk(KERN_INFO "bbswitch: Succesfully loaded. Discrete card %s is %s\n", dev_name(&dis_dev->dev), is_card_disabled() ? "off" : "on"); acpi_entry->write_proc = bbswitch_write; acpi_entry->read_proc = bbswitch_read; nb.notifier_call = &bbswitch_pm_handler; register_pm_notifier(&nb); return 0; }
/* get device name from acpi handle */ static void get_single_name(acpi_handle handle, char *name) { struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER}; if (ACPI_FAILURE(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer))) pr_warn("Failed to get device name from acpi handle\n"); else { memcpy(name, buffer.pointer, ACPI_NAMESEG_SIZE); kfree(buffer.pointer); } }
void bn_print ( BN_CONTEXT *button) { #ifdef ACPI_DEBUG acpi_buffer buffer; PROC_NAME("bn_print"); if (!button) { return; } buffer.length = 256; buffer.pointer = acpi_os_callocate(buffer.length); if (!buffer.pointer) { return; } /* * Get the full pathname for this ACPI object. */ acpi_get_name(button->acpi_handle, ACPI_FULL_PATHNAME, &buffer); /* * Print out basic button information. */ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------\n")); switch (button->type) { case BN_TYPE_POWER_BUTTON: case BN_TYPE_POWER_BUTTON_FIXED: ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| Power_button[%02x]:[%p] %s\n", button->device_handle, button->acpi_handle, (char*)buffer.pointer)); break; case BN_TYPE_SLEEP_BUTTON: case BN_TYPE_SLEEP_BUTTON_FIXED: ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| Sleep_button[%02x]:[%p] %s\n", button->device_handle, button->acpi_handle, (char*)buffer.pointer)); break; case BN_TYPE_LID_SWITCH: ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| Lid_switch[%02x]:[%p] %s\n", button->device_handle, button->acpi_handle, (char*)buffer.pointer)); break; } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------\n")); acpi_os_free(buffer.pointer); #endif /*ACPI_DEBUG*/ return; }
static ssize_t acpi_object_path(acpi_handle handle, char *buf) { struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL}; int result; result = acpi_get_name(handle, ACPI_FULL_PATHNAME, &path); if (result) return result; result = sprintf(buf, "%s\n", (char *)path.pointer); kfree(path.pointer); return result; }
/* -------------------------------------------------------------------------- Object Evaluation Helpers -------------------------------------------------------------------------- */ static void acpi_util_eval_error(acpi_handle h, acpi_string p, acpi_status s) { #ifdef ACPI_DEBUG_OUTPUT char prefix[80] = {'\0'}; struct acpi_buffer buffer = {sizeof(prefix), prefix}; acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n", (char *) prefix, p, acpi_format_exception(s))); #else return; #endif }
static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context, void **return_value) { acpi_status status; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); if (strstr(buffer.pointer, context) != NULL) { *return_value = handle; kfree(buffer.pointer); return AE_CTRL_TERMINATE; } return AE_OK; }
int acpi_pci_unbind( struct acpi_device *device) { int result = 0; acpi_status status = AE_OK; struct acpi_pci_data *data = NULL; char *pathname = NULL; struct acpi_buffer buffer = {0, NULL}; ACPI_FUNCTION_TRACE("acpi_pci_unbind"); if (!device || !device->parent) return_VALUE(-EINVAL); pathname = (char *) kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL); if(!pathname) return_VALUE(-ENOMEM); memset(pathname, 0, ACPI_PATHNAME_MAX); buffer.length = ACPI_PATHNAME_MAX; buffer.pointer = pathname; acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unbinding PCI device [%s]...\n", pathname)); kfree(pathname); status = acpi_get_data(device->handle, acpi_pci_data_handler, (void**)&data); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to get data from device %s\n", acpi_device_bid(device))); result = -ENODEV; goto end; } status = acpi_detach_data(device->handle, acpi_pci_data_handler); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to detach data from device %s\n", acpi_device_bid(device))); result = -ENODEV; goto end; } if (data->dev->subordinate) { acpi_pci_irq_del_prt(data->id.segment, data->bus->number); } kfree(data); end: return_VALUE(result); }
static u8 * acpi_path_name( acpi_handle handle) { acpi_status status; static u8 path_name[ACPI_PATHNAME_MAX]; struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name }; memset(path_name, 0, sizeof (path_name)); status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf); if (ACPI_FAILURE(status)) return NULL; else return path_name; }
int acpi_pci_bind_root(struct acpi_device *device, struct acpi_pci_id *id, struct pci_bus *bus) { int result = 0; acpi_status status; struct acpi_pci_data *data = NULL; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; if (!device || !id || !bus) { return -EINVAL; } data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); if (!data) return -ENOMEM; data->id = *id; data->bus = bus; device->ops.bind = acpi_pci_bind; device->ops.unbind = acpi_pci_unbind; status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); if (ACPI_FAILURE(status)) { kfree (data); return -ENODEV; } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to " "%04x:%02x\n", (char *)buffer.pointer, id->segment, id->bus)); status = acpi_attach_data(device->handle, acpi_pci_data_handler, data); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Unable to attach ACPI-PCI context to device %s", (char *)buffer.pointer)); result = -ENODEV; goto end; } end: kfree(buffer.pointer); if (result != 0) kfree(data); return result; }
static void acpi_print_osc_error(acpi_handle handle, struct acpi_osc_context *context, char *error) { struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER}; int i; if (ACPI_FAILURE(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer))) printk(KERN_DEBUG "%s\n", error); else { printk(KERN_DEBUG "%s:%s\n", (char *)buffer.pointer, error); kfree(buffer.pointer); } printk(KERN_DEBUG"_OSC request data:"); for (i = 0; i < context->cap.length; i += sizeof(u32)) printk("%x ", *((u32 *)(context->cap.pointer + i))); printk("\n"); }
static int acpi_pci_unbind(struct acpi_device *device) { int result = 0; acpi_status status; struct acpi_pci_data *data; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; if (!device || !device->parent) return -EINVAL; status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); if (ACPI_FAILURE(status)) return -ENODEV; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unbinding PCI device [%s]...\n", (char *) buffer.pointer)); kfree(buffer.pointer); status = acpi_get_data(device->handle, acpi_pci_data_handler, (void **)&data); if (ACPI_FAILURE(status)) { result = -ENODEV; goto end; } status = acpi_detach_data(device->handle, acpi_pci_data_handler); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Unable to detach data from device %s", acpi_device_bid(device))); result = -ENODEV; goto end; } if (data->dev->subordinate) { acpi_pci_irq_del_prt(data->id.segment, data->bus->number); } pci_dev_put(data->dev); kfree(data); end: return result; }
/* acpi_run_oshp - get control of hotplug from the firmware * * @handle - the handle of the hotplug controller. */ acpi_status acpi_run_oshp(acpi_handle handle) { acpi_status status; struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); /* run OSHP */ status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL); if (ACPI_FAILURE(status)) printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", __FUNCTION__, (char *)string.pointer, status); else pr_debug("%s:%s OSHP passes\n", __FUNCTION__, (char *)string.pointer); acpi_os_free(string.pointer); return status; }
static bool nouveau_dsm_detect(void) { char acpi_method_name[255] = { 0 }; struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name}; struct pci_dev *pdev = NULL; int has_dsm = 0; int has_optimus; int vga_count = 0; bool guid_valid; int retval; bool ret = false; /* lookup the MXM GUID */ guid_valid = mxm_wmi_supported(); if (guid_valid) printk("MXM: GUID detected in BIOS\n"); /* now do DSM detection */ while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { vga_count++; retval = nouveau_dsm_pci_probe(pdev); if (retval & NOUVEAU_DSM_HAS_MUX) has_dsm |= 1; if (retval & NOUVEAU_DSM_HAS_OPT) has_optimus = 1; } if (vga_count == 2 && has_dsm && guid_valid) { acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer); printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n", acpi_method_name); nouveau_dsm_priv.dsm_detected = true; ret = true; } if (has_optimus == 1) nouveau_dsm_priv.optimus_detected = true; return ret; }
/** * amdgpu_atpx_detect - detect whether we have PX * * Check if we have a PX system (all asics). * Returns true if we have a PX system, false if not. */ static bool amdgpu_atpx_detect(void) { char acpi_method_name[255] = { 0 }; struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name}; struct pci_dev *pdev = NULL; bool has_atpx = false; int vga_count = 0; bool d3_supported = false; struct pci_dev *parent_pdev; while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { vga_count++; has_atpx |= (amdgpu_atpx_pci_probe_handle(pdev) == true); parent_pdev = pci_upstream_bridge(pdev); d3_supported |= parent_pdev && parent_pdev->bridge_d3; amdgpu_atpx_get_quirks(pdev); } while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { vga_count++; has_atpx |= (amdgpu_atpx_pci_probe_handle(pdev) == true); parent_pdev = pci_upstream_bridge(pdev); d3_supported |= parent_pdev && parent_pdev->bridge_d3; amdgpu_atpx_get_quirks(pdev); } if (has_atpx && vga_count == 2) { acpi_get_name(amdgpu_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer); pr_info("vga_switcheroo: detected switching method %s handle\n", acpi_method_name); amdgpu_atpx_priv.atpx_detected = true; amdgpu_atpx_priv.bridge_pm_usable = d3_supported; amdgpu_atpx_init(); return true; } return false; }
void ec_print ( EC_CONTEXT *ec) { #ifdef ACPI_DEBUG acpi_buffer buffer; #endif /*ACPI_DEBUG*/ PROC_NAME("ec_print"); if (!ec) { return; } acpi_os_printf("EC: found, GPE %d\n", ec->gpe_bit); #ifdef ACPI_DEBUG buffer.length = 256; buffer.pointer = acpi_os_callocate(buffer.length); if (!buffer.pointer) { return; } /* * Get the full pathname for this ACPI object. */ acpi_get_name(ec->acpi_handle, ACPI_FULL_PATHNAME, &buffer); /* * Print out basic thermal zone information. */ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------\n")); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| Embedded_controller[%02x]:[%p] %s\n", ec->device_handle, ec->acpi_handle, (char*)buffer.pointer)); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| gpe_bit[%02x] status/command_port[%02x] data_port[%02x]\n", ec->gpe_bit, ec->status_port, ec->data_port)); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------\n")); acpi_os_free(buffer.pointer); #endif /*ACPI_DEBUG*/ return; }
static bool nouveau_dsm_detect(void) { char acpi_method_name[255] = { 0 }; struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name}; struct pci_dev *pdev = NULL; int has_dsm = 0; int vga_count = 0; while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { vga_count++; has_dsm |= (nouveau_dsm_pci_probe(pdev) == true); } if (vga_count == 2 && has_dsm) { acpi_get_name(nouveau_dsm_priv.dsm_handle, ACPI_FULL_PATHNAME, &buffer); printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n", acpi_method_name); nouveau_dsm_priv.dsm_detected = true; return true; } return false; }
static bool intel_dsm_detect(void) { char acpi_method_name[255] = { 0 }; struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name}; struct pci_dev *pdev = NULL; bool has_dsm = false; int vga_count = 0; while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { vga_count++; has_dsm |= intel_dsm_pci_probe(pdev); } if (vga_count == 2 && has_dsm) { acpi_get_name(intel_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer); DRM_DEBUG_DRIVER("VGA switcheroo: detected DSM switching method %s handle\n", acpi_method_name); return true; } return false; }
void ac_print ( AC_CONTEXT *ac_adapter) { #ifdef ACPI_DEBUG acpi_buffer buffer; PROC_NAME("ac_print"); if (!ac_adapter) { return; } buffer.length = 256; buffer.pointer = acpi_os_callocate(buffer.length); if (!buffer.pointer) { return; } /* * Get the full pathname for this ACPI object. */ acpi_get_name(ac_adapter->acpi_handle, ACPI_FULL_PATHNAME, &buffer); /* * Print out basic adapter information. */ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------\n")); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| AC Adapter[%02x]:[%p] %s\n", ac_adapter->device_handle, ac_adapter->acpi_handle, (char*)buffer.pointer)); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------\n")); acpi_os_free(buffer.pointer); #endif /*ACPI_DEBUG*/ return; }
void bm_print_eval_error ( u32 debug_level, acpi_handle handle, acpi_string pathname, acpi_status status) { acpi_buffer buffer; acpi_status local_status; PROC_NAME("bm_print_eval_error"); buffer.length = 256; buffer.pointer = acpi_os_callocate(buffer.length); if (!buffer.pointer) { return; } local_status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); if (ACPI_FAILURE(local_status)) { ACPI_DEBUG_PRINT((ACPI_DEBUG_LEVEL(debug_level), "Evaluate object [%p], %s\n", handle, acpi_format_exception(status))); return; } if (pathname) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate object [%s.%s], %s\n", (char*)buffer.pointer, pathname, acpi_format_exception(status))); } else { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate object [%s], %s\n", (char*)buffer.pointer, acpi_format_exception(status))); } acpi_os_free(buffer.pointer); }
int acpi_pci_bind(struct acpi_device *device) { int result = 0; acpi_status status; struct acpi_pci_data *data; struct acpi_pci_data *pdata; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; acpi_handle handle; if (!device || !device->parent) return -EINVAL; data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); if (!data) return -ENOMEM; status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); if (ACPI_FAILURE(status)) { kfree(data); return -ENODEV; } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n", (char *)buffer.pointer)); /* * Segment & Bus * ------------- * These are obtained via the parent device's ACPI-PCI context. */ status = acpi_get_data(device->parent->handle, acpi_pci_data_handler, (void **)&pdata); if (ACPI_FAILURE(status) || !pdata || !pdata->bus) { ACPI_EXCEPTION((AE_INFO, status, "Invalid ACPI-PCI context for parent device %s", acpi_device_bid(device->parent))); result = -ENODEV; goto end; } data->id.segment = pdata->id.segment; data->id.bus = pdata->bus->number; /* * Device & Function * ----------------- * These are simply obtained from the device's _ADR method. Note * that a value of zero is valid. */ data->id.device = device->pnp.bus_address >> 16; data->id.function = device->pnp.bus_address & 0xFFFF; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %04x:%02x:%02x.%d\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); /* * TBD: Support slot devices (e.g. function=0xFFFF). */ /* * Locate PCI Device * ----------------- * Locate matching device in PCI namespace. If it doesn't exist * this typically means that the device isn't currently inserted * (e.g. docking station, port replicator, etc.). */ data->dev = pci_get_slot(pdata->bus, PCI_DEVFN(data->id.device, data->id.function)); if (!data->dev) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %04x:%02x:%02x.%d not present in PCI namespace\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); result = -ENODEV; goto end; } if (!data->dev->bus) { printk(KERN_ERR PREFIX "Device %04x:%02x:%02x.%d has invalid 'bus' field\n", data->id.segment, data->id.bus, data->id.device, data->id.function); result = -ENODEV; goto end; } /* * PCI Bridge? * ----------- * If so, set the 'bus' field and install the 'bind' function to * facilitate callbacks for all of its children. */ if (data->dev->subordinate) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %04x:%02x:%02x.%d is a PCI bridge\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); data->bus = data->dev->subordinate; device->ops.bind = acpi_pci_bind; device->ops.unbind = acpi_pci_unbind; } /* * Attach ACPI-PCI Context * ----------------------- * Thus binding the ACPI and PCI devices. */ status = acpi_attach_data(device->handle, acpi_pci_data_handler, data); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Unable to attach ACPI-PCI context to device %s", acpi_device_bid(device))); result = -ENODEV; goto end; } /* * PCI Routing Table * ----------------- * Evaluate and parse _PRT, if exists. This code is independent of * PCI bridges (above) to allow parsing of _PRT objects within the * scope of non-bridge devices. Note that _PRTs within the scope of * a PCI bridge assume the bridge's subordinate bus number. * * TBD: Can _PRTs exist within the scope of non-bridge PCI devices? */ status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); if (ACPI_SUCCESS(status)) { if (data->bus) /* PCI-PCI bridge */ acpi_pci_irq_add_prt(device->handle, data->id.segment, data->bus->number); else /* non-bridge PCI device */ acpi_pci_irq_add_prt(device->handle, data->id.segment, data->id.bus); } end: kfree(buffer.pointer); if (result) { pci_dev_put(data->dev); kfree(data); } return result; }
// Returns 0 if the call succeeded and non-zero otherwise. If the call // succeeded, the result is stored in "result" providing that the result is an // integer or a buffer containing 4 values static int acpi_call_dsm(acpi_handle handle, const char muid[16], int revid, int func, char args[4], uint32_t *result) { struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_object_list input; union acpi_object params[4]; union acpi_object *obj; int err; input.count = 4; input.pointer = params; params[0].type = ACPI_TYPE_BUFFER; params[0].buffer.length = 16; params[0].buffer.pointer = (char *)muid; params[1].type = ACPI_TYPE_INTEGER; params[1].integer.value = revid; params[2].type = ACPI_TYPE_INTEGER; params[2].integer.value = func; params[3].type = ACPI_TYPE_BUFFER; params[3].buffer.length = 4; if (args) { params[3].buffer.pointer = args; } else { // Some implementations (Asus U36SD) seem to check the args before the // function ID and crash if it is not a buffer. params[3].buffer.pointer = (char[4]){0, 0, 0, 0}; } err = acpi_evaluate_object(handle, "_DSM", &input, &output); if (err) { struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; char muid_str[5 * 16]; char args_str[5 * 4]; acpi_get_name(handle, ACPI_FULL_PATHNAME, &buf); pr_warn("failed to evaluate %s._DSM {%s} 0x%X 0x%X {%s}: %s\n", (char *)buf.pointer, buffer_to_string(muid, 16, muid_str), revid, func, buffer_to_string(args, 4, args_str), acpi_format_exception(err)); return err; } obj = (union acpi_object *)output.pointer; if (obj->type == ACPI_TYPE_INTEGER && result) { *result = obj->integer.value; } else if (obj->type == ACPI_TYPE_BUFFER) { if (obj->buffer.length == 4 && result) { *result = 0; *result |= obj->buffer.pointer[0]; *result |= (obj->buffer.pointer[1] << 8); *result |= (obj->buffer.pointer[2] << 16); *result |= (obj->buffer.pointer[3] << 24); } } else { pr_warn("_DSM call yields an unsupported result type: %#x\n", obj->type); } kfree(output.pointer); return 0; } // Returns 1 if a _DSM function and its function index exists and 0 otherwise static int has_dsm_func(const char muid[16], int revid, int sfnc) { u32 result = 0; // fail if the _DSM call failed if (acpi_call_dsm(dis_handle, muid, revid, 0, 0, &result)) return 0; // ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. If // the n-th bit is enabled, function n is supported return result & 1 && result & (1 << sfnc); }
static int __init bbswitch_init(void) { struct proc_dir_entry *acpi_entry; struct pci_dev *pdev = NULL; acpi_handle igd_handle = NULL; pr_info("version %s\n", BBSWITCH_VERSION); while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) { struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; acpi_handle handle; int pci_class = pdev->class >> 8; if (pci_class != PCI_CLASS_DISPLAY_VGA && pci_class != PCI_CLASS_DISPLAY_3D) continue; handle = DEVICE_ACPI_HANDLE(&pdev->dev); if (!handle) { pr_warn("cannot find ACPI handle for VGA device %s\n", dev_name(&pdev->dev)); continue; } acpi_get_name(handle, ACPI_FULL_PATHNAME, &buf); if (pdev->vendor == PCI_VENDOR_ID_INTEL) { igd_handle = handle; pr_info("Found integrated VGA device %s: %s\n", dev_name(&pdev->dev), (char *)buf.pointer); } else { dis_dev = pdev; dis_handle = handle; pr_info("Found discrete VGA device %s: %s\n", dev_name(&pdev->dev), (char *)buf.pointer); } kfree(buf.pointer); } if (dis_dev == NULL) { pr_err("No discrete VGA device found\n"); return -ENODEV; } if (!skip_optimus_dsm && has_dsm_func(acpi_optimus_dsm_muid, 0x100, 0x1A)) { dsm_type = DSM_TYPE_OPTIMUS; pr_info("detected an Optimus _DSM function\n"); } else if (has_dsm_func(acpi_nvidia_dsm_muid, 0x102, 0x3)) { dsm_type = DSM_TYPE_NVIDIA; pr_info("detected a nVidia _DSM function\n"); } else { /* At least two Acer machines are known to use the intel ACPI handle * with the legacy nvidia DSM */ dis_handle = igd_handle; if (dis_handle && has_dsm_func(acpi_nvidia_dsm_muid, 0x102, 0x3)) { dsm_type = DSM_TYPE_NVIDIA; pr_info("detected a nVidia _DSM function on the" " integrated video card\n"); } else { pr_err("No suitable _DSM call found.\n"); return -ENODEV; } } acpi_entry = proc_create("bbswitch", 0664, acpi_root_dir, &bbswitch_fops); if (acpi_entry == NULL) { pr_err("Couldn't create proc entry\n"); return -ENOMEM; } dis_dev_get(); if (!is_card_disabled()) { /* We think the card is enabled, so ensure the kernel does as well */ if (pci_enable_device(dis_dev)) pr_warn("failed to enable %s\n", dev_name(&dis_dev->dev)); } if (load_state == CARD_ON) bbswitch_on(); else if (load_state == CARD_OFF) bbswitch_off(); pr_info("Succesfully loaded. Discrete card %s is %s\n", dev_name(&dis_dev->dev), is_card_disabled() ? "off" : "on"); dis_dev_put(); register_pm_notifier(&nb); return 0; }