Loading Documentation/devicetree/bindings/devfreq/arm-memlat-mon.txt 0 → 100644 +16 −0 Original line number Diff line number Diff line ARM CPU memory latency monitor device arm-memlat-mon is a device that represents the use of the PMU in ARM cores to measure the parameters for latency driven memory access patterns. Required properties: - compatible: Must be "qcom,arm-memlat-mon" - qcom,firstcpu: First CPU of the cluster to be monitored - qcom,target-dev: The DT device that corresponds to this master port Example: qcom,arm-memlat-mon { compatible = "qcom,arm-memlat-mon"; qcom,firstcpu = <&CPU0>; qcom,target-dev = <&memlat0>; }; arch/arm/boot/dts/qcom/msm8996-pm.dtsi +1 −0 Original line number Diff line number Diff line Loading @@ -230,6 +230,7 @@ <52 212>, /* qmp_usb3_lfps_rxterm_irq */ <87 358>, /* ee0_krait_hlos_spmi_periph_irq */ <0xff 16>, /* APCj_qgicdrCpu0HwFaultIrptReq */ <0xff 23>, /* APCj_qgicdrCpu0PerfMonIrptReq */ <0xff 27>, /* APCj_qgicdrCpu0QTmrVirtIrptReq */ <0xff 32>, /* APCj_qgicdrL2PerfMonIrptReq */ <0xff 33>, /* APCC_qgicL2PerfMonIrptReq */ Loading arch/arm/boot/dts/qcom/msm8996.dtsi +48 −0 Original line number Diff line number Diff line Loading @@ -483,6 +483,54 @@ < 13763 /* 1804 MHz */ >; }; memlat_cpu0: qcom,memlat-cpu0 { compatible = "qcom,devbw"; governor = "powersave"; qcom,src-dst-ports = <1 512>; qcom,active-only; qcom,bw-tbl = < 1525 /* 200 MHz */ >, < 2288 /* 300 MHz */ >, < 3509 /* 460 MHz */ >, < 4066 /* 533 MHz */ >, < 5126 /* 672 MHz */ >, < 5928 /* 777 MHz */ >, < 7904 /* 1036 MHz */ >, < 9887 /* 1296 MHz */ >, < 11863 /* 1555 MHz */ >, < 13763 /* 1804 MHz */ >; }; memlat_cpu2: qcom,memlat-cpu2 { compatible = "qcom,devbw"; governor = "powersave"; qcom,src-dst-ports = <1 512>; qcom,active-only; qcom,bw-tbl = < 1525 /* 200 MHz */ >, < 2288 /* 300 MHz */ >, < 3509 /* 460 MHz */ >, < 4066 /* 533 MHz */ >, < 5126 /* 672 MHz */ >, < 5928 /* 777 MHz */ >, < 7904 /* 1036 MHz */ >, < 9887 /* 1296 MHz */ >, < 11863 /* 1555 MHz */ >, < 13763 /* 1804 MHz */ >; }; qcom,arm-memlat-mon-0 { compatible = "qcom,arm-memlat-mon"; qcom,firstcpu = <&CPU0>; qcom,target-dev = <&memlat_cpu0>; }; qcom,arm-memlat-mon-2 { compatible = "qcom,arm-memlat-mon"; qcom,firstcpu = <&CPU2>; qcom,target-dev = <&memlat_cpu2>; }; devfreq_cpufreq: devfreq-cpufreq { cpubw-cpufreq { target-dev = <&cpubw>; Loading arch/arm64/Kconfig +2 −0 Original line number Diff line number Diff line Loading @@ -220,6 +220,8 @@ config ARCH_MSM select ARCH_HAS_OPP select THERMAL_WRITABLE_TRIPS select CPU_FREQ_MSM select ARM_MEMLAT_MON select DEVFREQ_GOV_MEMLAT help This enables support for the ARMv8 based Qualcomm chipsets. Loading arch/arm64/kernel/perf_event.c +39 −7 Original line number Diff line number Diff line Loading @@ -1224,11 +1224,9 @@ static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc, int idx; unsigned long evtype = event->config_base & ARMV8_EVTYPE_EVENT; /* Always place a cycle counter into the cycle counter. */ /* Place the first cycle counter request into the cycle counter. */ if (evtype == ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES) { if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask)) return -EAGAIN; if (!test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask)) return ARMV8_IDX_CYCLE_COUNTER; } Loading @@ -1253,8 +1251,6 @@ static int armv8pmu_set_event_filter(struct hw_perf_event *event, { unsigned long config_base = 0; if (attr->exclude_idle) return -EPERM; if (attr->exclude_user) config_base |= ARMV8_EXCLUDE_EL0; if (attr->exclude_kernel) Loading Loading @@ -1416,6 +1412,26 @@ static void armpmu_update_counters(void *x) } } static void armpmu_idle_update(void) { struct pmu_hw_events *hw_events; int idx; if (!cpu_pmu) return; hw_events = cpu_pmu->get_hw_events(); for (idx = 0; idx <= cpu_pmu->num_events; ++idx) { struct perf_event *event = hw_events->events[idx]; if (!event || !event->attr.exclude_idle) continue; cpu_pmu->pmu.read(event); } } static void armpmu_hotplug_enable(void *parm_pmu) { struct arm_pmu *armpmu = parm_pmu; Loading Loading @@ -1581,6 +1597,19 @@ static struct notifier_block perf_cpu_pm_notifier_block = { .notifier_call = perf_cpu_pm_notifier, }; static int perf_cpu_idle_notifier(struct notifier_block *nb, unsigned long action, void *data) { if (action == IDLE_START) armpmu_idle_update(); return NOTIFY_OK; } static struct notifier_block perf_cpu_idle_nb = { .notifier_call = perf_cpu_idle_notifier, }; /* * PMU platform driver and devicetree bindings. */ Loading Loading @@ -1633,6 +1662,8 @@ static int __init register_pmu_driver(void) if (err) goto err_cpu_pm; idle_notifier_register(&perf_cpu_idle_nb); err = platform_driver_register(&armpmu_driver); if (err) goto err_driver; Loading @@ -1640,6 +1671,7 @@ static int __init register_pmu_driver(void) err_driver: cpu_pm_unregister_notifier(&perf_cpu_pm_notifier_block); idle_notifier_unregister(&perf_cpu_idle_nb); err_cpu_pm: unregister_cpu_notifier(&cpu_pmu_hotplug_notifier); return err; Loading Loading
Documentation/devicetree/bindings/devfreq/arm-memlat-mon.txt 0 → 100644 +16 −0 Original line number Diff line number Diff line ARM CPU memory latency monitor device arm-memlat-mon is a device that represents the use of the PMU in ARM cores to measure the parameters for latency driven memory access patterns. Required properties: - compatible: Must be "qcom,arm-memlat-mon" - qcom,firstcpu: First CPU of the cluster to be monitored - qcom,target-dev: The DT device that corresponds to this master port Example: qcom,arm-memlat-mon { compatible = "qcom,arm-memlat-mon"; qcom,firstcpu = <&CPU0>; qcom,target-dev = <&memlat0>; };
arch/arm/boot/dts/qcom/msm8996-pm.dtsi +1 −0 Original line number Diff line number Diff line Loading @@ -230,6 +230,7 @@ <52 212>, /* qmp_usb3_lfps_rxterm_irq */ <87 358>, /* ee0_krait_hlos_spmi_periph_irq */ <0xff 16>, /* APCj_qgicdrCpu0HwFaultIrptReq */ <0xff 23>, /* APCj_qgicdrCpu0PerfMonIrptReq */ <0xff 27>, /* APCj_qgicdrCpu0QTmrVirtIrptReq */ <0xff 32>, /* APCj_qgicdrL2PerfMonIrptReq */ <0xff 33>, /* APCC_qgicL2PerfMonIrptReq */ Loading
arch/arm/boot/dts/qcom/msm8996.dtsi +48 −0 Original line number Diff line number Diff line Loading @@ -483,6 +483,54 @@ < 13763 /* 1804 MHz */ >; }; memlat_cpu0: qcom,memlat-cpu0 { compatible = "qcom,devbw"; governor = "powersave"; qcom,src-dst-ports = <1 512>; qcom,active-only; qcom,bw-tbl = < 1525 /* 200 MHz */ >, < 2288 /* 300 MHz */ >, < 3509 /* 460 MHz */ >, < 4066 /* 533 MHz */ >, < 5126 /* 672 MHz */ >, < 5928 /* 777 MHz */ >, < 7904 /* 1036 MHz */ >, < 9887 /* 1296 MHz */ >, < 11863 /* 1555 MHz */ >, < 13763 /* 1804 MHz */ >; }; memlat_cpu2: qcom,memlat-cpu2 { compatible = "qcom,devbw"; governor = "powersave"; qcom,src-dst-ports = <1 512>; qcom,active-only; qcom,bw-tbl = < 1525 /* 200 MHz */ >, < 2288 /* 300 MHz */ >, < 3509 /* 460 MHz */ >, < 4066 /* 533 MHz */ >, < 5126 /* 672 MHz */ >, < 5928 /* 777 MHz */ >, < 7904 /* 1036 MHz */ >, < 9887 /* 1296 MHz */ >, < 11863 /* 1555 MHz */ >, < 13763 /* 1804 MHz */ >; }; qcom,arm-memlat-mon-0 { compatible = "qcom,arm-memlat-mon"; qcom,firstcpu = <&CPU0>; qcom,target-dev = <&memlat_cpu0>; }; qcom,arm-memlat-mon-2 { compatible = "qcom,arm-memlat-mon"; qcom,firstcpu = <&CPU2>; qcom,target-dev = <&memlat_cpu2>; }; devfreq_cpufreq: devfreq-cpufreq { cpubw-cpufreq { target-dev = <&cpubw>; Loading
arch/arm64/Kconfig +2 −0 Original line number Diff line number Diff line Loading @@ -220,6 +220,8 @@ config ARCH_MSM select ARCH_HAS_OPP select THERMAL_WRITABLE_TRIPS select CPU_FREQ_MSM select ARM_MEMLAT_MON select DEVFREQ_GOV_MEMLAT help This enables support for the ARMv8 based Qualcomm chipsets. Loading
arch/arm64/kernel/perf_event.c +39 −7 Original line number Diff line number Diff line Loading @@ -1224,11 +1224,9 @@ static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc, int idx; unsigned long evtype = event->config_base & ARMV8_EVTYPE_EVENT; /* Always place a cycle counter into the cycle counter. */ /* Place the first cycle counter request into the cycle counter. */ if (evtype == ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES) { if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask)) return -EAGAIN; if (!test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask)) return ARMV8_IDX_CYCLE_COUNTER; } Loading @@ -1253,8 +1251,6 @@ static int armv8pmu_set_event_filter(struct hw_perf_event *event, { unsigned long config_base = 0; if (attr->exclude_idle) return -EPERM; if (attr->exclude_user) config_base |= ARMV8_EXCLUDE_EL0; if (attr->exclude_kernel) Loading Loading @@ -1416,6 +1412,26 @@ static void armpmu_update_counters(void *x) } } static void armpmu_idle_update(void) { struct pmu_hw_events *hw_events; int idx; if (!cpu_pmu) return; hw_events = cpu_pmu->get_hw_events(); for (idx = 0; idx <= cpu_pmu->num_events; ++idx) { struct perf_event *event = hw_events->events[idx]; if (!event || !event->attr.exclude_idle) continue; cpu_pmu->pmu.read(event); } } static void armpmu_hotplug_enable(void *parm_pmu) { struct arm_pmu *armpmu = parm_pmu; Loading Loading @@ -1581,6 +1597,19 @@ static struct notifier_block perf_cpu_pm_notifier_block = { .notifier_call = perf_cpu_pm_notifier, }; static int perf_cpu_idle_notifier(struct notifier_block *nb, unsigned long action, void *data) { if (action == IDLE_START) armpmu_idle_update(); return NOTIFY_OK; } static struct notifier_block perf_cpu_idle_nb = { .notifier_call = perf_cpu_idle_notifier, }; /* * PMU platform driver and devicetree bindings. */ Loading Loading @@ -1633,6 +1662,8 @@ static int __init register_pmu_driver(void) if (err) goto err_cpu_pm; idle_notifier_register(&perf_cpu_idle_nb); err = platform_driver_register(&armpmu_driver); if (err) goto err_driver; Loading @@ -1640,6 +1671,7 @@ static int __init register_pmu_driver(void) err_driver: cpu_pm_unregister_notifier(&perf_cpu_pm_notifier_block); idle_notifier_unregister(&perf_cpu_idle_nb); err_cpu_pm: unregister_cpu_notifier(&cpu_pmu_hotplug_notifier); return err; Loading