drivers/platform/x86/msi-wmi-platform.c

Source file repositories/reference/linux-study-clean/drivers/platform/x86/msi-wmi-platform.c

File Facts

System
Linux kernel
Corpus path
drivers/platform/x86/msi-wmi-platform.c
Extension
.c
Size
12289 bytes
Lines
495
Domain
Driver Families
Bucket
drivers/platform
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations msi_wmi_platform_debugfs_fops = {
	.owner = THIS_MODULE,
	.open = msi_wmi_platform_open,
	.read = seq_read,
	.write = msi_wmi_platform_write,
	.llseek = seq_lseek,
	.release = single_release,
};

static void msi_wmi_platform_debugfs_remove(void *data)
{
	struct dentry *dir = data;

	debugfs_remove_recursive(dir);
}

static void msi_wmi_platform_debugfs_add(struct msi_wmi_platform_data *drvdata, struct dentry *dir,
					 const char *name, enum msi_wmi_platform_method method)
{
	struct msi_wmi_platform_debugfs_data *data;
	struct dentry *entry;

	data = devm_kzalloc(&drvdata->wdev->dev, sizeof(*data), GFP_KERNEL);
	if (!data)
		return;

	data->data = drvdata;
	data->method = method;
	init_rwsem(&data->buffer_lock);

	/* The ACPI firmware for now always requires a 32 byte input buffer due to
	 * a peculiarity in how Windows handles the CreateByteField() ACPI operator.
	 */
	data->length = 32;

	entry = debugfs_create_file(name, 0600, dir, data, &msi_wmi_platform_debugfs_fops);
	if (IS_ERR(entry))
		devm_kfree(&drvdata->wdev->dev, data);
}

static void msi_wmi_platform_debugfs_init(struct msi_wmi_platform_data *data)
{
	struct dentry *dir;
	char dir_name[64];
	int ret, method;

	scnprintf(dir_name, ARRAY_SIZE(dir_name), "%s-%s", DRIVER_NAME, dev_name(&data->wdev->dev));

	dir = debugfs_create_dir(dir_name, NULL);
	if (IS_ERR(dir))
		return;

	ret = devm_add_action_or_reset(&data->wdev->dev, msi_wmi_platform_debugfs_remove, dir);
	if (ret < 0)
		return;

	for (method = MSI_PLATFORM_GET_PACKAGE; method <= MSI_PLATFORM_GET_WMI; method++)
		msi_wmi_platform_debugfs_add(data, dir, msi_wmi_platform_debugfs_names[method - 1],
					     method);
}

static int msi_wmi_platform_hwmon_init(struct msi_wmi_platform_data *data)
{
	struct device *hdev;

	hdev = devm_hwmon_device_register_with_info(&data->wdev->dev, "msi_wmi_platform", data,
						    &msi_wmi_platform_chip_info, NULL);

	return PTR_ERR_OR_ZERO(hdev);
}

static int msi_wmi_platform_ec_init(struct msi_wmi_platform_data *data)
{
	u8 input[32] = { 0 };
	u8 output[32];
	u8 flags;
	int ret;

	ret = msi_wmi_platform_query(data, MSI_PLATFORM_GET_EC, input, sizeof(input), output,
				     sizeof(output));
	if (ret < 0)
		return ret;

	flags = output[MSI_PLATFORM_EC_FLAGS_OFFSET];

	dev_dbg(&data->wdev->dev, "EC RAM version %lu.%lu\n",
		FIELD_GET(MSI_PLATFORM_EC_MAJOR_MASK, flags),
		FIELD_GET(MSI_PLATFORM_EC_MINOR_MASK, flags));
	dev_dbg(&data->wdev->dev, "EC firmware version %.28s\n",
		&output[MSI_PLATFORM_EC_VERSION_OFFSET]);

Annotation

Implementation Notes