hns3_pmu
struct hns3_pmu *hns3_pmu,
return hns3_pmu_valid_bdf(hns3_pmu, bdf);
struct hns3_pmu *hns3_pmu)
pci_err(hns3_pmu->pdev, "Invalid pmu event\n");
return hns3_pmu_set_func_mode(event, hns3_pmu);
return hns3_pmu_set_func_queue_mode(event, hns3_pmu);
if (hns3_pmu_is_enabled_func_intr_mode(event, hns3_pmu, pmu_event)) {
struct hns3_pmu *hns3_pmu = to_hns3_pmu(event->pmu);
hns3_pmu_writel(hns3_pmu, HNS3_PMU_REG_EVENT_CTRL_LOW, idx, val);
hns3_pmu_writel(hns3_pmu, HNS3_PMU_REG_EVENT_CTRL_HIGH, idx, val);
hns3_pmu_set_qid_para(hns3_pmu, idx, bdf, queue_id);
static void hns3_pmu_enable_counter(struct hns3_pmu *hns3_pmu,
val = hns3_pmu_readl(hns3_pmu, HNS3_PMU_REG_EVENT_CTRL_LOW, idx);
hns3_pmu_writel(hns3_pmu, HNS3_PMU_REG_EVENT_CTRL_LOW, idx, val);
static void hns3_pmu_disable_counter(struct hns3_pmu *hns3_pmu,
val = hns3_pmu_readl(hns3_pmu, HNS3_PMU_REG_EVENT_CTRL_LOW, idx);
hns3_pmu_writel(hns3_pmu, HNS3_PMU_REG_EVENT_CTRL_LOW, idx, val);
static void hns3_pmu_enable_intr(struct hns3_pmu *hns3_pmu,
val = hns3_pmu_readl(hns3_pmu, HNS3_PMU_REG_EVENT_INTR_MASK, idx);
hns3_pmu_writel(hns3_pmu, HNS3_PMU_REG_EVENT_INTR_MASK, idx, val);
static void hns3_pmu_disable_intr(struct hns3_pmu *hns3_pmu,
val = hns3_pmu_readl(hns3_pmu, HNS3_PMU_REG_EVENT_INTR_MASK, idx);
hns3_pmu_writel(hns3_pmu, HNS3_PMU_REG_EVENT_INTR_MASK, idx, val);
static void hns3_pmu_clear_intr_status(struct hns3_pmu *hns3_pmu, u32 idx)
val = hns3_pmu_readl(hns3_pmu, HNS3_PMU_REG_EVENT_CTRL_LOW, idx);
hns3_pmu_writel(hns3_pmu, HNS3_PMU_REG_EVENT_CTRL_LOW, idx, val);
val = hns3_pmu_readl(hns3_pmu, HNS3_PMU_REG_EVENT_CTRL_LOW, idx);
hns3_pmu_writel(hns3_pmu, HNS3_PMU_REG_EVENT_CTRL_LOW, idx, val);
struct hns3_pmu *hns3_pmu = to_hns3_pmu(event->pmu);
return hns3_pmu_readq(hns3_pmu, event->hw.event_base, event->hw.idx);
struct hns3_pmu *hns3_pmu = to_hns3_pmu(event->pmu);
hns3_pmu_writeq(hns3_pmu, HNS3_PMU_REG_EVENT_COUNTER, idx, value);
hns3_pmu_writeq(hns3_pmu, HNS3_PMU_REG_EVENT_EXT_COUNTER, idx, value);
struct hns3_pmu *hns3_pmu = to_hns3_pmu(event->pmu);
event->cpu = hns3_pmu->on_cpu;
idx = hns3_pmu_get_event_idx(hns3_pmu);
pci_err(hns3_pmu->pdev, "Up to %u events are supported!\n",
ret = hns3_pmu_select_filter_mode(event, hns3_pmu);
pci_err(hns3_pmu->pdev, "Invalid filter, ret = %d.\n", ret);
pci_err(hns3_pmu->pdev, "Invalid event group.\n");
struct hns3_pmu *hns3_pmu = to_hns3_pmu(event->pmu);
hns3_pmu_enable_intr(hns3_pmu, hwc);
hns3_pmu_enable_counter(hns3_pmu, hwc);
struct hns3_pmu *hns3_pmu = to_hns3_pmu(event->pmu);
hns3_pmu_disable_counter(hns3_pmu, hwc);
hns3_pmu_disable_intr(hns3_pmu, hwc);
struct hns3_pmu *hns3_pmu = to_hns3_pmu(event->pmu);
idx = hns3_pmu_find_related_event_idx(hns3_pmu, event);
idx = hns3_pmu_get_event_idx(hns3_pmu);
hns3_pmu->hw_events[idx] = event;
struct hns3_pmu *hns3_pmu = to_hns3_pmu(event->pmu);
hns3_pmu->hw_events[hwc->idx] = NULL;
struct hns3_pmu *hns3_pmu = to_hns3_pmu(pmu);
val = readl(hns3_pmu->base + HNS3_PMU_REG_GLOBAL_CTRL);
writel(val, hns3_pmu->base + HNS3_PMU_REG_GLOBAL_CTRL);
struct hns3_pmu *hns3_pmu = to_hns3_pmu(pmu);
val = readl(hns3_pmu->base + HNS3_PMU_REG_GLOBAL_CTRL);
writel(val, hns3_pmu->base + HNS3_PMU_REG_GLOBAL_CTRL);
static int hns3_pmu_alloc_pmu(struct pci_dev *pdev, struct hns3_pmu *hns3_pmu)
hns3_pmu->base = pcim_iomap_table(pdev)[BAR_2];
if (!hns3_pmu->base) {
hns3_pmu->hw_clk_freq = readl(hns3_pmu->base + HNS3_PMU_REG_CLOCK_FREQ);
val = readl(hns3_pmu->base + HNS3_PMU_REG_BDF);
hns3_pmu->bdf_min = val & 0xffff;
hns3_pmu->bdf_max = val >> 16;
val = readl(hns3_pmu->base + HNS3_PMU_REG_DEVICE_ID);
hns3_pmu->pdev = pdev;
hns3_pmu->on_cpu = -1;
hns3_pmu->identifier = readl(hns3_pmu->base + HNS3_PMU_REG_VERSION);
hns3_pmu->pmu = (struct pmu) {
struct hns3_pmu *hns3_pmu = data;
intr_status = hns3_pmu_readl(hns3_pmu,
hns3_pmu_clear_intr_status(hns3_pmu, idx);
struct hns3_pmu *hns3_pmu;
hns3_pmu = hlist_entry_safe(node, struct hns3_pmu, node);
if (!hns3_pmu)
if (hns3_pmu->on_cpu == -1) {
hns3_pmu->on_cpu = cpu;
irq_set_affinity(hns3_pmu->irq, cpumask_of(cpu));
struct hns3_pmu *hns3_pmu;
hns3_pmu = hlist_entry_safe(node, struct hns3_pmu, node);
if (!hns3_pmu)
if (hns3_pmu->on_cpu != cpu)
perf_pmu_migrate_context(&hns3_pmu->pmu, cpu, target);
hns3_pmu->on_cpu = target;
irq_set_affinity(hns3_pmu->irq, cpumask_of(target));
struct hns3_pmu *hns3_pmu)
hns3_pmu->pmu.name, hns3_pmu);
hns3_pmu->irq = irq;
static int hns3_pmu_init_pmu(struct pci_dev *pdev, struct hns3_pmu *hns3_pmu)
ret = hns3_pmu_alloc_pmu(pdev, hns3_pmu);
ret = hns3_pmu_irq_register(pdev, hns3_pmu);
&hns3_pmu->node);
ret = perf_pmu_register(&hns3_pmu->pmu, hns3_pmu->pmu.name, -1);
&hns3_pmu->node);
struct hns3_pmu *hns3_pmu = pci_get_drvdata(pdev);
perf_pmu_unregister(&hns3_pmu->pmu);
&hns3_pmu->node);
struct hns3_pmu *hns3_pmu;
hns3_pmu = devm_kzalloc(&pdev->dev, sizeof(*hns3_pmu), GFP_KERNEL);
if (!hns3_pmu)
ret = hns3_pmu_init_pmu(pdev, hns3_pmu);
pci_set_drvdata(pdev, hns3_pmu);
#define to_hns3_pmu(p) (container_of((p), struct hns3_pmu, pmu))
struct hns3_pmu *hns3_pmu = to_hns3_pmu(dev_get_drvdata(dev));
return sysfs_emit(buf, "0x%x\n", hns3_pmu->identifier);
struct hns3_pmu *hns3_pmu = to_hns3_pmu(dev_get_drvdata(dev));
return sysfs_emit(buf, "%d\n", hns3_pmu->on_cpu);
struct hns3_pmu *hns3_pmu = to_hns3_pmu(dev_get_drvdata(dev));
u16 bdf = hns3_pmu->bdf_min;
struct hns3_pmu *hns3_pmu = to_hns3_pmu(dev_get_drvdata(dev));
u16 bdf = hns3_pmu->bdf_max;
struct hns3_pmu *hns3_pmu = to_hns3_pmu(dev_get_drvdata(dev));
return sysfs_emit(buf, "%u\n", hns3_pmu->hw_clk_freq);
static u32 hns3_pmu_readl(struct hns3_pmu *hns3_pmu, u32 reg_offset, u32 idx)
return readl(hns3_pmu->base + offset);
static void hns3_pmu_writel(struct hns3_pmu *hns3_pmu, u32 reg_offset, u32 idx,
writel(val, hns3_pmu->base + offset);
static u64 hns3_pmu_readq(struct hns3_pmu *hns3_pmu, u32 reg_offset, u32 idx)
return readq(hns3_pmu->base + offset);
static void hns3_pmu_writeq(struct hns3_pmu *hns3_pmu, u32 reg_offset, u32 idx,
writeq(val, hns3_pmu->base + offset);
static int hns3_pmu_find_related_event_idx(struct hns3_pmu *hns3_pmu,
sibling = hns3_pmu->hw_events[idx];
static int hns3_pmu_get_event_idx(struct hns3_pmu *hns3_pmu)
if (!hns3_pmu->hw_events[idx])
static bool hns3_pmu_valid_bdf(struct hns3_pmu *hns3_pmu, u16 bdf)
if (bdf < hns3_pmu->bdf_min || bdf > hns3_pmu->bdf_max) {
pci_err(hns3_pmu->pdev, "Invalid EP device: %#x!\n", bdf);
pdev = pci_get_domain_bus_and_slot(pci_domain_nr(hns3_pmu->pdev->bus),
pci_err(hns3_pmu->pdev, "Nonexistent EP device: %#x!\n", bdf);
static void hns3_pmu_set_qid_para(struct hns3_pmu *hns3_pmu, u32 idx, u16 bdf,
hns3_pmu_writel(hns3_pmu, HNS3_PMU_REG_EVENT_QID_PARA, idx, val);
static bool hns3_pmu_qid_req_start(struct hns3_pmu *hns3_pmu, u32 idx)
hns3_pmu_writel(hns3_pmu, HNS3_PMU_REG_EVENT_QID_CTRL, idx,
err = readl_poll_timeout(hns3_pmu->base + reg_qid_ctrl, val,
pci_err(hns3_pmu->pdev, "QID request timeout!\n");
hns3_pmu_writel(hns3_pmu, HNS3_PMU_REG_EVENT_QID_CTRL, idx, 0);
static bool hns3_pmu_valid_queue(struct hns3_pmu *hns3_pmu, u32 idx, u16 bdf,
hns3_pmu_set_qid_para(hns3_pmu, idx, bdf, queue);
return hns3_pmu_qid_req_start(hns3_pmu, idx);
struct hns3_pmu *hns3_pmu)
if (!hns3_pmu_valid_bdf(hns3_pmu, bdf))
struct hns3_pmu *hns3_pmu)
if (!hns3_pmu_valid_bdf(hns3_pmu, bdf))
if (!hns3_pmu_valid_queue(hns3_pmu, hwc->idx, bdf, queue_id)) {
pci_err(hns3_pmu->pdev, "Invalid queue: %u\n", queue_id);