linux/drivers/hwmon/dell-smm-hwmon.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * dell-smm-hwmon.c -- Linux driver for accessing the SMM BIOS on Dell laptops.
 *
 * Copyright (C) 2001  Massimo Dal Zotto <[email protected]>
 *
 * Hwmon integration:
 * Copyright (C) 2011  Jean Delvare <[email protected]>
 * Copyright (C) 2013, 2014  Guenter Roeck <[email protected]>
 * Copyright (C) 2014, 2015  Pali Rohár <[email protected]>
 */

#define pr_fmt(fmt)

#include <linux/acpi.h>
#include <linux/capability.h>
#include <linux/cpu.h>
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/hwmon.h>
#include <linux/init.h>
#include <linux/kconfig.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/smp.h>
#include <linux/string.h>
#include <linux/thermal.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/wmi.h>

#include <linux/i8k.h>
#include <asm/unaligned.h>

#define I8K_SMM_FN_STATUS
#define I8K_SMM_POWER_STATUS
#define I8K_SMM_SET_FAN
#define I8K_SMM_GET_FAN
#define I8K_SMM_GET_SPEED
#define I8K_SMM_GET_FAN_TYPE
#define I8K_SMM_GET_NOM_SPEED
#define I8K_SMM_GET_TEMP
#define I8K_SMM_GET_TEMP_TYPE
#define I8K_SMM_GET_DELL_SIG1
#define I8K_SMM_GET_DELL_SIG2

/* in usecs */
#define DELL_SMM_MAX_DURATION

#define I8K_FAN_MULT
#define I8K_FAN_RPM_THRESHOLD
#define I8K_MAX_TEMP

#define I8K_FN_NONE
#define I8K_FN_UP
#define I8K_FN_DOWN
#define I8K_FN_MUTE
#define I8K_FN_MASK
#define I8K_FN_SHIFT

#define I8K_POWER_AC
#define I8K_POWER_BATTERY

#define DELL_SMM_WMI_GUID
#define DELL_SMM_LEGACY_EXECUTE

#define DELL_SMM_NO_TEMP
#define DELL_SMM_NO_FANS

struct smm_regs {};

struct dell_smm_ops {};

struct dell_smm_data {};

struct dell_smm_cooling_data {};

MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_ALIAS();

static bool force;
module_param_unsafe(force, bool, 0);
MODULE_PARM_DESC();

static bool ignore_dmi;
module_param(ignore_dmi, bool, 0);
MODULE_PARM_DESC();

#if IS_ENABLED(CONFIG_I8K)
static bool restricted =;
module_param(restricted, bool, 0);
MODULE_PARM_DESC();

static bool power_status;
module_param(power_status, bool, 0600);
MODULE_PARM_DESC();
#endif

static uint fan_mult;
module_param(fan_mult, uint, 0);
MODULE_PARM_DESC();

static uint fan_max;
module_param(fan_max, uint, 0);
MODULE_PARM_DESC();

static bool disallow_fan_type_call, disallow_fan_support;

static unsigned int manual_fan, auto_fan;

static const char * const temp_labels[] =;

static const char * const fan_labels[] =;

static const char * const docking_labels[] =;

static inline const char __init *i8k_get_dmi_data(int field)
{}

/*
 * Call the System Management Mode BIOS. Code provided by Jonathan Buzzard.
 */
static int i8k_smm_func(void *par)
{}

/*
 * Call the System Management Mode BIOS.
 */
static int i8k_smm_call(struct device *dummy, struct smm_regs *regs)
{}

static const struct dell_smm_ops i8k_smm_ops =;

/*
 * Call the System Management Mode BIOS over WMI.
 */
static ssize_t wmi_parse_register(u8 *buffer, u32 length, unsigned int *reg)
{}

static int wmi_parse_response(u8 *buffer, u32 length, struct smm_regs *regs)
{}

static int wmi_smm_call(struct device *dev, struct smm_regs *regs)
{}

static int dell_smm_call(const struct dell_smm_ops *ops, struct smm_regs *regs)
{}

/*
 * Read the fan status.
 */
static int i8k_get_fan_status(const struct dell_smm_data *data, u8 fan)
{}

/*
 * Read the fan speed in RPM.
 */
static int i8k_get_fan_speed(const struct dell_smm_data *data, u8 fan)
{}

/*
 * Read the fan type.
 */
static int _i8k_get_fan_type(const struct dell_smm_data *data, u8 fan)
{}

static int i8k_get_fan_type(struct dell_smm_data *data, u8 fan)
{}

/*
 * Read the fan nominal rpm for specific fan speed.
 */
static int i8k_get_fan_nominal_speed(const struct dell_smm_data *data, u8 fan, int speed)
{}

/*
 * Enable or disable automatic BIOS fan control support
 */
static int i8k_enable_fan_auto_mode(const struct dell_smm_data *data, bool enable)
{}

/*
 * Set the fan speed (off, low, high, ...).
 */
