int *ret;
        bool *has_match;
        bool metric_no_group;
+       bool metric_no_threshold;
        const char *user_requested_cpu_list;
        bool system_wide;
        struct metric *root_metric;
                      const struct pmu_metric *pm,
                      const char *modifier,
                      bool metric_no_group,
+                     bool metric_no_threshold,
                      const char *user_requested_cpu_list,
                      bool system_wide,
                      struct metric *root_metric,
 static int resolve_metric(struct list_head *metric_list,
                          const char *modifier,
                          bool metric_no_group,
+                         bool metric_no_threshold,
                          const char *user_requested_cpu_list,
                          bool system_wide,
                          struct metric *root_metric,
         */
        for (i = 0; i < pending_cnt; i++) {
                ret = add_metric(metric_list, &pending[i].pm, modifier, metric_no_group,
-                                user_requested_cpu_list, system_wide, root_metric, visited,
-                                table);
+                                metric_no_threshold, user_requested_cpu_list, system_wide,
+                                root_metric, visited, table);
                if (ret)
                        break;
        }
  * @metric_no_group: Should events written to events be grouped "{}" or
  *                   global. Grouping is the default but due to multiplexing the
  *                   user may override.
+ * @metric_no_threshold: Should threshold expressions be ignored?
  * @runtime: A special argument for the parser only known at runtime.
  * @user_requested_cpu_list: Command line specified CPUs to record on.
  * @system_wide: Are events for all processes recorded.
                        const struct pmu_metric *pm,
                        const char *modifier,
                        bool metric_no_group,
+                       bool metric_no_threshold,
                        int runtime,
                        const char *user_requested_cpu_list,
                        bool system_wide,
                 * Threshold expressions are built off the actual metric. Switch
                 * to use that in case of additional necessary events. Change
                 * the visited node name to avoid this being flagged as
-                * recursion.
+                * recursion. If the threshold events are disabled, just use the
+                * metric's name as a reference. This allows metric threshold
+                * computation if there are sufficient events.
                 */
                assert(strstr(pm->metric_threshold, pm->metric_name));
-               expr = pm->metric_threshold;
+               expr = metric_no_threshold ? pm->metric_name : pm->metric_threshold;
                visited_node.name = "__threshold__";
        }
        if (expr__find_ids(expr, NULL, root_metric->pctx) < 0) {
        if (!ret) {
                /* Resolve referenced metrics. */
                ret = resolve_metric(metric_list, modifier, metric_no_group,
-                                    user_requested_cpu_list, system_wide,
-                                    root_metric, &visited_node, table);
+                                    metric_no_threshold, user_requested_cpu_list,
+                                    system_wide, root_metric, &visited_node, table);
        }
        if (ret) {
                if (is_root)
                      const struct pmu_metric *pm,
                      const char *modifier,
                      bool metric_no_group,
+                     bool metric_no_threshold,
                      const char *user_requested_cpu_list,
                      bool system_wide,
                      struct metric *root_metric,
        pr_debug("metric expr %s for %s\n", pm->metric_expr, pm->metric_name);
 
        if (!strstr(pm->metric_expr, "?")) {
-               ret = __add_metric(metric_list, pm, modifier, metric_no_group, 0,
-                                  user_requested_cpu_list, system_wide, root_metric,
-                                  visited, table);
+               ret = __add_metric(metric_list, pm, modifier, metric_no_group,
+                                  metric_no_threshold, 0, user_requested_cpu_list,
+                                  system_wide, root_metric, visited, table);
        } else {
                int j, count;
 
                 */
 
                for (j = 0; j < count && !ret; j++)
-                       ret = __add_metric(metric_list, pm, modifier, metric_no_group, j,
-                                          user_requested_cpu_list, system_wide,
-                                          root_metric, visited, table);
+                       ret = __add_metric(metric_list, pm, modifier, metric_no_group,
+                                          metric_no_threshold, j, user_requested_cpu_list,
+                                          system_wide, root_metric, visited, table);
        }
 
        return ret;
                return 0;
 
        ret = add_metric(d->metric_list, pm, d->modifier, d->metric_no_group,
-                        d->user_requested_cpu_list, d->system_wide,
-                        d->root_metric, d->visited, d->table);
+                        d->metric_no_threshold, d->user_requested_cpu_list,
+                        d->system_wide, d->root_metric, d->visited, d->table);
        if (ret)
                goto out;
 
        const char *modifier;
        const char *user_requested_cpu_list;
        bool metric_no_group;
