Unverified Commit eeed9987 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!4388 intel: backport Intel SST TPMI support

Merge Pull Request from: @jiayingbao 
 
This PR added ISST TPMI support. 

For details on SST terminology refer to
Documentation/admin-guide/pm/intel-speed-select.rst
under the kernel documentation

SST TPMI details are published in the following document:
https://github.com/intel/tpmi_power_management/blob/main/SST_TPMI_public_disclosure_FINAL.docx

Test:
intel-speed-select tools work as expected
Note: intel-speed-select tools update to v1.15 above to support TPMI interface.

config:
+CONFIG_INTEL_SPEED_SELECT_TPMI=m 
 
Link:https://gitee.com/openeuler/kernel/pulls/4388

 

Reviewed-by: default avatarJason Zeng <jason.zeng@intel.com>
Reviewed-by: default avatarLiu Chao <liuchao173@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents 1fe70419 e4cdbb2a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6635,6 +6635,7 @@ CONFIG_INTEL_TPMI=m
# Intel Speed Select Technology interface support
#
CONFIG_INTEL_SPEED_SELECT_INTERFACE=m
CONFIG_INTEL_SPEED_SELECT_TPMI=m
# end of Intel Speed Select Technology interface support

CONFIG_INTEL_TURBO_MAX_3=y
+4 −0
Original line number Diff line number Diff line
@@ -2,8 +2,12 @@ menu "Intel Speed Select Technology interface support"
	depends on PCI
	depends on X86_64 || COMPILE_TEST

config INTEL_SPEED_SELECT_TPMI
	tristate

config INTEL_SPEED_SELECT_INTERFACE
	tristate "Intel(R) Speed Select Technology interface drivers"
	select INTEL_SPEED_SELECT_TPMI if INTEL_TPMI
	help
	  This config enables the Intel(R) Speed Select Technology interface
	  drivers. The Intel(R) speed select technology features are non
+2 −0
Original line number Diff line number Diff line
@@ -8,3 +8,5 @@ obj-$(CONFIG_INTEL_SPEED_SELECT_INTERFACE) += isst_if_common.o
obj-$(CONFIG_INTEL_SPEED_SELECT_INTERFACE) += isst_if_mmio.o
obj-$(CONFIG_INTEL_SPEED_SELECT_INTERFACE) += isst_if_mbox_pci.o
obj-$(CONFIG_INTEL_SPEED_SELECT_INTERFACE) += isst_if_mbox_msr.o
obj-$(CONFIG_INTEL_SPEED_SELECT_TPMI) += isst_tpmi_core.o
obj-$(CONFIG_INTEL_SPEED_SELECT_TPMI) += isst_tpmi.o
+57 −12
Original line number Diff line number Diff line
@@ -19,9 +19,13 @@
#include <linux/uaccess.h>
#include <uapi/linux/isst_if.h>

#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>

#include "isst_if_common.h"

#define MSR_THREAD_ID_INFO	0x53
#define MSR_PM_LOGICAL_ID	0x54
#define MSR_CPU_BUS_NUMBER	0x128

static struct isst_if_cmd_cb punit_callbacks[ISST_IF_DEV_MAX];
@@ -31,6 +35,7 @@ static int punit_msr_white_list[] = {
	MSR_CONFIG_TDP_CONTROL,
	MSR_TURBO_RATIO_LIMIT1,
	MSR_TURBO_RATIO_LIMIT2,
	MSR_PM_LOGICAL_ID,
};

