0001
0002
0003
0004
0005
0006
0007 #include <linux/init.h>
0008 #include <linux/io.h>
0009 #include <linux/module.h>
0010 #include <linux/of.h>
0011 #include <linux/of_address.h>
0012 #include <linux/of_device.h>
0013 #include <linux/perf_event.h>
0014 #include <linux/hrtimer.h>
0015
0016
0017 #define DDRC_PERF_CNT_OP_MODE_CTRL 0x8020
0018 #define OP_MODE_CTRL_VAL_MANNUAL 0x1
0019
0020
0021 #define DDRC_PERF_CNT_START_OP_CTRL 0x8028
0022 #define START_OP_CTRL_VAL_START 0x1ULL
0023 #define START_OP_CTRL_VAL_ACTIVE 0x2
0024
0025
0026 #define DDRC_PERF_CNT_END_OP_CTRL 0x8030
0027 #define END_OP_CTRL_VAL_END 0x1ULL
0028
0029
0030 #define DDRC_PERF_CNT_END_STATUS 0x8038
0031 #define END_STATUS_VAL_END_TIMER_MODE_END 0x1
0032
0033
0034 #define DDRC_PERF_CFG_BASE 0x8040
0035
0036
0037 #define DDRC_PERF_NUM_GEN_COUNTERS 8
0038 #define DDRC_PERF_NUM_FIX_COUNTERS 2
0039 #define DDRC_PERF_READ_COUNTER_IDX DDRC_PERF_NUM_GEN_COUNTERS
0040 #define DDRC_PERF_WRITE_COUNTER_IDX (DDRC_PERF_NUM_GEN_COUNTERS + 1)
0041 #define DDRC_PERF_NUM_COUNTERS (DDRC_PERF_NUM_GEN_COUNTERS + \
0042 DDRC_PERF_NUM_FIX_COUNTERS)
0043
0044
0045 #define DDRC_PERF_CFG(n) (DDRC_PERF_CFG_BASE + 8 * (n))
0046 #define EVENT_ENABLE BIT_ULL(63)
0047
0048
0049 #define EVENT_DDR_READS 101
0050 #define EVENT_DDR_WRITES 100
0051
0052
0053
0054
0055
0056
0057 #define EVENT_OP_IS_ZQLATCH 55
0058 #define EVENT_OP_IS_ZQSTART 54
0059 #define EVENT_OP_IS_TCR_MRR 53
0060 #define EVENT_OP_IS_DQSOSC_MRR 52
0061 #define EVENT_OP_IS_DQSOSC_MPC 51
0062 #define EVENT_VISIBLE_WIN_LIMIT_REACHED_WR 50
0063 #define EVENT_VISIBLE_WIN_LIMIT_REACHED_RD 49
0064 #define EVENT_BSM_STARVATION 48
0065 #define EVENT_BSM_ALLOC 47
0066 #define EVENT_LPR_REQ_WITH_NOCREDIT 46
0067 #define EVENT_HPR_REQ_WITH_NOCREDIT 45
0068 #define EVENT_OP_IS_ZQCS 44
0069 #define EVENT_OP_IS_ZQCL 43
0070 #define EVENT_OP_IS_LOAD_MODE 42
0071 #define EVENT_OP_IS_SPEC_REF 41
0072 #define EVENT_OP_IS_CRIT_REF 40
0073 #define EVENT_OP_IS_REFRESH 39
0074 #define EVENT_OP_IS_ENTER_MPSM 35
0075 #define EVENT_OP_IS_ENTER_POWERDOWN 31
0076 #define EVENT_OP_IS_ENTER_SELFREF 27
0077 #define EVENT_WAW_HAZARD 26
0078 #define EVENT_RAW_HAZARD 25
0079 #define EVENT_WAR_HAZARD 24
0080 #define EVENT_WRITE_COMBINE 23
0081 #define EVENT_RDWR_TRANSITIONS 22
0082 #define EVENT_PRECHARGE_FOR_OTHER 21
0083 #define EVENT_PRECHARGE_FOR_RDWR 20
0084 #define EVENT_OP_IS_PRECHARGE 19
0085 #define EVENT_OP_IS_MWR 18
0086 #define EVENT_OP_IS_WR 17
0087 #define EVENT_OP_IS_RD 16
0088 #define EVENT_OP_IS_RD_ACTIVATE 15
0089 #define EVENT_OP_IS_RD_OR_WR 14
0090 #define EVENT_OP_IS_ACTIVATE 13
0091 #define EVENT_WR_XACT_WHEN_CRITICAL 12
0092 #define EVENT_LPR_XACT_WHEN_CRITICAL 11
0093 #define EVENT_HPR_XACT_WHEN_CRITICAL 10
0094 #define EVENT_DFI_RD_DATA_CYCLES 9
0095 #define EVENT_DFI_WR_DATA_CYCLES 8
0096 #define EVENT_ACT_BYPASS 7
0097 #define EVENT_READ_BYPASS 6
0098 #define EVENT_HIF_HI_PRI_RD 5
0099 #define EVENT_HIF_RMW 4
0100 #define EVENT_HIF_RD 3
0101 #define EVENT_HIF_WR 2
0102 #define EVENT_HIF_RD_OR_WR 1
0103
0104
0105 #define DDRC_PERF_CNT_VALUE_BASE 0x8080
0106 #define DDRC_PERF_CNT_VALUE(n) (DDRC_PERF_CNT_VALUE_BASE + 8 * (n))
0107
0108
0109 #define DDRC_PERF_CNT_FREERUN_EN 0x80C0
0110 #define DDRC_PERF_FREERUN_WRITE_EN 0x1
0111 #define DDRC_PERF_FREERUN_READ_EN 0x2
0112
0113
0114 #define DDRC_PERF_CNT_FREERUN_CTRL 0x80C8
0115 #define DDRC_FREERUN_WRITE_CNT_CLR 0x1
0116 #define DDRC_FREERUN_READ_CNT_CLR 0x2
0117
0118
0119 #define DDRC_PERF_CNT_VALUE_WR_OP 0x80D0
0120 #define DDRC_PERF_CNT_VALUE_RD_OP 0x80D8
0121 #define DDRC_PERF_CNT_VALUE_OVERFLOW BIT_ULL(48)
0122 #define DDRC_PERF_CNT_MAX_VALUE GENMASK_ULL(48, 0)
0123
0124 struct cn10k_ddr_pmu {
0125 struct pmu pmu;
0126 void __iomem *base;
0127 unsigned int cpu;
0128 struct device *dev;
0129 int active_events;
0130 struct perf_event *events[DDRC_PERF_NUM_COUNTERS];
0131 struct hrtimer hrtimer;
0132 struct hlist_node node;
0133 };
0134
0135 #define to_cn10k_ddr_pmu(p) container_of(p, struct cn10k_ddr_pmu, pmu)
0136
0137 static ssize_t cn10k_ddr_pmu_event_show(struct device *dev,
0138 struct device_attribute *attr,
0139 char *page)
0140 {
0141 struct perf_pmu_events_attr *pmu_attr;
0142
0143 pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
0144 return sysfs_emit(page, "event=0x%02llx\n", pmu_attr->id);
0145
0146 }
0147
0148 #define CN10K_DDR_PMU_EVENT_ATTR(_name, _id) \
0149 PMU_EVENT_ATTR_ID(_name, cn10k_ddr_pmu_event_show, _id)
0150
0151 static struct attribute *cn10k_ddr_perf_events_attrs[] = {
0152 CN10K_DDR_PMU_EVENT_ATTR(ddr_hif_rd_or_wr_access, EVENT_HIF_RD_OR_WR),
0153 CN10K_DDR_PMU_EVENT_ATTR(ddr_hif_wr_access, EVENT_HIF_WR),
0154 CN10K_DDR_PMU_EVENT_ATTR(ddr_hif_rd_access, EVENT_HIF_RD),
0155 CN10K_DDR_PMU_EVENT_ATTR(ddr_hif_rmw_access, EVENT_HIF_RMW),
0156 CN10K_DDR_PMU_EVENT_ATTR(ddr_hif_pri_rdaccess, EVENT_HIF_HI_PRI_RD),
0157 CN10K_DDR_PMU_EVENT_ATTR(ddr_rd_bypass_access, EVENT_READ_BYPASS),
0158 CN10K_DDR_PMU_EVENT_ATTR(ddr_act_bypass_access, EVENT_ACT_BYPASS),
0159 CN10K_DDR_PMU_EVENT_ATTR(ddr_dif_wr_data_access, EVENT_DFI_WR_DATA_CYCLES),
0160 CN10K_DDR_PMU_EVENT_ATTR(ddr_dif_rd_data_access, EVENT_DFI_RD_DATA_CYCLES),
0161 CN10K_DDR_PMU_EVENT_ATTR(ddr_hpri_sched_rd_crit_access,
0162 EVENT_HPR_XACT_WHEN_CRITICAL),
0163 CN10K_DDR_PMU_EVENT_ATTR(ddr_lpri_sched_rd_crit_access,
0164 EVENT_LPR_XACT_WHEN_CRITICAL),
0165 CN10K_DDR_PMU_EVENT_ATTR(ddr_wr_trxn_crit_access,
0166 EVENT_WR_XACT_WHEN_CRITICAL),
0167 CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_active_access, EVENT_OP_IS_ACTIVATE),
0168 CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_rd_or_wr_access, EVENT_OP_IS_RD_OR_WR),
0169 CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_rd_active_access, EVENT_OP_IS_RD_ACTIVATE),
0170 CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_read, EVENT_OP_IS_RD),
0171 CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_write, EVENT_OP_IS_WR),
0172 CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_mwr, EVENT_OP_IS_MWR),
0173 CN10K_DDR_PMU_EVENT_ATTR(ddr_precharge, EVENT_OP_IS_PRECHARGE),
0174 CN10K_DDR_PMU_EVENT_ATTR(ddr_precharge_for_rdwr, EVENT_PRECHARGE_FOR_RDWR),
0175 CN10K_DDR_PMU_EVENT_ATTR(ddr_precharge_for_other,
0176 EVENT_PRECHARGE_FOR_OTHER),
0177 CN10K_DDR_PMU_EVENT_ATTR(ddr_rdwr_transitions, EVENT_RDWR_TRANSITIONS),
0178 CN10K_DDR_PMU_EVENT_ATTR(ddr_write_combine, EVENT_WRITE_COMBINE),
0179 CN10K_DDR_PMU_EVENT_ATTR(ddr_war_hazard, EVENT_WAR_HAZARD),
0180 CN10K_DDR_PMU_EVENT_ATTR(ddr_raw_hazard, EVENT_RAW_HAZARD),
0181 CN10K_DDR_PMU_EVENT_ATTR(ddr_waw_hazard, EVENT_WAW_HAZARD),
0182 CN10K_DDR_PMU_EVENT_ATTR(ddr_enter_selfref, EVENT_OP_IS_ENTER_SELFREF),
0183 CN10K_DDR_PMU_EVENT_ATTR(ddr_enter_powerdown, EVENT_OP_IS_ENTER_POWERDOWN),
0184 CN10K_DDR_PMU_EVENT_ATTR(ddr_enter_mpsm, EVENT_OP_IS_ENTER_MPSM),
0185 CN10K_DDR_PMU_EVENT_ATTR(ddr_refresh, EVENT_OP_IS_REFRESH),
0186 CN10K_DDR_PMU_EVENT_ATTR(ddr_crit_ref, EVENT_OP_IS_CRIT_REF),
0187 CN10K_DDR_PMU_EVENT_ATTR(ddr_spec_ref, EVENT_OP_IS_SPEC_REF),
0188 CN10K_DDR_PMU_EVENT_ATTR(ddr_load_mode, EVENT_OP_IS_LOAD_MODE),
0189 CN10K_DDR_PMU_EVENT_ATTR(ddr_zqcl, EVENT_OP_IS_ZQCL),
0190 CN10K_DDR_PMU_EVENT_ATTR(ddr_cam_wr_access, EVENT_OP_IS_ZQCS),
0191 CN10K_DDR_PMU_EVENT_ATTR(ddr_hpr_req_with_nocredit,
0192 EVENT_HPR_REQ_WITH_NOCREDIT),
0193 CN10K_DDR_PMU_EVENT_ATTR(ddr_lpr_req_with_nocredit,
0194 EVENT_LPR_REQ_WITH_NOCREDIT),
0195 CN10K_DDR_PMU_EVENT_ATTR(ddr_bsm_alloc, EVENT_BSM_ALLOC),
0196 CN10K_DDR_PMU_EVENT_ATTR(ddr_bsm_starvation, EVENT_BSM_STARVATION),
0197 CN10K_DDR_PMU_EVENT_ATTR(ddr_win_limit_reached_rd,
0198 EVENT_VISIBLE_WIN_LIMIT_REACHED_RD),
0199 CN10K_DDR_PMU_EVENT_ATTR(ddr_win_limit_reached_wr,
0200 EVENT_VISIBLE_WIN_LIMIT_REACHED_WR),
0201 CN10K_DDR_PMU_EVENT_ATTR(ddr_dqsosc_mpc, EVENT_OP_IS_DQSOSC_MPC),
0202 CN10K_DDR_PMU_EVENT_ATTR(ddr_dqsosc_mrr, EVENT_OP_IS_DQSOSC_MRR),
0203 CN10K_DDR_PMU_EVENT_ATTR(ddr_tcr_mrr, EVENT_OP_IS_TCR_MRR),
0204 CN10K_DDR_PMU_EVENT_ATTR(ddr_zqstart, EVENT_OP_IS_ZQSTART),
0205 CN10K_DDR_PMU_EVENT_ATTR(ddr_zqlatch, EVENT_OP_IS_ZQLATCH),
0206
0207 CN10K_DDR_PMU_EVENT_ATTR(ddr_ddr_reads, EVENT_DDR_READS),
0208 CN10K_DDR_PMU_EVENT_ATTR(ddr_ddr_writes, EVENT_DDR_WRITES),
0209 NULL
0210 };
0211
0212 static struct attribute_group cn10k_ddr_perf_events_attr_group = {
0213 .name = "events",
0214 .attrs = cn10k_ddr_perf_events_attrs,
0215 };
0216
0217 PMU_FORMAT_ATTR(event, "config:0-8");
0218
0219 static struct attribute *cn10k_ddr_perf_format_attrs[] = {
0220 &format_attr_event.attr,
0221 NULL,
0222 };
0223
0224 static struct attribute_group cn10k_ddr_perf_format_attr_group = {
0225 .name = "format",
0226 .attrs = cn10k_ddr_perf_format_attrs,
0227 };
0228
0229 static ssize_t cn10k_ddr_perf_cpumask_show(struct device *dev,
0230 struct device_attribute *attr,
0231 char *buf)
0232 {
0233 struct cn10k_ddr_pmu *pmu = dev_get_drvdata(dev);
0234
0235 return cpumap_print_to_pagebuf(true, buf, cpumask_of(pmu->cpu));
0236 }
0237
0238 static struct device_attribute cn10k_ddr_perf_cpumask_attr =
0239 __ATTR(cpumask, 0444, cn10k_ddr_perf_cpumask_show, NULL);
0240
0241 static struct attribute *cn10k_ddr_perf_cpumask_attrs[] = {
0242 &cn10k_ddr_perf_cpumask_attr.attr,
0243 NULL,
0244 };
0245
0246 static struct attribute_group cn10k_ddr_perf_cpumask_attr_group = {
0247 .attrs = cn10k_ddr_perf_cpumask_attrs,
0248 };
0249
0250 static const struct attribute_group *cn10k_attr_groups[] = {
0251 &cn10k_ddr_perf_events_attr_group,
0252 &cn10k_ddr_perf_format_attr_group,
0253 &cn10k_ddr_perf_cpumask_attr_group,
0254 NULL,
0255 };
0256
0257
0258
0259
0260
0261 static unsigned long cn10k_ddr_pmu_poll_period_sec = 100;
0262 module_param_named(poll_period_sec, cn10k_ddr_pmu_poll_period_sec, ulong, 0644);
0263
0264 static ktime_t cn10k_ddr_pmu_timer_period(void)
0265 {
0266 return ms_to_ktime((u64)cn10k_ddr_pmu_poll_period_sec * USEC_PER_SEC);
0267 }
0268
0269 static int ddr_perf_get_event_bitmap(int eventid, u64 *event_bitmap)
0270 {
0271 switch (eventid) {
0272 case EVENT_HIF_RD_OR_WR ... EVENT_WAW_HAZARD:
0273 case EVENT_OP_IS_REFRESH ... EVENT_OP_IS_ZQLATCH:
0274 *event_bitmap = (1ULL << (eventid - 1));
0275 break;
0276 case EVENT_OP_IS_ENTER_SELFREF:
0277 case EVENT_OP_IS_ENTER_POWERDOWN:
0278 case EVENT_OP_IS_ENTER_MPSM:
0279 *event_bitmap = (0xFULL << (eventid - 1));
0280 break;
0281 default:
0282 pr_err("%s Invalid eventid %d\n", __func__, eventid);
0283 return -EINVAL;
0284 }
0285
0286 return 0;
0287 }
0288
0289 static int cn10k_ddr_perf_alloc_counter(struct cn10k_ddr_pmu *pmu,
0290 struct perf_event *event)
0291 {
0292 u8 config = event->attr.config;
0293 int i;
0294
0295
0296 if (config == EVENT_DDR_READS) {
0297 pmu->events[DDRC_PERF_READ_COUNTER_IDX] = event;
0298 return DDRC_PERF_READ_COUNTER_IDX;
0299 }
0300
0301
0302 if (config == EVENT_DDR_WRITES) {
0303 pmu->events[DDRC_PERF_WRITE_COUNTER_IDX] = event;
0304 return DDRC_PERF_WRITE_COUNTER_IDX;
0305 }
0306
0307
0308 for (i = 0; i < DDRC_PERF_NUM_GEN_COUNTERS; i++) {
0309 if (pmu->events[i] == NULL) {
0310 pmu->events[i] = event;
0311 return i;
0312 }
0313 }
0314
0315 return -ENOENT;
0316 }
0317
0318 static void cn10k_ddr_perf_free_counter(struct cn10k_ddr_pmu *pmu, int counter)
0319 {
0320 pmu->events[counter] = NULL;
0321 }
0322
0323 static int cn10k_ddr_perf_event_init(struct perf_event *event)
0324 {
0325 struct cn10k_ddr_pmu *pmu = to_cn10k_ddr_pmu(event->pmu);
0326 struct hw_perf_event *hwc = &event->hw;
0327
0328 if (event->attr.type != event->pmu->type)
0329 return -ENOENT;
0330
0331 if (is_sampling_event(event)) {
0332 dev_info(pmu->dev, "Sampling not supported!\n");
0333 return -EOPNOTSUPP;
0334 }
0335
0336 if (event->cpu < 0) {
0337 dev_warn(pmu->dev, "Can't provide per-task data!\n");
0338 return -EOPNOTSUPP;
0339 }
0340
0341
0342 if (event->group_leader->pmu != event->pmu &&
0343 !is_software_event(event->group_leader))
0344 return -EINVAL;
0345
0346
0347
0348
0349 event->cpu = pmu->cpu;
0350 hwc->idx = -1;
0351 return 0;
0352 }
0353
0354 static void cn10k_ddr_perf_counter_enable(struct cn10k_ddr_pmu *pmu,
0355 int counter, bool enable)
0356 {
0357 u32 reg;
0358 u64 val;
0359
0360 if (counter > DDRC_PERF_NUM_COUNTERS) {
0361 pr_err("Error: unsupported counter %d\n", counter);
0362 return;
0363 }
0364
0365 if (counter < DDRC_PERF_NUM_GEN_COUNTERS) {
0366 reg = DDRC_PERF_CFG(counter);
0367 val = readq_relaxed(pmu->base + reg);
0368
0369 if (enable)
0370 val |= EVENT_ENABLE;
0371 else
0372 val &= ~EVENT_ENABLE;
0373
0374 writeq_relaxed(val, pmu->base + reg);
0375 } else {
0376 val = readq_relaxed(pmu->base + DDRC_PERF_CNT_FREERUN_EN);
0377 if (enable) {
0378 if (counter == DDRC_PERF_READ_COUNTER_IDX)
0379 val |= DDRC_PERF_FREERUN_READ_EN;
0380 else
0381 val |= DDRC_PERF_FREERUN_WRITE_EN;
0382 } else {
0383 if (counter == DDRC_PERF_READ_COUNTER_IDX)
0384 val &= ~DDRC_PERF_FREERUN_READ_EN;
0385 else
0386 val &= ~DDRC_PERF_FREERUN_WRITE_EN;
0387 }
0388 writeq_relaxed(val, pmu->base + DDRC_PERF_CNT_FREERUN_EN);
0389 }
0390 }
0391
0392 static u64 cn10k_ddr_perf_read_counter(struct cn10k_ddr_pmu *pmu, int counter)
0393 {
0394 u64 val;
0395
0396 if (counter == DDRC_PERF_READ_COUNTER_IDX)
0397 return readq_relaxed(pmu->base + DDRC_PERF_CNT_VALUE_RD_OP);
0398
0399 if (counter == DDRC_PERF_WRITE_COUNTER_IDX)
0400 return readq_relaxed(pmu->base + DDRC_PERF_CNT_VALUE_WR_OP);
0401
0402 val = readq_relaxed(pmu->base + DDRC_PERF_CNT_VALUE(counter));
0403 return val;
0404 }
0405
0406 static void cn10k_ddr_perf_event_update(struct perf_event *event)
0407 {
0408 struct cn10k_ddr_pmu *pmu = to_cn10k_ddr_pmu(event->pmu);
0409 struct hw_perf_event *hwc = &event->hw;
0410 u64 prev_count, new_count, mask;
0411
0412 do {
0413 prev_count = local64_read(&hwc->prev_count);
0414 new_count = cn10k_ddr_perf_read_counter(pmu, hwc->idx);
0415 } while (local64_xchg(&hwc->prev_count, new_count) != prev_count);
0416
0417 mask = DDRC_PERF_CNT_MAX_VALUE;
0418
0419 local64_add((new_count - prev_count) & mask, &event->count);
0420 }
0421
0422 static void cn10k_ddr_perf_event_start(struct perf_event *event, int flags)
0423 {
0424 struct cn10k_ddr_pmu *pmu = to_cn10k_ddr_pmu(event->pmu);
0425 struct hw_perf_event *hwc = &event->hw;
0426 int counter = hwc->idx;
0427
0428 local64_set(&hwc->prev_count, 0);
0429
0430 cn10k_ddr_perf_counter_enable(pmu, counter, true);
0431
0432 hwc->state = 0;
0433 }
0434
0435 static int cn10k_ddr_perf_event_add(struct perf_event *event, int flags)
0436 {
0437 struct cn10k_ddr_pmu *pmu = to_cn10k_ddr_pmu(event->pmu);
0438 struct hw_perf_event *hwc = &event->hw;
0439 u8 config = event->attr.config;
0440 int counter, ret;
0441 u32 reg_offset;
0442 u64 val;
0443
0444 counter = cn10k_ddr_perf_alloc_counter(pmu, event);
0445 if (counter < 0)
0446 return -EAGAIN;
0447
0448 pmu->active_events++;
0449 hwc->idx = counter;
0450
0451 if (pmu->active_events == 1)
0452 hrtimer_start(&pmu->hrtimer, cn10k_ddr_pmu_timer_period(),
0453 HRTIMER_MODE_REL_PINNED);
0454
0455 if (counter < DDRC_PERF_NUM_GEN_COUNTERS) {
0456
0457 reg_offset = DDRC_PERF_CFG(counter);
0458 ret = ddr_perf_get_event_bitmap(config, &val);
0459 if (ret)
0460 return ret;
0461
0462 writeq_relaxed(val, pmu->base + reg_offset);
0463 } else {
0464
0465 if (counter == DDRC_PERF_READ_COUNTER_IDX)
0466 val = DDRC_FREERUN_READ_CNT_CLR;
0467 else
0468 val = DDRC_FREERUN_WRITE_CNT_CLR;
0469
0470 writeq_relaxed(val, pmu->base + DDRC_PERF_CNT_FREERUN_CTRL);
0471 }
0472
0473 hwc->state |= PERF_HES_STOPPED;
0474
0475 if (flags & PERF_EF_START)
0476 cn10k_ddr_perf_event_start(event, flags);
0477
0478 return 0;
0479 }
0480
0481 static void cn10k_ddr_perf_event_stop(struct perf_event *event, int flags)
0482 {
0483 struct cn10k_ddr_pmu *pmu = to_cn10k_ddr_pmu(event->pmu);
0484 struct hw_perf_event *hwc = &event->hw;
0485 int counter = hwc->idx;
0486
0487 cn10k_ddr_perf_counter_enable(pmu, counter, false);
0488
0489 if (flags & PERF_EF_UPDATE)
0490 cn10k_ddr_perf_event_update(event);
0491
0492 hwc->state |= PERF_HES_STOPPED;
0493 }
0494
0495 static void cn10k_ddr_perf_event_del(struct perf_event *event, int flags)
0496 {
0497 struct cn10k_ddr_pmu *pmu = to_cn10k_ddr_pmu(event->pmu);
0498 struct hw_perf_event *hwc = &event->hw;
0499 int counter = hwc->idx;
0500
0501 cn10k_ddr_perf_event_stop(event, PERF_EF_UPDATE);
0502
0503 cn10k_ddr_perf_free_counter(pmu, counter);
0504 pmu->active_events--;
0505 hwc->idx = -1;
0506
0507
0508 if (pmu->active_events == 0)
0509 hrtimer_cancel(&pmu->hrtimer);
0510 }
0511
0512 static void cn10k_ddr_perf_pmu_enable(struct pmu *pmu)
0513 {
0514 struct cn10k_ddr_pmu *ddr_pmu = to_cn10k_ddr_pmu(pmu);
0515
0516 writeq_relaxed(START_OP_CTRL_VAL_START, ddr_pmu->base +
0517 DDRC_PERF_CNT_START_OP_CTRL);
0518 }
0519
0520 static void cn10k_ddr_perf_pmu_disable(struct pmu *pmu)
0521 {
0522 struct cn10k_ddr_pmu *ddr_pmu = to_cn10k_ddr_pmu(pmu);
0523
0524 writeq_relaxed(END_OP_CTRL_VAL_END, ddr_pmu->base +
0525 DDRC_PERF_CNT_END_OP_CTRL);
0526 }
0527
0528 static void cn10k_ddr_perf_event_update_all(struct cn10k_ddr_pmu *pmu)
0529 {
0530 struct hw_perf_event *hwc;
0531 int i;
0532
0533 for (i = 0; i < DDRC_PERF_NUM_GEN_COUNTERS; i++) {
0534 if (pmu->events[i] == NULL)
0535 continue;
0536
0537 cn10k_ddr_perf_event_update(pmu->events[i]);
0538 }
0539
0540
0541 for (i = 0; i < DDRC_PERF_NUM_GEN_COUNTERS; i++) {
0542 if (pmu->events[i] == NULL)
0543 continue;
0544
0545 hwc = &pmu->events[i]->hw;
0546 local64_set(&hwc->prev_count, 0);
0547 }
0548 }
0549
0550 static irqreturn_t cn10k_ddr_pmu_overflow_handler(struct cn10k_ddr_pmu *pmu)
0551 {
0552 struct perf_event *event;
0553 struct hw_perf_event *hwc;
0554 u64 prev_count, new_count;
0555 u64 value;
0556 int i;
0557
0558 event = pmu->events[DDRC_PERF_READ_COUNTER_IDX];
0559 if (event) {
0560 hwc = &event->hw;
0561 prev_count = local64_read(&hwc->prev_count);
0562 new_count = cn10k_ddr_perf_read_counter(pmu, hwc->idx);
0563
0564
0565
0566
0567 if (new_count < prev_count)
0568 cn10k_ddr_perf_event_update(event);
0569 }
0570
0571 event = pmu->events[DDRC_PERF_WRITE_COUNTER_IDX];
0572 if (event) {
0573 hwc = &event->hw;
0574 prev_count = local64_read(&hwc->prev_count);
0575 new_count = cn10k_ddr_perf_read_counter(pmu, hwc->idx);
0576
0577
0578
0579
0580 if (new_count < prev_count)
0581 cn10k_ddr_perf_event_update(event);
0582 }
0583
0584 for (i = 0; i < DDRC_PERF_NUM_GEN_COUNTERS; i++) {
0585 if (pmu->events[i] == NULL)
0586 continue;
0587
0588 value = cn10k_ddr_perf_read_counter(pmu, i);
0589 if (value == DDRC_PERF_CNT_MAX_VALUE) {
0590 pr_info("Counter-(%d) reached max value\n", i);
0591 cn10k_ddr_perf_event_update_all(pmu);
0592 cn10k_ddr_perf_pmu_disable(&pmu->pmu);
0593 cn10k_ddr_perf_pmu_enable(&pmu->pmu);
0594 }
0595 }
0596
0597 return IRQ_HANDLED;
0598 }
0599
0600 static enum hrtimer_restart cn10k_ddr_pmu_timer_handler(struct hrtimer *hrtimer)
0601 {
0602 struct cn10k_ddr_pmu *pmu = container_of(hrtimer, struct cn10k_ddr_pmu,
0603 hrtimer);
0604 unsigned long flags;
0605
0606 local_irq_save(flags);
0607 cn10k_ddr_pmu_overflow_handler(pmu);
0608 local_irq_restore(flags);
0609
0610 hrtimer_forward_now(hrtimer, cn10k_ddr_pmu_timer_period());
0611 return HRTIMER_RESTART;
0612 }
0613
0614 static int cn10k_ddr_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
0615 {
0616 struct cn10k_ddr_pmu *pmu = hlist_entry_safe(node, struct cn10k_ddr_pmu,
0617 node);
0618 unsigned int target;
0619
0620 if (cpu != pmu->cpu)
0621 return 0;
0622
0623 target = cpumask_any_but(cpu_online_mask, cpu);
0624 if (target >= nr_cpu_ids)
0625 return 0;
0626
0627 perf_pmu_migrate_context(&pmu->pmu, cpu, target);
0628 pmu->cpu = target;
0629 return 0;
0630 }
0631
0632 static int cn10k_ddr_perf_probe(struct platform_device *pdev)
0633 {
0634 struct cn10k_ddr_pmu *ddr_pmu;
0635 struct resource *res;
0636 void __iomem *base;
0637 char *name;
0638 int ret;
0639
0640 ddr_pmu = devm_kzalloc(&pdev->dev, sizeof(*ddr_pmu), GFP_KERNEL);
0641 if (!ddr_pmu)
0642 return -ENOMEM;
0643
0644 ddr_pmu->dev = &pdev->dev;
0645 platform_set_drvdata(pdev, ddr_pmu);
0646
0647 base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
0648 if (IS_ERR(base))
0649 return PTR_ERR(base);
0650
0651 ddr_pmu->base = base;
0652
0653
0654 writeq_relaxed(OP_MODE_CTRL_VAL_MANNUAL, ddr_pmu->base +
0655 DDRC_PERF_CNT_OP_MODE_CTRL);
0656
0657 ddr_pmu->pmu = (struct pmu) {
0658 .module = THIS_MODULE,
0659 .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
0660 .task_ctx_nr = perf_invalid_context,
0661 .attr_groups = cn10k_attr_groups,
0662 .event_init = cn10k_ddr_perf_event_init,
0663 .add = cn10k_ddr_perf_event_add,
0664 .del = cn10k_ddr_perf_event_del,
0665 .start = cn10k_ddr_perf_event_start,
0666 .stop = cn10k_ddr_perf_event_stop,
0667 .read = cn10k_ddr_perf_event_update,
0668 .pmu_enable = cn10k_ddr_perf_pmu_enable,
0669 .pmu_disable = cn10k_ddr_perf_pmu_disable,
0670 };
0671
0672
0673 ddr_pmu->cpu = raw_smp_processor_id();
0674
0675 name = devm_kasprintf(ddr_pmu->dev, GFP_KERNEL, "mrvl_ddr_pmu_%llx",
0676 res->start);
0677 if (!name)
0678 return -ENOMEM;
0679
0680 hrtimer_init(&ddr_pmu->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
0681 ddr_pmu->hrtimer.function = cn10k_ddr_pmu_timer_handler;
0682
0683 cpuhp_state_add_instance_nocalls(
0684 CPUHP_AP_PERF_ARM_MARVELL_CN10K_DDR_ONLINE,
0685 &ddr_pmu->node);
0686
0687 ret = perf_pmu_register(&ddr_pmu->pmu, name, -1);
0688 if (ret)
0689 goto error;
0690
0691 pr_info("CN10K DDR PMU Driver for ddrc@%llx\n", res->start);
0692 return 0;
0693 error:
0694 cpuhp_state_remove_instance_nocalls(
0695 CPUHP_AP_PERF_ARM_MARVELL_CN10K_DDR_ONLINE,
0696 &ddr_pmu->node);
0697 return ret;
0698 }
0699
0700 static int cn10k_ddr_perf_remove(struct platform_device *pdev)
0701 {
0702 struct cn10k_ddr_pmu *ddr_pmu = platform_get_drvdata(pdev);
0703
0704 cpuhp_state_remove_instance_nocalls(
0705 CPUHP_AP_PERF_ARM_MARVELL_CN10K_DDR_ONLINE,
0706 &ddr_pmu->node);
0707
0708 perf_pmu_unregister(&ddr_pmu->pmu);
0709 return 0;
0710 }
0711
0712 #ifdef CONFIG_OF
0713 static const struct of_device_id cn10k_ddr_pmu_of_match[] = {
0714 { .compatible = "marvell,cn10k-ddr-pmu", },
0715 { },
0716 };
0717 MODULE_DEVICE_TABLE(of, cn10k_ddr_pmu_of_match);
0718 #endif
0719
0720 static struct platform_driver cn10k_ddr_pmu_driver = {
0721 .driver = {
0722 .name = "cn10k-ddr-pmu",
0723 .of_match_table = of_match_ptr(cn10k_ddr_pmu_of_match),
0724 .suppress_bind_attrs = true,
0725 },
0726 .probe = cn10k_ddr_perf_probe,
0727 .remove = cn10k_ddr_perf_remove,
0728 };
0729
0730 static int __init cn10k_ddr_pmu_init(void)
0731 {
0732 int ret;
0733
0734 ret = cpuhp_setup_state_multi(
0735 CPUHP_AP_PERF_ARM_MARVELL_CN10K_DDR_ONLINE,
0736 "perf/marvell/cn10k/ddr:online", NULL,
0737 cn10k_ddr_pmu_offline_cpu);
0738 if (ret)
0739 return ret;
0740
0741 ret = platform_driver_register(&cn10k_ddr_pmu_driver);
0742 if (ret)
0743 cpuhp_remove_multi_state(
0744 CPUHP_AP_PERF_ARM_MARVELL_CN10K_DDR_ONLINE);
0745 return ret;
0746 }
0747
0748 static void __exit cn10k_ddr_pmu_exit(void)
0749 {
0750 platform_driver_unregister(&cn10k_ddr_pmu_driver);
0751 cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_MARVELL_CN10K_DDR_ONLINE);
0752 }
0753
0754 module_init(cn10k_ddr_pmu_init);
0755 module_exit(cn10k_ddr_pmu_exit);
0756
0757 MODULE_AUTHOR("Bharat Bhushan <bbhushan2@marvell.com>");
0758 MODULE_LICENSE("GPL v2");