drivers/acpi/fan_core.c

Source file repositories/reference/linux-study-clean/drivers/acpi/fan_core.c

File Facts

System
Linux kernel
Corpus path
drivers/acpi/fan_core.c
Extension
.c
Size
17587 bytes
Lines
702
Domain
Driver Families
Bucket
drivers/acpi
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (fst.control > 100) {
			dev_dbg(&device->dev, "Invalid control value returned\n");
			goto match_fps;
		}

		*state = (int) fst.control / fan->fif.step_size;
		return 0;
	}

match_fps:
	for (i = 0; i < fan->fps_count; i++) {
		if (fst.control == fan->fps[i].control)
			break;
	}
	if (i == fan->fps_count) {
		dev_dbg(&device->dev, "No matching fps control value\n");
		return -EINVAL;
	}

	*state = i;

	return status;
}

static int fan_get_state(struct acpi_device *device, unsigned long *state)
{
	int result;
	int acpi_state = ACPI_STATE_D0;

	result = acpi_device_update_power(device, &acpi_state);
	if (result)
		return result;

	*state = acpi_state == ACPI_STATE_D3_COLD
			|| acpi_state == ACPI_STATE_D3_HOT ?
		0 : (acpi_state == ACPI_STATE_D0 ? 1 : -1);
	return 0;
}

static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
			     *state)
{
	struct acpi_device *device = cdev->devdata;
	struct acpi_fan *fan = acpi_driver_data(device);

	if (fan->acpi4)
		return fan_get_state_acpi4(device, state);
	else
		return fan_get_state(device, state);
}

static int fan_set_state(struct acpi_device *device, unsigned long state)
{
	if (state != 0 && state != 1)
		return -EINVAL;

	return acpi_device_set_power(device,
				     state ? ACPI_STATE_D0 : ACPI_STATE_D3_COLD);
}

static int fan_set_state_acpi4(struct acpi_device *device, unsigned long state)
{
	struct acpi_fan *fan = acpi_driver_data(device);
	acpi_status status;
	u64 value = state;
	int max_state;

	if (fan->fif.fine_grain_ctrl)
		max_state = 100 / fan->fif.step_size;
	else
		max_state = fan->fps_count - 1;

	if (state > max_state)
		return -EINVAL;

	if (fan->fif.fine_grain_ctrl) {
		value *= fan->fif.step_size;
		/* Spec allows compensate the last step only */
		if (value + fan->fif.step_size > 100)
			value = 100;
	} else {
		value = fan->fps[state].control;
	}

	status = acpi_execute_simple_method(device->handle, "_FSL", value);
	if (ACPI_FAILURE(status)) {
		dev_dbg(&device->dev, "Failed to set state by _FSL\n");
		return -ENODEV;
	}

Annotation

Implementation Notes