struct isst_valid_cmd_ranges {
@@ -47,7 +52,7 @@ struct isst_cmd_set_req_type {

static const struct isst_valid_cmd_ranges isst_valid_cmds[] = {
	{0xD0, 0x00, 0x03},
	{0x7F, 0x00, 0x0B},
	{0x7F, 0x00, 0x0C},
	{0x7F, 0x10, 0x12},
	{0x7F, 0x20, 0x23},
	{0x94, 0x03, 0x03},
@@ -73,6 +78,8 @@ struct isst_cmd {
	u32 param;
};

static bool isst_hpm_support;

static DECLARE_HASHTABLE(isst_hash, 8);
static DEFINE_MUTEX(isst_hash_lock);

@@ -112,6 +119,7 @@ static void isst_delete_hash(void)
 * isst_store_cmd() - Store command to a hash table
 * @cmd: Mailbox command.
 * @sub_cmd: Mailbox sub-command or MSR id.
 * @cpu: Target CPU for the command
 * @mbox_cmd_type: Mailbox or MSR command.
 * @param: Mailbox parameter.
 * @data: Mailbox request data or MSR data.
@@ -261,11 +269,13 @@ bool isst_if_mbox_cmd_set_req(struct isst_if_mbox_cmd *cmd)
}
EXPORT_SYMBOL_GPL(isst_if_mbox_cmd_set_req);

static int isst_if_api_version;

static int isst_if_get_platform_info(void __user *argp)
{
	struct isst_if_platform_info info;

	info.api_version = ISST_IF_API_VERSION;
	info.api_version = isst_if_api_version;
	info.driver_version = ISST_IF_DRIVER_VERSION;
	info.max_cmds_per_ioctl = ISST_IF_CMD_LIMIT;
	info.mbox_supported = punit_callbacks[ISST_IF_DEV_MBOX].registered;
@@ -294,14 +304,13 @@ struct isst_if_pkg_info {
static struct isst_if_cpu_info *isst_cpu_info;
static struct isst_if_pkg_info *isst_pkg_info;

#define ISST_MAX_PCI_DOMAINS	8

static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn)
{
	struct pci_dev *matched_pci_dev = NULL;
	struct pci_dev *pci_dev = NULL;
	struct pci_dev *_pci_dev = NULL;
	int no_matches = 0, pkg_id;
	int i, bus_number;
	int bus_number;

	if (bus_no < 0 || bus_no >= ISST_MAX_BUS_NUMBER || cpu < 0 ||
	    cpu >= nr_cpu_ids || cpu >= num_possible_cpus())
@@ -313,12 +322,11 @@ static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn
	if (bus_number < 0)
		return NULL;

	for (i = 0; i < ISST_MAX_PCI_DOMAINS; ++i) {
		struct pci_dev *_pci_dev;
	for_each_pci_dev(_pci_dev) {
		int node;

		_pci_dev = pci_get_domain_bus_and_slot(i, bus_number, PCI_DEVFN(dev, fn));
		if (!_pci_dev)
		if (_pci_dev->bus->number != bus_number ||
		    _pci_dev->devfn != PCI_DEVFN(dev, fn))
			continue;

		++no_matches;
@@ -327,7 +335,7 @@ static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn

		node = dev_to_node(&_pci_dev->dev);
		if (node == NUMA_NO_NODE) {
			pr_info("Fail to get numa node for CPU:%d bus:%d dev:%d fn:%d\n",
			pr_info_once("Fail to get numa node for CPU:%d bus:%d dev:%d fn:%d\n",
				     cpu, bus_no, dev, fn);
			continue;
		}
@@ -363,7 +371,7 @@ static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn
/**
 * isst_if_get_pci_dev() - Get the PCI device instance for a CPU
 * @cpu: Logical CPU number.
 * @bus_number: The bus number assigned by the hardware.
 * @bus_no: The bus number assigned by the hardware.
 * @dev: The device number assigned by the hardware.
 * @fn: The function number assigned by the hardware.
 *
@@ -408,11 +416,20 @@ static int isst_if_cpu_online(unsigned int cpu)
		isst_cpu_info[cpu].pci_dev[1] = _isst_if_get_pci_dev(cpu, 1, 30, 1);
	}

	if (isst_hpm_support) {

		ret = rdmsrl_safe(MSR_PM_LOGICAL_ID, &data);
		if (!ret)
			goto set_punit_id;
	}

	ret = rdmsrl_safe(MSR_THREAD_ID_INFO, &data);
	if (ret) {
		isst_cpu_info[cpu].punit_cpu_id = -1;
		return ret;
	}

set_punit_id:
	isst_cpu_info[cpu].punit_cpu_id = data;

	isst_restore_msr_local(cpu);
@@ -587,6 +604,7 @@ static long isst_if_def_ioctl(struct file *file, unsigned int cmd,
	struct isst_if_cmd_cb cmd_cb;
	struct isst_if_cmd_cb *cb;
	long ret = -ENOTTY;
	int i;

	switch (cmd) {
	case ISST_IF_GET_PLATFORM_INFO:
@@ -615,6 +633,16 @@ static long isst_if_def_ioctl(struct file *file, unsigned int cmd,
		ret = isst_if_exec_multi_cmd(argp, &cmd_cb);
		break;
	default:
		for (i = 0; i < ISST_IF_DEV_MAX; ++i) {
			struct isst_if_cmd_cb *cb = &punit_callbacks[i];
			int ret;

			if (cb->def_ioctl) {
				ret = cb->def_ioctl(file, cmd, arg);
				if (!ret)
					return ret;
			}
		}
		break;
	}

@@ -690,6 +718,12 @@ static struct miscdevice isst_if_char_driver = {
	.fops		= &isst_if_char_driver_ops,
};

static const struct x86_cpu_id hpm_cpu_ids[] = {
	X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_X,	NULL),
	X86_MATCH_INTEL_FAM6_MODEL(ATOM_CRESTMONT_X,	NULL),
	{}
};

static int isst_misc_reg(void)
{
	mutex_lock(&punit_misc_dev_reg_lock);
@@ -697,6 +731,12 @@ static int isst_misc_reg(void)
		goto unlock_exit;

	if (!misc_usage_count) {
		const struct x86_cpu_id *id;

		id = x86_match_cpu(hpm_cpu_ids);
		if (id)
			isst_hpm_support = true;

		misc_device_ret = isst_if_cpu_info_init();
		if (misc_device_ret)
			goto unlock_exit;
@@ -755,6 +795,10 @@ int isst_if_cdev_register(int device_type, struct isst_if_cmd_cb *cb)
		mutex_unlock(&punit_misc_dev_open_lock);
		return -EAGAIN;
	}
	if (!cb->api_version)
		cb->api_version = ISST_IF_API_VERSION;
	if (cb->api_version > isst_if_api_version)
		isst_if_api_version = cb->api_version;
	memcpy(&punit_callbacks[device_type], cb, sizeof(*cb));
	punit_callbacks[device_type].registered = 1;
	mutex_unlock(&punit_misc_dev_open_lock);
@@ -785,6 +829,7 @@ void isst_if_cdev_unregister(int device_type)
{
	isst_misc_unreg();
	mutex_lock(&punit_misc_dev_open_lock);
	punit_callbacks[device_type].def_ioctl = NULL;
	punit_callbacks[device_type].registered = 0;
	if (device_type == ISST_IF_DEV_MBOX)
		isst_delete_hash();
+8 −1
Original line number Diff line number Diff line
@@ -30,7 +30,8 @@

#define ISST_IF_DEV_MBOX	0
#define ISST_IF_DEV_MMIO	1
#define ISST_IF_DEV_MAX		2
#define ISST_IF_DEV_TPMI	2
#define ISST_IF_DEV_MAX		3

/**
 * struct isst_if_cmd_cb - Used to register a IOCTL handler
@@ -40,12 +41,16 @@
 * @offset:	Offset to the first valid member in command structure.
 *		This will be the offset of the start of the command
 *		after command count field
 * @api_version: API version supported for this target. 0, if none.
 * @owner:	Registered module owner
 * @cmd_callback: Callback function to handle IOCTL. The callback has the
 *		command pointer with data for command. There is a pointer
 *		called write_only, which when set, will not copy the
 *		response to user ioctl buffer. The "resume" argument
 *		can be used to avoid storing the command for replay
 *		during system resume
 * @def_ioctl:	Default IOCTL handler callback, if there is no match in
 *		the existing list of IOCTL handled by the common handler.
 *
 * This structure is used to register an handler for IOCTL. To avoid
 * code duplication common code handles all the IOCTL command read/write
@@ -56,8 +61,10 @@ struct isst_if_cmd_cb {
	int registered;
	int cmd_size;
	int offset;
	int api_version;
	struct module *owner;
	long (*cmd_callback)(u8 *ptr, int *write_only, int resume);
	long (*def_ioctl)(struct file *file, unsigned int cmd, unsigned long arg);
};

/* Internal interface functions */
Loading