static int tb_acpi_retimer_set_power()

in acpi.c [205:264]


static int tb_acpi_retimer_set_power(struct tb_port *port, bool power)
{
	struct usb4_port *usb4 = port->usb4;
	union acpi_object argv4[2];
	struct acpi_device *adev;
	union acpi_object *obj;
	int ret;

	if (!usb4->can_offline)
		return 0;

	adev = ACPI_COMPANION(&usb4->dev);
	if (WARN_ON(!adev))
		return 0;

	/* Check if we are already powered on (and in correct mode) */
	obj = acpi_evaluate_dsm_typed(adev->handle, &retimer_dsm_guid, 1,
				      RETIMER_DSM_QUERY_ONLINE_STATE, NULL,
				      ACPI_TYPE_INTEGER);
	if (!obj) {
		tb_port_warn(port, "ACPI: query online _DSM failed\n");
		return -EIO;
	}

	ret = obj->integer.value;
	ACPI_FREE(obj);

	if (power == ret)
		return 0;

	tb_port_dbg(port, "ACPI: calling _DSM to power %s retimers\n",
		    power ? "on" : "off");

	argv4[0].type = ACPI_TYPE_PACKAGE;
	argv4[0].package.count = 1;
	argv4[0].package.elements = &argv4[1];
	argv4[1].integer.type = ACPI_TYPE_INTEGER;
	argv4[1].integer.value = power;

	obj = acpi_evaluate_dsm_typed(adev->handle, &retimer_dsm_guid, 1,
				      RETIMER_DSM_SET_ONLINE_STATE, argv4,
				      ACPI_TYPE_INTEGER);
	if (!obj) {
		tb_port_warn(port,
			     "ACPI: set online state _DSM evaluation failed\n");
		return -EIO;
	}

	ret = obj->integer.value;
	ACPI_FREE(obj);

	if (ret >= 0) {
		if (power)
			return ret == 1 ? 0 : -EBUSY;
		return 0;
	}

	tb_port_warn(port, "ACPI: set online state _DSM failed with error %d\n", ret);
	return -EIO;
}