perf/x86/uncore: Apply the unit control RB tree to PCI uncore units
BugLink: https://bugs.launchpad.net/bugs/2081079
The unit control RB tree has the unit control and unit ID information
for all the PCI units. Use them to replace the box_ctls/pci_offsets to
get an accurate unit control address for PCI uncore units.
The UPI/M3UPI units in the discovery table are ignored. Please see the
commit 65248a9a9e ("perf/x86/uncore: Add a quirk for UPI on SPR").
Manually allocate a unit control RB tree for UPI/M3UPI.
Add cleanup_extra_boxes to release such manual allocation.
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Tested-by: Yunying Sun <yunying.sun@intel.com>
Link: https://lore.kernel.org/r/20240614134631.1092359-7-kan.liang@linux.intel.com
(cherry picked from commit f76a8420444beb1c3968504c8176a67d2d5fe18f)
Signed-off-by: Michael Reed <Michael.Reed@canonical.com>
Acked-by: Thibault Ferrante <thibault.ferrante@canonical.com>
Acked-by: Mehmet Basaran <mehmet.basaran@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
This commit is contained in:
committed by
Mehmet Basaran
parent
bf1224e87c
commit
6c160a3ca8
@@ -969,6 +969,9 @@ static void uncore_type_exit(struct intel_uncore_type *type)
|
||||
if (type->cleanup_mapping)
|
||||
type->cleanup_mapping(type);
|
||||
|
||||
if (type->cleanup_extra_boxes)
|
||||
type->cleanup_extra_boxes(type);
|
||||
|
||||
if (pmu) {
|
||||
for (i = 0; i < type->num_boxes; i++, pmu++) {
|
||||
uncore_pmu_unregister(pmu);
|
||||
@@ -1084,22 +1087,19 @@ static struct intel_uncore_pmu *
|
||||
uncore_pci_find_dev_pmu_from_types(struct pci_dev *pdev)
|
||||
{
|
||||
struct intel_uncore_type **types = uncore_pci_uncores;
|
||||
struct intel_uncore_discovery_unit *unit;
|
||||
struct intel_uncore_type *type;
|
||||
u64 box_ctl;
|
||||
int i, die;
|
||||
struct rb_node *node;
|
||||
|
||||
for (; *types; types++) {
|
||||
type = *types;
|
||||
for (die = 0; die < __uncore_max_dies; die++) {
|
||||
for (i = 0; i < type->num_boxes; i++) {
|
||||
if (!type->box_ctls[die])
|
||||
continue;
|
||||
box_ctl = type->box_ctls[die] + type->pci_offsets[i];
|
||||
if (pdev->devfn == UNCORE_DISCOVERY_PCI_DEVFN(box_ctl) &&
|
||||
pdev->bus->number == UNCORE_DISCOVERY_PCI_BUS(box_ctl) &&
|
||||
pci_domain_nr(pdev->bus) == UNCORE_DISCOVERY_PCI_DOMAIN(box_ctl))
|
||||
return &type->pmus[i];
|
||||
}
|
||||
|
||||
for (node = rb_first(type->boxes); node; node = rb_next(node)) {
|
||||
unit = rb_entry(node, struct intel_uncore_discovery_unit, node);
|
||||
if (pdev->devfn == UNCORE_DISCOVERY_PCI_DEVFN(unit->addr) &&
|
||||
pdev->bus->number == UNCORE_DISCOVERY_PCI_BUS(unit->addr) &&
|
||||
pci_domain_nr(pdev->bus) == UNCORE_DISCOVERY_PCI_DOMAIN(unit->addr))
|
||||
return &type->pmus[unit->pmu_idx];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1375,28 +1375,25 @@ static struct notifier_block uncore_pci_notifier = {
|
||||
static void uncore_pci_pmus_register(void)
|
||||
{
|
||||
struct intel_uncore_type **types = uncore_pci_uncores;
|
||||
struct intel_uncore_discovery_unit *unit;
|
||||
struct intel_uncore_type *type;
|
||||
struct intel_uncore_pmu *pmu;
|
||||
struct rb_node *node;
|
||||
struct pci_dev *pdev;
|
||||
u64 box_ctl;
|
||||
int i, die;
|
||||
|
||||
for (; *types; types++) {
|
||||
type = *types;
|
||||
for (die = 0; die < __uncore_max_dies; die++) {
|
||||
for (i = 0; i < type->num_boxes; i++) {
|
||||
if (!type->box_ctls[die])
|
||||
continue;
|
||||
box_ctl = type->box_ctls[die] + type->pci_offsets[i];
|
||||
pdev = pci_get_domain_bus_and_slot(UNCORE_DISCOVERY_PCI_DOMAIN(box_ctl),
|
||||
UNCORE_DISCOVERY_PCI_BUS(box_ctl),
|
||||
UNCORE_DISCOVERY_PCI_DEVFN(box_ctl));
|
||||
if (!pdev)
|
||||
continue;
|
||||
pmu = &type->pmus[i];
|
||||
|
||||
uncore_pci_pmu_register(pdev, type, pmu, die);
|
||||
}
|
||||
for (node = rb_first(type->boxes); node; node = rb_next(node)) {
|
||||
unit = rb_entry(node, struct intel_uncore_discovery_unit, node);
|
||||
pdev = pci_get_domain_bus_and_slot(UNCORE_DISCOVERY_PCI_DOMAIN(unit->addr),
|
||||
UNCORE_DISCOVERY_PCI_BUS(unit->addr),
|
||||
UNCORE_DISCOVERY_PCI_DEVFN(unit->addr));
|
||||
|
||||
if (!pdev)
|
||||
continue;
|
||||
pmu = &type->pmus[unit->pmu_idx];
|
||||
uncore_pci_pmu_register(pdev, type, pmu, unit->die);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,6 +99,10 @@ struct intel_uncore_type {
|
||||
int (*get_topology)(struct intel_uncore_type *type);
|
||||
void (*set_mapping)(struct intel_uncore_type *type);
|
||||
void (*cleanup_mapping)(struct intel_uncore_type *type);
|
||||
/*
|
||||
* Optional callbacks for extra uncore units cleanup
|
||||
*/
|
||||
void (*cleanup_extra_boxes)(struct intel_uncore_type *type);
|
||||
};
|
||||
|
||||
#define pmu_group attr_groups[0]
|
||||
|
||||
@@ -215,8 +215,8 @@ uncore_find_unit(struct rb_root *root, unsigned int id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void uncore_find_add_unit(struct intel_uncore_discovery_unit *node,
|
||||
struct rb_root *root, u16 *num_units)
|
||||
void uncore_find_add_unit(struct intel_uncore_discovery_unit *node,
|
||||
struct rb_root *root, u16 *num_units)
|
||||
{
|
||||
struct intel_uncore_discovery_unit *unit = uncore_find_unit(root, node->id);
|
||||
|
||||
@@ -560,7 +560,7 @@ bool intel_generic_uncore_assign_hw_event(struct perf_event *event,
|
||||
if (!box->pmu->type->boxes)
|
||||
return false;
|
||||
|
||||
if (box->pci_dev || box->io_addr) {
|
||||
if (box->io_addr) {
|
||||
hwc->config_base = uncore_pci_event_ctl(box, hwc->idx);
|
||||
hwc->event_base = uncore_pci_perf_ctr(box, hwc->idx);
|
||||
return true;
|
||||
@@ -570,16 +570,28 @@ bool intel_generic_uncore_assign_hw_event(struct perf_event *event,
|
||||
if (!box_ctl)
|
||||
return false;
|
||||
|
||||
if (box->pci_dev) {
|
||||
box_ctl = UNCORE_DISCOVERY_PCI_BOX_CTRL(box_ctl);
|
||||
hwc->config_base = box_ctl + uncore_pci_event_ctl(box, hwc->idx);
|
||||
hwc->event_base = box_ctl + uncore_pci_perf_ctr(box, hwc->idx);
|
||||
return true;
|
||||
}
|
||||
|
||||
hwc->config_base = box_ctl + box->pmu->type->event_ctl + hwc->idx;
|
||||
hwc->event_base = box_ctl + box->pmu->type->perf_ctr + hwc->idx;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline int intel_pci_uncore_box_ctl(struct intel_uncore_box *box)
|
||||
{
|
||||
return UNCORE_DISCOVERY_PCI_BOX_CTRL(intel_generic_uncore_box_ctl(box));
|
||||
}
|
||||
|
||||
void intel_generic_uncore_pci_init_box(struct intel_uncore_box *box)
|
||||
{
|
||||
struct pci_dev *pdev = box->pci_dev;
|
||||
int box_ctl = uncore_pci_box_ctl(box);
|
||||
int box_ctl = intel_pci_uncore_box_ctl(box);
|
||||
|
||||
__set_bit(UNCORE_BOX_FLAG_CTL_OFFS8, &box->flags);
|
||||
pci_write_config_dword(pdev, box_ctl, GENERIC_PMON_BOX_CTL_INT);
|
||||
@@ -588,7 +600,7 @@ void intel_generic_uncore_pci_init_box(struct intel_uncore_box *box)
|
||||
void intel_generic_uncore_pci_disable_box(struct intel_uncore_box *box)
|
||||
{
|
||||
struct pci_dev *pdev = box->pci_dev;
|
||||
int box_ctl = uncore_pci_box_ctl(box);
|
||||
int box_ctl = intel_pci_uncore_box_ctl(box);
|
||||
|
||||
pci_write_config_dword(pdev, box_ctl, GENERIC_PMON_BOX_CTL_FRZ);
|
||||
}
|
||||
@@ -596,7 +608,7 @@ void intel_generic_uncore_pci_disable_box(struct intel_uncore_box *box)
|
||||
void intel_generic_uncore_pci_enable_box(struct intel_uncore_box *box)
|
||||
{
|
||||
struct pci_dev *pdev = box->pci_dev;
|
||||
int box_ctl = uncore_pci_box_ctl(box);
|
||||
int box_ctl = intel_pci_uncore_box_ctl(box);
|
||||
|
||||
pci_write_config_dword(pdev, box_ctl, 0);
|
||||
}
|
||||
@@ -748,6 +760,8 @@ static bool uncore_update_uncore_type(enum uncore_access_type type_id,
|
||||
uncore->box_ctl = (unsigned int)UNCORE_DISCOVERY_PCI_BOX_CTRL(type->box_ctrl);
|
||||
uncore->box_ctls = type->box_ctrl_die;
|
||||
uncore->pci_offsets = type->box_offset;
|
||||
uncore->boxes = &type->units;
|
||||
uncore->num_boxes = type->num_units;
|
||||
break;
|
||||
case UNCORE_ACCESS_MMIO:
|
||||
uncore->ops = &generic_uncore_mmio_ops;
|
||||
|
||||
@@ -171,3 +171,5 @@ int intel_uncore_find_discovery_unit_id(struct rb_root *units, int die,
|
||||
unsigned int pmu_idx);
|
||||
bool intel_generic_uncore_assign_hw_event(struct perf_event *event,
|
||||
struct intel_uncore_box *box);
|
||||
void uncore_find_add_unit(struct intel_uncore_discovery_unit *node,
|
||||
struct rb_root *root, u16 *num_units);
|
||||
|
||||
@@ -6200,6 +6200,24 @@ static u64 spr_upi_pci_offsets[SPR_UNCORE_UPI_NUM_BOXES] = {
|
||||
0, 0x8000, 0x10000, 0x18000
|
||||
};
|
||||
|
||||
static void spr_extra_boxes_cleanup(struct intel_uncore_type *type)
|
||||
{
|
||||
struct intel_uncore_discovery_unit *pos;
|
||||
struct rb_node *node;
|
||||
|
||||
if (!type->boxes)
|
||||
return;
|
||||
|
||||
while (!RB_EMPTY_ROOT(type->boxes)) {
|
||||
node = rb_first(type->boxes);
|
||||
pos = rb_entry(node, struct intel_uncore_discovery_unit, node);
|
||||
rb_erase(node, type->boxes);
|
||||
kfree(pos);
|
||||
}
|
||||
kfree(type->boxes);
|
||||
type->boxes = NULL;
|
||||
}
|
||||
|
||||
static struct intel_uncore_type spr_uncore_upi = {
|
||||
.event_mask = SNBEP_PMON_RAW_EVENT_MASK,
|
||||
.event_mask_ext = SPR_RAW_EVENT_MASK_EXT,
|
||||
@@ -6214,10 +6232,11 @@ static struct intel_uncore_type spr_uncore_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,
|
||||
.perf_ctr = ICX_UPI_PCI_PMON_CTR0 - ICX_UPI_PCI_PMON_BOX_CTL,
|
||||
.event_ctl = ICX_UPI_PCI_PMON_CTL0 - ICX_UPI_PCI_PMON_BOX_CTL,
|
||||
.box_ctl = ICX_UPI_PCI_PMON_BOX_CTL,
|
||||
.pci_offsets = spr_upi_pci_offsets,
|
||||
.cleanup_extra_boxes = spr_extra_boxes_cleanup,
|
||||
};
|
||||
|
||||
static struct intel_uncore_type spr_uncore_m3upi = {
|
||||
@@ -6227,11 +6246,12 @@ static struct intel_uncore_type spr_uncore_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,
|
||||
.perf_ctr = ICX_M3UPI_PCI_PMON_CTR0 - ICX_M3UPI_PCI_PMON_BOX_CTL,
|
||||
.event_ctl = ICX_M3UPI_PCI_PMON_CTL0 - ICX_M3UPI_PCI_PMON_BOX_CTL,
|
||||
.box_ctl = ICX_M3UPI_PCI_PMON_BOX_CTL,
|
||||
.pci_offsets = spr_upi_pci_offsets,
|
||||
.constraints = icx_uncore_m3upi_constraints,
|
||||
.cleanup_extra_boxes = spr_extra_boxes_cleanup,
|
||||
};
|
||||
|
||||
enum perf_uncore_spr_iio_freerunning_type_id {
|
||||
@@ -6518,10 +6538,11 @@ void spr_uncore_cpu_init(void)
|
||||
|
||||
static void spr_update_device_location(int type_id)
|
||||
{
|
||||
struct intel_uncore_discovery_unit *unit;
|
||||
struct intel_uncore_type *type;
|
||||
struct pci_dev *dev = NULL;
|
||||
struct rb_root *root;
|
||||
u32 device, devfn;
|
||||
u64 *ctls;
|
||||
int die;
|
||||
|
||||
if (type_id == UNCORE_SPR_UPI) {
|
||||
@@ -6535,27 +6556,35 @@ static void spr_update_device_location(int type_id)
|
||||
} else
|
||||
return;
|
||||
|
||||
ctls = kcalloc(__uncore_max_dies, sizeof(u64), GFP_KERNEL);
|
||||
if (!ctls) {
|
||||
root = kzalloc(sizeof(struct rb_root), GFP_KERNEL);
|
||||
if (!root) {
|
||||
type->num_boxes = 0;
|
||||
return;
|
||||
}
|
||||
*root = RB_ROOT;
|
||||
|
||||
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;
|
||||
unit = kzalloc(sizeof(*unit), GFP_KERNEL);
|
||||
if (!unit)
|
||||
continue;
|
||||
unit->die = die;
|
||||
unit->id = PCI_SLOT(dev->devfn) - PCI_SLOT(devfn);
|
||||
unit->addr = 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;
|
||||
|
||||
unit->pmu_idx = unit->id;
|
||||
|
||||
uncore_find_add_unit(unit, root, NULL);
|
||||
}
|
||||
|
||||
type->box_ctls = ctls;
|
||||
type->boxes = root;
|
||||
}
|
||||
|
||||
int spr_uncore_pci_init(void)
|
||||
|
||||
Reference in New Issue
Block a user