Example #1
0
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);
}
Example #2
0
/**
 * 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;
}
Example #3
0
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;
}
Example #4
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;
}
Example #6
0
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);
}
Example #7
0
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;
}
Example #8
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;
}
Example #9
0
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;
}
Example #10
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);
	}
}
Example #11
0
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;
}
Example #12
0
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;
}
Example #13
0
/* --------------------------------------------------------------------------
                            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
}
Example #14
0
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;
}
Example #15
0
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;
}
Example #18
0
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;
}
Example #20
0
/* 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;
}
Example #22
0
/**
 * 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;
}
Example #23
0
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;
}
Example #24
0
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;
}
Example #25
0
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;
}
Example #26
0
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;
}
Example #27
0
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;
}
Example #29
0
// 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);
}
Example #30
0
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;
}