static int i8k_set_fan(const struct dell_smm_data *data, u8 fan, int speed)
{}

static int i8k_get_temp_type(const struct dell_smm_data *data, u8 sensor)
{}

/*
 * Read the cpu temperature.
 */
static int _i8k_get_temp(const struct dell_smm_data *data, u8 sensor)
{}

static int i8k_get_temp(const struct dell_smm_data *data, u8 sensor)
{}

static int dell_smm_get_signature(const struct dell_smm_ops *ops, int req_fn)
{}

#if IS_ENABLED(CONFIG_I8K)

/*
 * Read the Fn key status.
 */
static int i8k_get_fn_status(const struct dell_smm_data *data)
{}

/*
 * Read the power status.
 */
static int i8k_get_power_status(const struct dell_smm_data *data)
{}

/*
 * Procfs interface
 */

static long i8k_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
{}

/*
 * Print the information for /proc/i8k.
 */
static int i8k_proc_show(struct seq_file *seq, void *offset)
{}

static int i8k_open_fs(struct inode *inode, struct file *file)
{}

static const struct proc_ops i8k_proc_ops =;

static void i8k_exit_procfs(void *param)
{}

static void __init i8k_init_procfs(struct device *dev)
{}

#else

static void __init i8k_init_procfs(struct device *dev)
{
}

#endif

static int dell_smm_get_max_state(struct thermal_cooling_device *dev, unsigned long *state)
{}

static int dell_smm_get_cur_state(struct thermal_cooling_device *dev, unsigned long *state)
{}

static int dell_smm_set_cur_state(struct thermal_cooling_device *dev, unsigned long state)
{}

static const struct thermal_cooling_device_ops dell_smm_cooling_ops =;

static umode_t dell_smm_is_visible(const void *drvdata, enum hwmon_sensor_types type, u32 attr,
				   int channel)
{}

static int dell_smm_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
			 long *val)
{}

static const char *dell_smm_fan_label(struct dell_smm_data *data, int channel)
{}

static int dell_smm_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr,
				int channel, const char **str)
{}

static int dell_smm_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
			  long val)
{}

static const struct hwmon_ops dell_smm_ops =;

static const struct hwmon_channel_info * const dell_smm_info[] =;

static const struct hwmon_chip_info dell_smm_chip_info =;

static int dell_smm_init_cdev(struct device *dev, u8 fan_num)
{}

static int dell_smm_init_hwmon(struct device *dev)
{}

static int dell_smm_init_data(struct device *dev, const struct dell_smm_ops *ops)
{}

static const struct dmi_system_id i8k_dmi_table[] __initconst =;

MODULE_DEVICE_TABLE(dmi, i8k_dmi_table);

/*
 * Only use for machines which need some special configuration
 * in order to work correctly (e.g. if autoconfig fails on this machines).
 */
struct i8k_config_data {};

enum i8k_configs {};

static const struct i8k_config_data i8k_config_data[] __initconst =;

static const struct dmi_system_id i8k_config_dmi_table[] __initconst =;

/*
 * On some machines once I8K_SMM_GET_FAN_TYPE is issued then CPU fan speed
 * randomly going up and down due to bug in Dell SMM or BIOS. Here is blacklist
 * of affected Dell machines for which we disallow I8K_SMM_GET_FAN_TYPE call.
 * See bug: https://bugzilla.kernel.org/show_bug.cgi?id=100121
 */
static const struct dmi_system_id i8k_blacklist_fan_type_dmi_table[] __initconst =;

/*
 * On some machines all fan related SMM functions implemented by Dell BIOS
 * firmware freeze kernel for about 500ms. Until Dell fixes these problems fan
 * support for affected blacklisted Dell machines stay disabled.
 * See bug: https://bugzilla.kernel.org/show_bug.cgi?id=195751
 */
static const struct dmi_system_id i8k_blacklist_fan_support_dmi_table[] __initconst =;

struct i8k_fan_control_data {};

enum i8k_fan_controls {};

static const struct i8k_fan_control_data i8k_fan_control_data[] __initconst =;

static const struct dmi_system_id i8k_whitelist_fan_control[] __initconst =;

/*
 * Legacy SMM backend driver.
 */
static int __init dell_smm_probe(struct platform_device *pdev)
{}

static struct platform_driver dell_smm_driver =;

static struct platform_device *dell_smm_device;

/*
 * WMI SMM backend driver.
 */
static int dell_smm_wmi_probe(struct wmi_device *wdev, const void *context)
{}

static const struct wmi_device_id dell_smm_wmi_id_table[] =;
MODULE_DEVICE_TABLE(wmi, dell_smm_wmi_id_table);

static struct wmi_driver dell_smm_wmi_driver =;

/*
 * Probe for the presence of a supported laptop.
 */
static void __init dell_smm_init_dmi(void)
{}

static int __init dell_smm_legacy_check(void)
{}

static int __init i8k_init(void)
{}

static void __exit i8k_exit(void)
{}

module_init();
module_exit(i8k_exit);