Commit 6016d611 authored by Srinivas Pandruvada's avatar Srinivas Pandruvada Committed by jiayingbao
Browse files

platform/x86/intel/tpmi: Add debugfs support for read/write blocked

mainline inclusion
from mainline-v6.7-rc1
commit 8df012a7f513141412b3c35af204ccdb810fcc81
category: feature
bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I8WOEC

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8df012a7f513141412b3c35af204ccdb810fcc81



-------------------------------------

Display read and write blocked status of each TPMI feature in addition
to disabled and locked status.

This will require reading of read/write blocked state from the hardware.
Currently tpmi_read_feature_status(), doesn't provide this state.

Define TPMI feature state as defined in the TPMI spec. Modify the function
tpmi_read_feature_status() to update full feature state instead of just
disabled and locked state.

Intel-SIG: commit 8df012a7f513 platform/x86/intel/tpmi: Add debugfs support for read/write blocked.
Backport Intel_tpmi base driver.

Signed-off-by: default avatarSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Link: https://lore.kernel.org/r/20230925194219.966602-1-srinivas.pandruvada@linux.intel.com


Reviewed-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
[ Yingbao Jia: amend commit log ]
Signed-off-by: default avatarYingbao Jia <yingbao.jia@intel.com>
parent 1d8b52e1
Loading
Loading
Loading
Loading
+56 −25
Original line number Diff line number Diff line
@@ -143,6 +143,33 @@ struct tpmi_info_header {
	u64 lock:1;
} __packed;

/**
 * struct tpmi_feature_state - Structure to read hardware state of a feature
 * @enabled:	Enable state of a feature, 1: enabled, 0: disabled
 * @reserved_1:	Reserved for future use
 * @write_blocked: Writes are blocked means all write operations are ignored
 * @read_blocked: Reads are blocked means will read 0xFFs
 * @pcs_select:	Interface used by out of band software, not used in OS
 * @reserved_2:	Reserved for future use
 * @id:		TPMI ID of the feature
 * @reserved_3:	Reserved for future use
 * @locked:	When set to 1, OS can't change this register.
 *
 * The structure is used to read hardware state of a TPMI feature. This
 * information is used for debug and restricting operations for this feature.
 */
struct tpmi_feature_state {
	u32 enabled:1;
	u32 reserved_1:3;
	u32 write_blocked:1;
	u32 read_blocked:1;
	u32 pcs_select:1;
	u32 reserved_2:1;
	u32 id:8;
	u32 reserved_3:15;
	u32 locked:1;
} __packed;

/*
 * List of supported TMPI IDs.
 * Some TMPI IDs are not used by Linux, so the numbers are not consecutive.
@@ -202,6 +229,7 @@ EXPORT_SYMBOL_NS_GPL(tpmi_get_resource_at_index, INTEL_TPMI);

#define TPMI_CONTROL_STATUS_OFFSET	0x00
#define TPMI_COMMAND_OFFSET		0x08
#define TMPI_CONTROL_DATA_VAL_OFFSET	0x0c

/*
 * Spec is calling for max 1 seconds to get ownership at the worst
@@ -230,7 +258,6 @@ EXPORT_SYMBOL_NS_GPL(tpmi_get_resource_at_index, INTEL_TPMI);

/* TPMI command data registers */
#define TMPI_CONTROL_DATA_CMD		GENMASK_ULL(7, 0)
#define TMPI_CONTROL_DATA_VAL		GENMASK_ULL(63, 32)
#define TPMI_CONTROL_DATA_VAL_FEATURE	GENMASK_ULL(48, 40)

/* Command to send via control interface */
@@ -240,9 +267,6 @@ EXPORT_SYMBOL_NS_GPL(tpmi_get_resource_at_index, INTEL_TPMI);

#define TPMI_CMD_LEN_MASK		GENMASK_ULL(18, 16)

#define TPMI_STATE_DISABLED		BIT_ULL(0)
#define TPMI_STATE_LOCKED		BIT_ULL(31)

/* Mutex to complete get feature status without interruption */
static DEFINE_MUTEX(tpmi_dev_lock);

@@ -256,7 +280,7 @@ static int tpmi_wait_for_owner(struct intel_tpmi_info *tpmi_info, u8 owner)
}

