mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
platform/x86/intel/pmt: Cache the telemetry discovery header
pmt_telem_header_decode() only needs the discovery header dwords, but it currently decodes them by reading directly from entry->disc_table. Cache the discovery header in intel_pmt_entry when the device is created and have telemetry decode use the cached values instead of performing MMIO reads at decode time. The DVSEC discovery resource for a namespace is sized by its per-entry entry_size (in dwords), which can be less than the 4-dword cache (e.g. telemetry uses entry_size = 3, i.e. 12 bytes). Cap the memcpy_fromio() to resource_size(disc_res) so the new cache does not read past the mapped region. Any unread dwords stay zero from the zero-initialized allocation of the containing struct. This keeps the telemetry header decode path independent of how the discovery data is backed and avoids baking a direct MMIO assumption into the feature-specific decode logic. Assisted-by: GitHub-Copilot:claude-opus-4.7 Signed-off-by: David E. Box <david.e.box@linux.intel.com> Link: https://patch.msgid.link/f805e2ada52dc0661761cda7f692e76e6ea2d257.1781294741.git.david.e.box@linux.intel.com Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
This commit is contained in:
parent
4a87492cd1
commit
4dfc7dca6e
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/log2.h>
|
||||
#include <linux/intel_vsec.h>
|
||||
#include <linux/io-64-nonatomic-lo-hi.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/pci.h>
|
||||
|
|
@ -383,6 +384,16 @@ int intel_pmt_dev_create(struct intel_pmt_entry *entry, struct intel_pmt_namespa
|
|||
if (IS_ERR(entry->disc_table))
|
||||
return PTR_ERR(entry->disc_table);
|
||||
|
||||
/*
|
||||
* The mapped discovery resource may be smaller than disc_header (its
|
||||
* size is the namespace's DVSEC entry_size in dwords, which can be
|
||||
* less than 4). Cap the copy to the actual resource size to avoid
|
||||
* reading past the mapped region; any unread dwords stay zero from
|
||||
* the zero-initialized allocation of the containing struct.
|
||||
*/
|
||||
memcpy_fromio(entry->disc_header, entry->disc_table,
|
||||
min(sizeof(entry->disc_header), resource_size(disc_res)));
|
||||
|
||||
if (ns->pmt_pre_decode) {
|
||||
ret = ns->pmt_pre_decode(intel_vsec_dev, entry);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ struct intel_pmt_entry {
|
|||
struct telem_endpoint *ep;
|
||||
struct pci_dev *pcidev;
|
||||
struct intel_pmt_header header;
|
||||
u32 disc_header[4];
|
||||
struct bin_attribute pmt_bin_attr;
|
||||
const struct attribute_group *attr_grp;
|
||||
struct kobject *kobj;
|
||||
|
|
|
|||
|
|
@ -72,16 +72,16 @@ static bool pmt_telem_region_overlaps(struct device *dev, u32 guid, u32 type)
|
|||
static int pmt_telem_header_decode(struct intel_pmt_entry *entry,
|
||||
struct device *dev)
|
||||
{
|
||||
void __iomem *disc_table = entry->disc_table;
|
||||
struct intel_pmt_header *header = &entry->header;
|
||||
u32 *disc_header = entry->disc_header;
|
||||
|
||||
header->access_type = TELEM_ACCESS(readl(disc_table));
|
||||
header->guid = readl(disc_table + TELEM_GUID_OFFSET);
|
||||
header->base_offset = readl(disc_table + TELEM_BASE_OFFSET);
|
||||
header->access_type = TELEM_ACCESS(disc_header[0]);
|
||||
header->guid = disc_header[1];
|
||||
header->base_offset = disc_header[2];
|
||||
|
||||
/* Size is measured in DWORDS, but accessor returns bytes */
|
||||
header->size = TELEM_SIZE(readl(disc_table));
|
||||
header->telem_type = TELEM_TYPE(readl(entry->disc_table));
|
||||
header->size = TELEM_SIZE(disc_header[0]);
|
||||
header->telem_type = TELEM_TYPE(disc_header[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user