static irqreturn_t px_pmu_isr(struct pt_regs * const regs, unsigned int pid, unsigned int tid, unsigned int cpu, unsigned long long ts) { u32 pmnc_value; u32 flag_value; unsigned int i; unsigned int reg_id; bool buffer_full = false; char ** bt_buffer = &per_cpu(g_bt_buffer, cpu); PXD32_CSS_Call_Stack_V2 *css_data = (PXD32_CSS_Call_Stack_V2 *)*bt_buffer; /* disable the counters */ pmnc_value = PJ4_Read_PMNC(); pmnc_value &= ~0x1; PJ4_Write_PMNC(pmnc_value); /* clear the overflow flag */ flag_value = PJ4_Read_FLAG(); PJ4_Write_FLAG(0xffffffff); if (flag_value != 0) backtrace(regs, cpu, pid, tid, css_data); if ((flag_value & 0x80000000) && es[COUNTER_PJ4_PMU_CCNT].enabled) { reg_id = COUNTER_PJ4_PMU_CCNT; /* ccnt overflow */ if (es[reg_id].calibration == false) { /* write css data in non-calibration mode */ if (!buffer_full) { fill_css_data_head(css_data, pid, tid, reg_id, ts); buffer_full |= write_css_data(cpu, css_data); } } else { /* calculate the overflow count in calibration mode */ es[reg_id].overflow++; } PJ4_WritePMUCounter(reg_id, es[reg_id].reset_value); } for (i=0; i<PJ4_PMN_NUM; i++) { if (flag_value & (0x1 << i)) { switch (i) { case 0: reg_id = COUNTER_PJ4_PMU_PMN0; break; case 1: reg_id = COUNTER_PJ4_PMU_PMN1; break; case 2: reg_id = COUNTER_PJ4_PMU_PMN2; break; case 3: reg_id = COUNTER_PJ4_PMU_PMN3; break; default: break; } if (es[reg_id].calibration == false) { /* write css data in non-calibration mode */ if (!buffer_full) { fill_css_data_head(css_data, pid, tid, reg_id, ts); buffer_full |= write_css_data(cpu, css_data); } } else { /* calculate the overflow count in calibration mode */ es[reg_id].overflow++; } PJ4_WritePMUCounter(reg_id, es[reg_id].reset_value); } } if (!buffer_full) { /* enable the counters */ pmnc_value |= 0x1; PJ4_Write_PMNC(pmnc_value); } return IRQ_HANDLED; }
static irqreturn_t px_pmu_isr(unsigned int pid, unsigned int tid, unsigned int pc, unsigned int timestamp) { u32 pmnc_value; u32 flag_value; unsigned int i; bool buffer_full = false; PXD32_Hotspot_Sample sample_rec; /* disable the counters */ pmnc_value = PJ4_Read_PMNC(); pmnc_value &= ~0x1; PJ4_Write_PMNC(pmnc_value); /* clear the overflow flag */ flag_value = PJ4_Read_FLAG(); PJ4_Write_FLAG(0x8000000f); sample_rec.pc = pc; sample_rec.pid = pid; sample_rec.tid = tid; memcpy(sample_rec.timestamp, ×tamp, 3); if ((flag_value & 0x80000000) && es[COUNTER_PJ4_PMU_CCNT].enabled) { sample_rec.registerId = COUNTER_PJ4_PMU_CCNT; /* ccnt overflow */ if (es[sample_rec.registerId].calibration == false) { /* write sample record in non-calibration mode */ buffer_full |= write_sample(&sample_rec); } else { /* calculate the overflow count in calibration mode */ es[sample_rec.registerId].overflow++; } PJ4_WritePMUCounter(sample_rec.registerId, es[sample_rec.registerId].reset_value); } for (i=0; i<4; i++) { if (flag_value & (0x1 << i)) { switch (i) { case 0: sample_rec.registerId = COUNTER_PJ4_PMU_PMN0; break; case 1: sample_rec.registerId = COUNTER_PJ4_PMU_PMN1; break; case 2: sample_rec.registerId = COUNTER_PJ4_PMU_PMN2; break; case 3: sample_rec.registerId = COUNTER_PJ4_PMU_PMN3; break; default: break; } if (es[sample_rec.registerId].calibration == false) { /* write sample record in non-calibration mode */ buffer_full |= write_sample(&sample_rec); } else { /* calculate the overflow count in calibration mode */ es[sample_rec.registerId].overflow++; } PJ4_WritePMUCounter(sample_rec.registerId, es[sample_rec.registerId].reset_value); } } if (!buffer_full) { /* enable the counters */ pmnc_value |= 0x1; PJ4_Write_PMNC(pmnc_value); } return IRQ_HANDLED; }