static int tpmi_read_feature_status(struct intel_tpmi_info *tpmi_info, int feature_id,
				    int *locked, int *disabled)
				    struct tpmi_feature_state *feature_state)
{
	u64 control, data;
	int ret;
@@ -306,17 +330,8 @@ static int tpmi_read_feature_status(struct intel_tpmi_info *tpmi_info, int featu
	}

	/* Response is ready */
	data = readq(tpmi_info->tpmi_control_mem + TPMI_COMMAND_OFFSET);
	data = FIELD_GET(TMPI_CONTROL_DATA_VAL, data);

	*disabled = 0;
	*locked = 0;

	if (!(data & TPMI_STATE_DISABLED))
		*disabled = 1;

	if (data & TPMI_STATE_LOCKED)
		*locked = 1;
	memcpy_fromio(feature_state, tpmi_info->tpmi_control_mem + TMPI_CONTROL_DATA_VAL_OFFSET,
		      sizeof(*feature_state));

	ret = 0;

@@ -335,34 +350,50 @@ int tpmi_get_feature_status(struct auxiliary_device *auxdev, int feature_id,
{
	struct intel_vsec_device *intel_vsec_dev = dev_to_ivdev(auxdev->dev.parent);
	struct intel_tpmi_info *tpmi_info = auxiliary_get_drvdata(&intel_vsec_dev->auxdev);
	struct tpmi_feature_state feature_state;
	int ret;

	ret = tpmi_read_feature_status(tpmi_info, feature_id, &feature_state);
	if (ret)
		return ret;

	return tpmi_read_feature_status(tpmi_info, feature_id, locked, disabled);
	*locked = feature_state.locked;
	*disabled = !feature_state.enabled;

	return 0;
}
EXPORT_SYMBOL_NS_GPL(tpmi_get_feature_status, INTEL_TPMI);

static int tpmi_pfs_dbg_show(struct seq_file *s, void *unused)
{
	struct intel_tpmi_info *tpmi_info = s->private;
	int locked, disabled, read_blocked, write_blocked;
	struct tpmi_feature_state feature_state;
	struct intel_tpmi_pm_feature *pfs;
	int locked, disabled, ret, i;
	int ret, i;


	seq_printf(s, "tpmi PFS start offset 0x:%llx\n", tpmi_info->pfs_start);
	seq_puts(s, "tpmi_id\t\tentries\t\tsize\t\tcap_offset\tattribute\tvsec_offset\tlocked\tdisabled\n");
	seq_puts(s, "tpmi_id\t\tentries\t\tsize\t\tcap_offset\tattribute\tvsec_offset\tlocked\tdisabled\tread_blocked\twrite_blocked\n");
	for (i = 0; i < tpmi_info->feature_count; ++i) {
		pfs = &tpmi_info->tpmi_features[i];
		ret = tpmi_read_feature_status(tpmi_info, pfs->pfs_header.tpmi_id, &locked,
					       &disabled);
		ret = tpmi_read_feature_status(tpmi_info, pfs->pfs_header.tpmi_id, &feature_state);
		if (ret) {
			locked = 'U';
			disabled = 'U';
			read_blocked = 'U';
			write_blocked = 'U';
		} else {
			disabled = disabled ? 'Y' : 'N';
			locked = locked ? 'Y' : 'N';
			disabled = feature_state.enabled ? 'N' : 'Y';
			locked = feature_state.locked ? 'Y' : 'N';
			read_blocked = feature_state.read_blocked ? 'Y' : 'N';
			write_blocked = feature_state.write_blocked ? 'Y' : 'N';
		}
		seq_printf(s, "0x%02x\t\t0x%02x\t\t0x%04x\t\t0x%04x\t\t0x%02x\t\t0x%08x\t%c\t%c\n",
		seq_printf(s, "0x%02x\t\t0x%02x\t\t0x%04x\t\t0x%04x\t\t0x%02x\t\t0x%08x\t%c\t%c\t\t%c\t\t%c\n",
			   pfs->pfs_header.tpmi_id, pfs->pfs_header.num_entries,
			   pfs->pfs_header.entry_size, pfs->pfs_header.cap_offset,
			   pfs->pfs_header.attribute, pfs->vsec_offset, locked, disabled);
			   pfs->pfs_header.attribute, pfs->vsec_offset, locked, disabled,
			   read_blocked, write_blocked);
	}

	return 0;