+       bool metric_no_threshold;
        bool system_wide;
        bool has_match;
 };
 
                data->has_match = true;
                ret = add_metric(data->list, pm, data->modifier, data->metric_no_group,
-                                data->user_requested_cpu_list, data->system_wide,
-                                /*root_metric=*/NULL, /*visited_metrics=*/NULL, table);
+                                data->metric_no_threshold, data->user_requested_cpu_list,
+                                data->system_wide, /*root_metric=*/NULL,
+                                /*visited_metrics=*/NULL, table);
        }
        return ret;
 }
  *       architecture perf is running upon.
  */
 static int metricgroup__add_metric(const char *metric_name, const char *modifier,
-                                  bool metric_no_group,
+                                  bool metric_no_group, bool metric_no_threshold,
                                   const char *user_requested_cpu_list,
                                   bool system_wide,
                                   struct list_head *metric_list,
                        .metric_name = metric_name,
                        .modifier = modifier,
                        .metric_no_group = metric_no_group,
+                       .metric_no_threshold = metric_no_threshold,
                        .user_requested_cpu_list = user_requested_cpu_list,
                        .system_wide = system_wide,
                        .has_match = false,
  *       architecture perf is running upon.
  */
 static int metricgroup__add_metric_list(const char *list, bool metric_no_group,
+                                       bool metric_no_threshold,
                                        const char *user_requested_cpu_list,
                                        bool system_wide, struct list_head *metric_list,
                                        const struct pmu_metrics_table *table)
                        *modifier++ = '\0';
 
                ret = metricgroup__add_metric(metric_name, modifier,
-                                             metric_no_group, user_requested_cpu_list,
+                                             metric_no_group, metric_no_threshold,
+                                             user_requested_cpu_list,
                                              system_wide, metric_list, table);
                if (ret == -EINVAL)
                        pr_err("Cannot find metric or group `%s'\n", metric_name);
 static int parse_groups(struct evlist *perf_evlist, const char *str,
                        bool metric_no_group,
                        bool metric_no_merge,
+                       bool metric_no_threshold,
                        const char *user_requested_cpu_list,
                        bool system_wide,
                        struct perf_pmu *fake_pmu,
 
        if (metric_events_list->nr_entries == 0)
                metricgroup__rblist_init(metric_events_list);
-       ret = metricgroup__add_metric_list(str, metric_no_group,
+       ret = metricgroup__add_metric_list(str, metric_no_group, metric_no_threshold,
                                           user_requested_cpu_list,
                                           system_wide, &metric_list, table);
        if (ret)
                              const char *str,
                              bool metric_no_group,
                              bool metric_no_merge,
+                             bool metric_no_threshold,
                              const char *user_requested_cpu_list,
                              bool system_wide,
                              struct rblist *metric_events)
                return -EINVAL;
 
        return parse_groups(perf_evlist, str, metric_no_group, metric_no_merge,
-                           user_requested_cpu_list, system_wide,
+                           metric_no_threshold, user_requested_cpu_list, system_wide,
                            /*fake_pmu=*/NULL, metric_events, table);
 }
 
 int metricgroup__parse_groups_test(struct evlist *evlist,
                                   const struct pmu_metrics_table *table,
                                   const char *str,
-                                  bool metric_no_group,
-                                  bool metric_no_merge,
                                   struct rblist *metric_events)
 {
-       return parse_groups(evlist, str, metric_no_group, metric_no_merge,
+       return parse_groups(evlist, str,
+                           /*metric_no_group=*/false,
+                           /*metric_no_merge=*/false,
+                           /*metric_no_threshold=*/false,
                            /*user_requested_cpu_list=*/NULL,
                            /*system_wide=*/false,
                            &perf_pmu__fake, metric_events, table);