1111#include <linux/of_address.h>
1212#include <linux/of_device.h>
1313#include <linux/perf_event.h>
14+ #include <linux/hrtimer.h>
1415
1516/* Performance Counters Operating Mode Control Registers */
1617#define DDRC_PERF_CNT_OP_MODE_CTRL 0x8020
@@ -127,6 +128,7 @@ struct cn10k_ddr_pmu {
127128 struct device * dev ;
128129 int active_events ;
129130 struct perf_event * events [DDRC_PERF_NUM_COUNTERS ];
131+ struct hrtimer hrtimer ;
130132};
131133
132134#define to_cn10k_ddr_pmu (p ) container_of(p, struct cn10k_ddr_pmu, pmu)
@@ -251,6 +253,18 @@ static const struct attribute_group *cn10k_attr_groups[] = {
251253 NULL ,
252254};
253255
256+ /* Default poll timeout is 100 sec, which is very sufficient for
257+ * 48 bit counter incremented max at 5.6 GT/s, which may take many
258+ * hours to overflow.
259+ */
260+ static unsigned long cn10k_ddr_pmu_poll_period_sec = 100 ;
261+ module_param_named (poll_period_sec , cn10k_ddr_pmu_poll_period_sec , ulong , 0644 );
262+
263+ static ktime_t cn10k_ddr_pmu_timer_period (void )
264+ {
265+ return ms_to_ktime ((u64 )cn10k_ddr_pmu_poll_period_sec * USEC_PER_SEC );
266+ }
267+
254268static int ddr_perf_get_event_bitmap (int eventid , u64 * event_bitmap )
255269{
256270 switch (eventid ) {
@@ -433,6 +447,10 @@ static int cn10k_ddr_perf_event_add(struct perf_event *event, int flags)
433447 pmu -> active_events ++ ;
434448 hwc -> idx = counter ;
435449
450+ if (pmu -> active_events == 1 )
451+ hrtimer_start (& pmu -> hrtimer , cn10k_ddr_pmu_timer_period (),
452+ HRTIMER_MODE_REL_PINNED );
453+
436454 if (counter < DDRC_PERF_NUM_GEN_COUNTERS ) {
437455 /* Generic counters, configure event id */
438456 reg_offset = DDRC_PERF_CFG (counter );
@@ -484,6 +502,10 @@ static void cn10k_ddr_perf_event_del(struct perf_event *event, int flags)
484502 cn10k_ddr_perf_free_counter (pmu , counter );
485503 pmu -> active_events -- ;
486504 hwc -> idx = -1 ;
505+
506+ /* Cancel timer when no events to capture */
507+ if (pmu -> active_events == 0 )
508+ hrtimer_cancel (& pmu -> hrtimer );
487509}
488510
489511static void cn10k_ddr_perf_pmu_enable (struct pmu * pmu )
@@ -502,6 +524,92 @@ static void cn10k_ddr_perf_pmu_disable(struct pmu *pmu)
502524 DDRC_PERF_CNT_END_OP_CTRL );
503525}
504526
527+ static void cn10k_ddr_perf_event_update_all (struct cn10k_ddr_pmu * pmu )
528+ {
529+ struct hw_perf_event * hwc ;
530+ int i ;
531+
532+ for (i = 0 ; i < DDRC_PERF_NUM_GEN_COUNTERS ; i ++ ) {
533+ if (pmu -> events [i ] == NULL )
534+ continue ;
535+
536+ cn10k_ddr_perf_event_update (pmu -> events [i ]);
537+ }
538+
539+ /* Reset previous count as h/w counter are reset */
540+ for (i = 0 ; i < DDRC_PERF_NUM_GEN_COUNTERS ; i ++ ) {
541+ if (pmu -> events [i ] == NULL )
542+ continue ;
543+
544+ hwc = & pmu -> events [i ]-> hw ;
545+ local64_set (& hwc -> prev_count , 0 );
546+ }
547+ }
548+
549+ static irqreturn_t cn10k_ddr_pmu_overflow_handler (struct cn10k_ddr_pmu * pmu )
550+ {
551+ struct perf_event * event ;
552+ struct hw_perf_event * hwc ;
553+ u64 prev_count , new_count ;
554+ u64 value ;
555+ int i ;
556+
557+ event = pmu -> events [DDRC_PERF_READ_COUNTER_IDX ];
558+ if (event ) {
559+ hwc = & event -> hw ;
560+ prev_count = local64_read (& hwc -> prev_count );
561+ new_count = cn10k_ddr_perf_read_counter (pmu , hwc -> idx );
562+
563+ /* Overflow condition is when new count less than
564+ * previous count
565+ */
566+ if (new_count < prev_count )
567+ cn10k_ddr_perf_event_update (event );
568+ }
569+
570+ event = pmu -> events [DDRC_PERF_WRITE_COUNTER_IDX ];
571+ if (event ) {
572+ hwc = & event -> hw ;
573+ prev_count = local64_read (& hwc -> prev_count );
574+ new_count = cn10k_ddr_perf_read_counter (pmu , hwc -> idx );
575+
576+ /* Overflow condition is when new count less than
577+ * previous count
578+ */
579+ if (new_count < prev_count )
580+ cn10k_ddr_perf_event_update (event );
581+ }
582+
583+ for (i = 0 ; i < DDRC_PERF_NUM_GEN_COUNTERS ; i ++ ) {
584+ if (pmu -> events [i ] == NULL )
585+ continue ;
586+
587+ value = cn10k_ddr_perf_read_counter (pmu , i );
588+ if (value == DDRC_PERF_CNT_MAX_VALUE ) {
589+ pr_info ("Counter-(%d) reached max value\n" , i );
590+ cn10k_ddr_perf_event_update_all (pmu );
591+ cn10k_ddr_perf_pmu_disable (& pmu -> pmu );
592+ cn10k_ddr_perf_pmu_enable (& pmu -> pmu );
593+ }
594+ }
595+
596+ return IRQ_HANDLED ;
597+ }
598+
599+ static enum hrtimer_restart cn10k_ddr_pmu_timer_handler (struct hrtimer * hrtimer )
600+ {
601+ struct cn10k_ddr_pmu * pmu = container_of (hrtimer , struct cn10k_ddr_pmu ,
602+ hrtimer );
603+ unsigned long flags ;
604+
605+ local_irq_save (flags );
606+ cn10k_ddr_pmu_overflow_handler (pmu );
607+ local_irq_restore (flags );
608+
609+ hrtimer_forward_now (hrtimer , cn10k_ddr_pmu_timer_period ());
610+ return HRTIMER_RESTART ;
611+ }
612+
505613static int cn10k_ddr_perf_probe (struct platform_device * pdev )
506614{
507615 struct cn10k_ddr_pmu * ddr_pmu ;
@@ -550,6 +658,9 @@ static int cn10k_ddr_perf_probe(struct platform_device *pdev)
550658 if (!name )
551659 return - ENOMEM ;
552660
661+ hrtimer_init (& ddr_pmu -> hrtimer , CLOCK_MONOTONIC , HRTIMER_MODE_REL );
662+ ddr_pmu -> hrtimer .function = cn10k_ddr_pmu_timer_handler ;
663+
553664 ret = perf_pmu_register (& ddr_pmu -> pmu , name , -1 );
554665 if (ret )
555666 return ret ;
0 commit comments