mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-10 23:20:05 +00:00
perf/x86/uncore: Apply the unit control RB tree to PCI uncore units
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 65248a9a9ee1 ("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
This commit is contained in:
parent
b1d9ea2e1c
commit
f76a842044
@ -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);
|
||||
|
@ -6199,6 +6199,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,
|
||||
@ -6213,10 +6231,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 = {
|
||||
@ -6226,11 +6245,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 {
|
||||
@ -6517,10 +6537,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) {
|
||||
@ -6534,27 +6555,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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user