perf/x86/uncore: Add a quirk for UPI on SPR
The discovery table of UPI on some SPR variants, e.g., MCC, is broken. The third UPI table may includes a wrong address which points to a non-exists device. The bug impacts both UPI and M3UPI uncore PMON. Use a pre-defined UPI and M3UPI table to replace the broken table. Different BIOS may populate a device into a different domain or a different BUS. The accurate location can only be retrieved at load time. Add spr_update_device_location() to update the location of the UPI and M3UPI in the pre-defined table. Signed-off-by: Kan Liang <kan.liang@linux.intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Tested-by: Michael Petlan <mpetlan@redhat.com> Link: https://lore.kernel.org/r/20230112200105.733466-5-kan.liang@linux.intel.com
This commit is contained in:
parent
bd9514a4d5
commit
65248a9a9e
|
@ -1806,6 +1806,7 @@ static const struct intel_uncore_init_fun spr_uncore_init __initconst = {
|
|||
.pci_init = spr_uncore_pci_init,
|
||||
.mmio_init = spr_uncore_mmio_init,
|
||||
.use_discovery = true,
|
||||
.uncore_units_ignore = spr_uncore_units_ignore,
|
||||
};
|
||||
|
||||
static const struct intel_uncore_init_fun generic_uncore_init __initconst = {
|
||||
|
|
|
@ -592,6 +592,7 @@ extern raw_spinlock_t pci2phy_map_lock;
|
|||
extern struct list_head pci2phy_map_head;
|
||||
extern struct pci_extra_dev *uncore_extra_pci_dev;
|
||||
extern struct event_constraint uncore_constraint_empty;
|
||||
extern int spr_uncore_units_ignore[];
|
||||
|
||||
/* uncore_snb.c */
|
||||
int snb_uncore_pci_init(void);
|
||||
|
|
|
@ -21,9 +21,15 @@
|
|||
/* Global discovery table size */
|
||||
#define UNCORE_DISCOVERY_GLOBAL_MAP_SIZE 0x20
|
||||
|
||||
#define UNCORE_DISCOVERY_PCI_DOMAIN(data) ((data >> 28) & 0x7)
|
||||
#define UNCORE_DISCOVERY_PCI_BUS(data) ((data >> 20) & 0xff)
|
||||
#define UNCORE_DISCOVERY_PCI_DEVFN(data) ((data >> 12) & 0xff)
|
||||
#define UNCORE_DISCOVERY_PCI_DOMAIN_OFFSET 28
|
||||
#define UNCORE_DISCOVERY_PCI_DOMAIN(data) \
|
||||
((data >> UNCORE_DISCOVERY_PCI_DOMAIN_OFFSET) & 0x7)
|
||||
#define UNCORE_DISCOVERY_PCI_BUS_OFFSET 20
|
||||
#define UNCORE_DISCOVERY_PCI_BUS(data) \
|
||||
((data >> UNCORE_DISCOVERY_PCI_BUS_OFFSET) & 0xff)
|
||||
#define UNCORE_DISCOVERY_PCI_DEVFN_OFFSET 12
|
||||
#define UNCORE_DISCOVERY_PCI_DEVFN(data) \
|
||||
((data >> UNCORE_DISCOVERY_PCI_DEVFN_OFFSET) & 0xff)
|
||||
#define UNCORE_DISCOVERY_PCI_BOX_CTRL(data) (data & 0xfff)
|
||||
|
||||
|
||||
|
|
|
@ -6132,6 +6132,46 @@ static int spr_upi_get_topology(struct intel_uncore_type *type)
|
|||
return discover_upi_topology(type, SPR_UBOX_DID, SPR_UPI_REGS_ADDR_DEVICE_LINK0);
|
||||
}
|
||||
|
||||
static struct intel_uncore_type spr_uncore_mdf = {
|
||||
SPR_UNCORE_COMMON_FORMAT(),
|
||||
.name = "mdf",
|
||||
};
|
||||
|
||||
#define UNCORE_SPR_NUM_UNCORE_TYPES 12
|
||||
#define UNCORE_SPR_IIO 1
|
||||
#define UNCORE_SPR_IMC 6
|
||||
#define UNCORE_SPR_UPI 8
|
||||
#define UNCORE_SPR_M3UPI 9
|
||||
|
||||
/*
|
||||
* The uncore units, which are supported by the discovery table,
|
||||
* are defined here.
|
||||
*/
|
||||
static struct intel_uncore_type *spr_uncores[UNCORE_SPR_NUM_UNCORE_TYPES] = {
|
||||
&spr_uncore_chabox,
|
||||
&spr_uncore_iio,
|
||||
&spr_uncore_irp,
|
||||
&spr_uncore_m2pcie,
|
||||
&spr_uncore_pcu,
|
||||
NULL,
|
||||
&spr_uncore_imc,
|
||||
&spr_uncore_m2m,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&spr_uncore_mdf,
|
||||
};
|
||||
|
||||
/*
|
||||
* The uncore units, which are not supported by the discovery table,
|
||||
* are implemented from here.
|
||||
*/
|
||||
#define SPR_UNCORE_UPI_NUM_BOXES 4
|
||||
|
||||
static unsigned int spr_upi_pci_offsets[SPR_UNCORE_UPI_NUM_BOXES] = {
|
||||
0, 0x8000, 0x10000, 0x18000
|
||||
};
|
||||
|
||||
static struct intel_uncore_type spr_uncore_upi = {
|
||||
.event_mask = SNBEP_PMON_RAW_EVENT_MASK,
|
||||
.event_mask_ext = SPR_RAW_EVENT_MASK_EXT,
|
||||
|
@ -6142,38 +6182,30 @@ static struct intel_uncore_type spr_uncore_upi = {
|
|||
.get_topology = spr_upi_get_topology,
|
||||
.set_mapping = spr_upi_set_mapping,
|
||||
.cleanup_mapping = spr_upi_cleanup_mapping,
|
||||
.type_id = UNCORE_SPR_UPI,
|
||||
.num_counters = 4,
|
||||
.num_boxes = SPR_UNCORE_UPI_NUM_BOXES,
|
||||
.perf_ctr_bits = 48,
|
||||
.perf_ctr = ICX_UPI_PCI_PMON_CTR0,
|
||||
.event_ctl = ICX_UPI_PCI_PMON_CTL0,
|
||||
.box_ctl = ICX_UPI_PCI_PMON_BOX_CTL,
|
||||
.pci_offsets = spr_upi_pci_offsets,
|
||||
};
|
||||
|
||||
static struct intel_uncore_type spr_uncore_m3upi = {
|
||||
SPR_UNCORE_PCI_COMMON_FORMAT(),
|
||||
.name = "m3upi",
|
||||
.type_id = UNCORE_SPR_M3UPI,
|
||||
.num_counters = 4,
|
||||
.num_boxes = SPR_UNCORE_UPI_NUM_BOXES,
|
||||
.perf_ctr_bits = 48,
|
||||
.perf_ctr = ICX_M3UPI_PCI_PMON_CTR0,
|
||||
.event_ctl = ICX_M3UPI_PCI_PMON_CTL0,
|
||||
.box_ctl = ICX_M3UPI_PCI_PMON_BOX_CTL,
|
||||
.pci_offsets = spr_upi_pci_offsets,
|
||||
.constraints = icx_uncore_m3upi_constraints,
|
||||
};
|
||||
|
||||
static struct intel_uncore_type spr_uncore_mdf = {
|
||||
SPR_UNCORE_COMMON_FORMAT(),
|
||||
.name = "mdf",
|
||||
};
|
||||
|
||||
#define UNCORE_SPR_NUM_UNCORE_TYPES 12
|
||||
#define UNCORE_SPR_IIO 1
|
||||
#define UNCORE_SPR_IMC 6
|
||||
|
||||
static struct intel_uncore_type *spr_uncores[UNCORE_SPR_NUM_UNCORE_TYPES] = {
|
||||
&spr_uncore_chabox,
|
||||
&spr_uncore_iio,
|
||||
&spr_uncore_irp,
|
||||
&spr_uncore_m2pcie,
|
||||
&spr_uncore_pcu,
|
||||
NULL,
|
||||
&spr_uncore_imc,
|
||||
&spr_uncore_m2m,
|
||||
&spr_uncore_upi,
|
||||
&spr_uncore_m3upi,
|
||||
NULL,
|
||||
&spr_uncore_mdf,
|
||||
};
|
||||
|
||||
enum perf_uncore_spr_iio_freerunning_type_id {
|
||||
SPR_IIO_MSR_IOCLK,
|
||||
SPR_IIO_MSR_BW_IN,
|
||||
|
@ -6304,6 +6336,7 @@ static struct intel_uncore_type spr_uncore_imc_free_running = {
|
|||
|
||||
#define UNCORE_SPR_MSR_EXTRA_UNCORES 1
|
||||
#define UNCORE_SPR_MMIO_EXTRA_UNCORES 1
|
||||
#define UNCORE_SPR_PCI_EXTRA_UNCORES 2
|
||||
|
||||
static struct intel_uncore_type *spr_msr_uncores[UNCORE_SPR_MSR_EXTRA_UNCORES] = {
|
||||
&spr_uncore_iio_free_running,
|
||||
|
@ -6313,6 +6346,17 @@ static struct intel_uncore_type *spr_mmio_uncores[UNCORE_SPR_MMIO_EXTRA_UNCORES]
|
|||
&spr_uncore_imc_free_running,
|
||||
};
|
||||
|
||||
static struct intel_uncore_type *spr_pci_uncores[UNCORE_SPR_PCI_EXTRA_UNCORES] = {
|
||||
&spr_uncore_upi,
|
||||
&spr_uncore_m3upi
|
||||
};
|
||||
|
||||
int spr_uncore_units_ignore[] = {
|
||||
UNCORE_SPR_UPI,
|
||||
UNCORE_SPR_M3UPI,
|
||||
UNCORE_IGNORE_END
|
||||
};
|
||||
|
||||
static void uncore_type_customized_copy(struct intel_uncore_type *to_type,
|
||||
struct intel_uncore_type *from_type)
|
||||
{
|
||||
|
@ -6413,9 +6457,69 @@ void spr_uncore_cpu_init(void)
|
|||
spr_uncore_iio_free_running.num_boxes = uncore_type_max_boxes(uncore_msr_uncores, UNCORE_SPR_IIO);
|
||||
}
|
||||
|
||||
#define SPR_UNCORE_UPI_PCIID 0x3241
|
||||
#define SPR_UNCORE_UPI0_DEVFN 0x9
|
||||
#define SPR_UNCORE_M3UPI_PCIID 0x3246
|
||||
#define SPR_UNCORE_M3UPI0_DEVFN 0x29
|
||||
|
||||
static void spr_update_device_location(int type_id)
|
||||
{
|
||||
struct intel_uncore_type *type;
|
||||
struct pci_dev *dev = NULL;
|
||||
u32 device, devfn;
|
||||
u64 *ctls;
|
||||
int die;
|
||||
|
||||
if (type_id == UNCORE_SPR_UPI) {
|
||||
type = &spr_uncore_upi;
|
||||
device = SPR_UNCORE_UPI_PCIID;
|
||||
devfn = SPR_UNCORE_UPI0_DEVFN;
|
||||
} else if (type_id == UNCORE_SPR_M3UPI) {
|
||||
type = &spr_uncore_m3upi;
|
||||
device = SPR_UNCORE_M3UPI_PCIID;
|
||||
devfn = SPR_UNCORE_M3UPI0_DEVFN;
|
||||
} else
|
||||
return;
|
||||
|
||||
ctls = kcalloc(__uncore_max_dies, sizeof(u64), GFP_KERNEL);
|
||||
if (!ctls) {
|
||||
type->num_boxes = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, dev)) != NULL) {
|
||||
if (devfn != dev->devfn)
|
||||
continue;
|
||||
|
||||
die = uncore_device_to_die(dev);
|
||||
if (die < 0)
|
||||
continue;
|
||||
|
||||
ctls[die] = pci_domain_nr(dev->bus) << UNCORE_DISCOVERY_PCI_DOMAIN_OFFSET |
|
||||
dev->bus->number << UNCORE_DISCOVERY_PCI_BUS_OFFSET |
|
||||
devfn << UNCORE_DISCOVERY_PCI_DEVFN_OFFSET |
|
||||
type->box_ctl;
|
||||
}
|
||||
|
||||
type->box_ctls = ctls;
|
||||
}
|
||||
|
||||
int spr_uncore_pci_init(void)
|
||||
{
|
||||
uncore_pci_uncores = uncore_get_uncores(UNCORE_ACCESS_PCI, 0, NULL);
|
||||
/*
|
||||
* The discovery table of UPI on some SPR variant is broken,
|
||||
* which impacts the detection of both UPI and M3UPI uncore PMON.
|
||||
* Use the pre-defined UPI and M3UPI table to replace.
|
||||
*
|
||||
* The accurate location, e.g., domain and BUS number,
|
||||
* can only be retrieved at load time.
|
||||
* Update the location of UPI and M3UPI.
|
||||
*/
|
||||
spr_update_device_location(UNCORE_SPR_UPI);
|
||||
spr_update_device_location(UNCORE_SPR_M3UPI);
|
||||
uncore_pci_uncores = uncore_get_uncores(UNCORE_ACCESS_PCI,
|
||||
UNCORE_SPR_PCI_EXTRA_UNCORES,
|
||||
spr_pci_uncores);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue