Commit a465d38f authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'pm-devfreq', 'pm-avs' and 'pm-tools'

* pm-devfreq:
  PM / devfreq: add devfreq_suspend/resume() functions
  PM / devfreq: add support for suspend/resume of a devfreq device
  PM / devfreq: refactor set_target frequency function

* pm-avs:
  PM / AVS: SmartReflex: Switch to SPDX Licence ID
  PM / AVS: SmartReflex: NULL check before some freeing functions is not needed
  PM / AVS: SmartReflex: remove unused function

* pm-tools:
  tools/power/x86/intel_pstate_tracer: Fix non root execution for post processing a trace file
  tools/power turbostat: consolidate duplicate model numbers
  tools/power turbostat: fix goldmont C-state limit decoding
  cpupower : Auto-completion for cpupower tool
  tools/power turbostat: reduce debug output
  tools/power turbosat: fix AMD APIC-id output
...@@ -285,6 +285,44 @@ static int devfreq_notify_transition(struct devfreq *devfreq, ...@@ -285,6 +285,44 @@ static int devfreq_notify_transition(struct devfreq *devfreq,
return 0; return 0;
} }
static int devfreq_set_target(struct devfreq *devfreq, unsigned long new_freq,
u32 flags)
{
struct devfreq_freqs freqs;
unsigned long cur_freq;
int err = 0;
if (devfreq->profile->get_cur_freq)
devfreq->profile->get_cur_freq(devfreq->dev.parent, &cur_freq);
else
cur_freq = devfreq->previous_freq;
freqs.old = cur_freq;
freqs.new = new_freq;
devfreq_notify_transition(devfreq, &freqs, DEVFREQ_PRECHANGE);
err = devfreq->profile->target(devfreq->dev.parent, &new_freq, flags);
if (err) {
freqs.new = cur_freq;
devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
return err;
}
freqs.new = new_freq;
devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
if (devfreq_update_status(devfreq, new_freq))
dev_err(&devfreq->dev,
"Couldn't update frequency transition information.\n");
devfreq->previous_freq = new_freq;
if (devfreq->suspend_freq)
devfreq->resume_freq = cur_freq;
return err;
}
/* Load monitoring helper functions for governors use */ /* Load monitoring helper functions for governors use */
/** /**
...@@ -296,8 +334,7 @@ static int devfreq_notify_transition(struct devfreq *devfreq, ...@@ -296,8 +334,7 @@ static int devfreq_notify_transition(struct devfreq *devfreq,
*/ */
int update_devfreq(struct devfreq *devfreq) int update_devfreq(struct devfreq *devfreq)
{ {
struct devfreq_freqs freqs; unsigned long freq, min_freq, max_freq;
unsigned long freq, cur_freq, min_freq, max_freq;
int err = 0; int err = 0;
u32 flags = 0; u32 flags = 0;
...@@ -333,31 +370,8 @@ int update_devfreq(struct devfreq *devfreq) ...@@ -333,31 +370,8 @@ int update_devfreq(struct devfreq *devfreq)
flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */ flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */
} }
if (devfreq->profile->get_cur_freq) return devfreq_set_target(devfreq, freq, flags);
devfreq->profile->get_cur_freq(devfreq->dev.parent, &cur_freq);
else
cur_freq = devfreq->previous_freq;
freqs.old = cur_freq;
freqs.new = freq;
devfreq_notify_transition(devfreq, &freqs, DEVFREQ_PRECHANGE);
err = devfreq->profile->target(devfreq->dev.parent, &freq, flags);
if (err) {
freqs.new = cur_freq;
devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
return err;
}
freqs.new = freq;
devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
if (devfreq_update_status(devfreq, freq))
dev_err(&devfreq->dev,
"Couldn't update frequency transition information.\n");
devfreq->previous_freq = freq;
return err;
} }
EXPORT_SYMBOL(update_devfreq); EXPORT_SYMBOL(update_devfreq);
...@@ -657,6 +671,9 @@ struct devfreq *devfreq_add_device(struct device *dev, ...@@ -657,6 +671,9 @@ struct devfreq *devfreq_add_device(struct device *dev,
} }
devfreq->max_freq = devfreq->scaling_max_freq; devfreq->max_freq = devfreq->scaling_max_freq;
devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
atomic_set(&devfreq->suspend_count, 0);
dev_set_name(&devfreq->dev, "devfreq%d", dev_set_name(&devfreq->dev, "devfreq%d",
atomic_inc_return(&devfreq_no)); atomic_inc_return(&devfreq_no));
err = device_register(&devfreq->dev); err = device_register(&devfreq->dev);
...@@ -857,14 +874,28 @@ EXPORT_SYMBOL(devm_devfreq_remove_device); ...@@ -857,14 +874,28 @@ EXPORT_SYMBOL(devm_devfreq_remove_device);
*/ */
int devfreq_suspend_device(struct devfreq *devfreq) int devfreq_suspend_device(struct devfreq *devfreq)
{ {
int ret;
if (!devfreq) if (!devfreq)
return -EINVAL; return -EINVAL;
if (!devfreq->governor) if (atomic_inc_return(&devfreq->suspend_count) > 1)
return 0; return 0;
return devfreq->governor->event_handler(devfreq, if (devfreq->governor) {
DEVFREQ_GOV_SUSPEND, NULL); ret = devfreq->governor->event_handler(devfreq,
DEVFREQ_GOV_SUSPEND, NULL);
if (ret)
return ret;
}
if (devfreq->suspend_freq) {
ret = devfreq_set_target(devfreq, devfreq->suspend_freq, 0);
if (ret)
return ret;
}
return 0;
} }
EXPORT_SYMBOL(devfreq_suspend_device); EXPORT_SYMBOL(devfreq_suspend_device);
...@@ -878,17 +909,75 @@ EXPORT_SYMBOL(devfreq_suspend_device); ...@@ -878,17 +909,75 @@ EXPORT_SYMBOL(devfreq_suspend_device);
*/ */
int devfreq_resume_device(struct devfreq *devfreq) int devfreq_resume_device(struct devfreq *devfreq)
{ {
int ret;
if (!devfreq) if (!devfreq)
return -EINVAL; return -EINVAL;
if (!devfreq->governor) if (atomic_dec_return(&devfreq->suspend_count) >= 1)
return 0; return 0;
return devfreq->governor->event_handler(devfreq, if (devfreq->resume_freq) {
DEVFREQ_GOV_RESUME, NULL); ret = devfreq_set_target(devfreq, devfreq->resume_freq, 0);
if (ret)
return ret;
}
if (devfreq->governor) {
ret = devfreq->governor->event_handler(devfreq,
DEVFREQ_GOV_RESUME, NULL);
if (ret)
return ret;
}
return 0;
} }
EXPORT_SYMBOL(devfreq_resume_device); EXPORT_SYMBOL(devfreq_resume_device);
/**
* devfreq_suspend() - Suspend devfreq governors and devices
*
* Called during system wide Suspend/Hibernate cycles for suspending governors
* and devices preserving the state for resume. On some platforms the devfreq
* device must have precise state (frequency) after resume in order to provide
* fully operating setup.
*/
void devfreq_suspend(void)
{
struct devfreq *devfreq;
int ret;
mutex_lock(&devfreq_list_lock);
list_for_each_entry(devfreq, &devfreq_list, node) {
ret = devfreq_suspend_device(devfreq);
if (ret)
dev_err(&devfreq->dev,
"failed to suspend devfreq device\n");
}
mutex_unlock(&devfreq_list_lock);
}
/**
* devfreq_resume() - Resume devfreq governors and devices
*
* Called during system wide Suspend/Hibernate cycle for resuming governors and
* devices that are suspended with devfreq_suspend().
*/
void devfreq_resume(void)
{
struct devfreq *devfreq;
int ret;
mutex_lock(&devfreq_list_lock);
list_for_each_entry(devfreq, &devfreq_list, node) {
ret = devfreq_resume_device(devfreq);
if (ret)
dev_warn(&devfreq->dev,
"failed to resume devfreq device\n");
}
mutex_unlock(&devfreq_list_lock);
}
/** /**
* devfreq_add_governor() - Add devfreq governor * devfreq_add_governor() - Add devfreq governor
* @governor: the devfreq governor to be added * @governor: the devfreq governor to be added
......
// SPDX-License-Identifier: GPL-2.0
/* /*
* OMAP SmartReflex Voltage Control * OMAP SmartReflex Voltage Control
* *
...@@ -11,10 +12,6 @@ ...@@ -11,10 +12,6 @@
* *
* Copyright (C) 2007 Texas Instruments, Inc. * Copyright (C) 2007 Texas Instruments, Inc.
* Lesly A M <x0080970@ti.com> * Lesly A M <x0080970@ti.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -37,7 +34,6 @@ ...@@ -37,7 +34,6 @@
static LIST_HEAD(sr_list); static LIST_HEAD(sr_list);
static struct omap_sr_class_data *sr_class; static struct omap_sr_class_data *sr_class;
static struct omap_sr_pmic_data *sr_pmic_data;
static struct dentry *sr_dbg_dir; static struct dentry *sr_dbg_dir;
static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value) static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
...@@ -780,25 +776,6 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm) ...@@ -780,25 +776,6 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
sr_class->disable(sr, 1); sr_class->disable(sr, 1);
} }
/**
* omap_sr_register_pmic() - API to register pmic specific info.
* @pmic_data: The structure containing pmic specific data.
*
* This API is to be called from the PMIC specific code to register with
* smartreflex driver pmic specific info. Currently the only info required
* is the smartreflex init on the PMIC side.
*/
void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data)
{
if (!pmic_data) {
pr_warn("%s: Trying to register NULL PMIC data structure with smartreflex\n",
__func__);
return;
}
sr_pmic_data = pmic_data;
}
/* PM Debug FS entries to enable and disable smartreflex. */ /* PM Debug FS entries to enable and disable smartreflex. */
static int omap_sr_autocomp_show(void *data, u64 *val) static int omap_sr_autocomp_show(void *data, u64 *val)
{ {
...@@ -1010,8 +987,7 @@ static int omap_sr_remove(struct platform_device *pdev) ...@@ -1010,8 +987,7 @@ static int omap_sr_remove(struct platform_device *pdev)
if (sr_info->autocomp_active) if (sr_info->autocomp_active)
sr_stop_vddautocomp(sr_info); sr_stop_vddautocomp(sr_info);
if (sr_info->dbg_dir) debugfs_remove_recursive(sr_info->dbg_dir);
debugfs_remove_recursive(sr_info->dbg_dir);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
list_del(&sr_info->node); list_del(&sr_info->node);
...@@ -1065,17 +1041,6 @@ static int __init sr_init(void) ...@@ -1065,17 +1041,6 @@ static int __init sr_init(void)
{ {
int ret = 0; int ret = 0;
/*
* sr_init is a late init. If by then a pmic specific API is not
* registered either there is no need for anything to be done on
* the PMIC side or somebody has forgotten to register a PMIC
* handler. Warn for the second condition.
*/
if (sr_pmic_data && sr_pmic_data->sr_pmic_init)
sr_pmic_data->sr_pmic_init();
else
pr_warn("%s: No PMIC hook to init smartreflex\n", __func__);
ret = platform_driver_register(&smartreflex_driver); ret = platform_driver_register(&smartreflex_driver);
if (ret) { if (ret) {
pr_err("%s: platform driver register failed for SR\n", pr_err("%s: platform driver register failed for SR\n",
......
...@@ -131,6 +131,9 @@ struct devfreq_dev_profile { ...@@ -131,6 +131,9 @@ struct devfreq_dev_profile {
* @scaling_min_freq: Limit minimum frequency requested by OPP interface * @scaling_min_freq: Limit minimum frequency requested by OPP interface
* @scaling_max_freq: Limit maximum frequency requested by OPP interface * @scaling_max_freq: Limit maximum frequency requested by OPP interface
* @stop_polling: devfreq polling status of a device. * @stop_polling: devfreq polling status of a device.
* @suspend_freq: frequency of a device set during suspend phase.
* @resume_freq: frequency of a device set in resume phase.
* @suspend_count: suspend requests counter for a device.
* @total_trans: Number of devfreq transitions * @total_trans: Number of devfreq transitions
* @trans_table: Statistics of devfreq transitions * @trans_table: Statistics of devfreq transitions
* @time_in_state: Statistics of devfreq states * @time_in_state: Statistics of devfreq states
...@@ -167,6 +170,10 @@ struct devfreq { ...@@ -167,6 +170,10 @@ struct devfreq {
unsigned long scaling_max_freq; unsigned long scaling_max_freq;
bool stop_polling; bool stop_polling;
unsigned long suspend_freq;
unsigned long resume_freq;
atomic_t suspend_count;
/* information for device frequency transition */ /* information for device frequency transition */
unsigned int total_trans; unsigned int total_trans;
unsigned int *trans_table; unsigned int *trans_table;
...@@ -198,6 +205,9 @@ extern void devm_devfreq_remove_device(struct device *dev, ...@@ -198,6 +205,9 @@ extern void devm_devfreq_remove_device(struct device *dev,
extern int devfreq_suspend_device(struct devfreq *devfreq); extern int devfreq_suspend_device(struct devfreq *devfreq);
extern int devfreq_resume_device(struct devfreq *devfreq); extern int devfreq_resume_device(struct devfreq *devfreq);
extern void devfreq_suspend(void);
extern void devfreq_resume(void);
/** /**
* update_devfreq() - Reevaluate the device and configure frequency * update_devfreq() - Reevaluate the device and configure frequency
* @devfreq: the devfreq device * @devfreq: the devfreq device
...@@ -324,6 +334,9 @@ static inline int devfreq_resume_device(struct devfreq *devfreq) ...@@ -324,6 +334,9 @@ static inline int devfreq_resume_device(struct devfreq *devfreq)
return 0; return 0;
} }
static inline void devfreq_suspend(void) {}
static inline void devfreq_resume(void) {}
static inline struct dev_pm_opp *devfreq_recommended_opp(struct device *dev, static inline struct dev_pm_opp *devfreq_recommended_opp(struct device *dev,
unsigned long *freq, u32 flags) unsigned long *freq, u32 flags)
{ {
......
/* SPDX-License-Identifier: GPL-2.0 */
/* /*
* OMAP Smartreflex Defines and Routines * OMAP Smartreflex Defines and Routines
* *
...@@ -11,10 +12,6 @@ ...@@ -11,10 +12,6 @@
* *
* Copyright (C) 2007 Texas Instruments, Inc. * Copyright (C) 2007 Texas Instruments, Inc.
* Lesly A M <x0080970@ti.com> * Lesly A M <x0080970@ti.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/ */
#ifndef __POWER_SMARTREFLEX_H #ifndef __POWER_SMARTREFLEX_H
...@@ -303,9 +300,6 @@ void omap_sr_enable(struct voltagedomain *voltdm); ...@@ -303,9 +300,6 @@ void omap_sr_enable(struct voltagedomain *voltdm);
void omap_sr_disable(struct voltagedomain *voltdm); void omap_sr_disable(struct voltagedomain *voltdm);
void omap_sr_disable_reset_volt(struct voltagedomain *voltdm); void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
/* API to register the pmic specific data with the smartreflex driver. */
void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);
/* Smartreflex driver hooks to be called from Smartreflex class driver */ /* Smartreflex driver hooks to be called from Smartreflex class driver */
int sr_enable(struct omap_sr *sr, unsigned long volt); int sr_enable(struct omap_sr *sr, unsigned long volt);
void sr_disable(struct omap_sr *sr); void sr_disable(struct omap_sr *sr);
...@@ -320,7 +314,5 @@ static inline void omap_sr_enable(struct voltagedomain *voltdm) {} ...@@ -320,7 +314,5 @@ static inline void omap_sr_enable(struct voltagedomain *voltdm) {}
static inline void omap_sr_disable(struct voltagedomain *voltdm) {} static inline void omap_sr_disable(struct voltagedomain *voltdm) {}
static inline void omap_sr_disable_reset_volt( static inline void omap_sr_disable_reset_volt(
struct voltagedomain *voltdm) {} struct voltagedomain *voltdm) {}
static inline void omap_sr_register_pmic(
struct omap_sr_pmic_data *pmic_data) {}
#endif #endif
#endif #endif
...@@ -89,6 +89,7 @@ endif ...@@ -89,6 +89,7 @@ endif
localedir ?= /usr/share/locale localedir ?= /usr/share/locale
docdir ?= /usr/share/doc/packages/cpupower docdir ?= /usr/share/doc/packages/cpupower
confdir ?= /etc/ confdir ?= /etc/
bash_completion_dir ?= /usr/share/bash-completion/completions
# Toolchain: what tools do we use, and what options do they need: # Toolchain: what tools do we use, and what options do they need:
...@@ -96,7 +97,8 @@ CP = cp -fpR ...@@ -96,7 +97,8 @@ CP = cp -fpR
INSTALL = /usr/bin/install -c INSTALL = /usr/bin/install -c
INSTALL_PROGRAM = ${INSTALL} INSTALL_PROGRAM = ${INSTALL}
INSTALL_DATA = ${INSTALL} -m 644 INSTALL_DATA = ${INSTALL} -m 644
INSTALL_SCRIPT = ${INSTALL_PROGRAM} #bash completion scripts get sourced and so they should be rw only.
INSTALL_SCRIPT = ${INSTALL} -m 644
# If you are running a cross compiler, you may want to set this # If you are running a cross compiler, you may want to set this
# to something more interesting, like "arm-linux-". If you want # to something more interesting, like "arm-linux-". If you want
...@@ -288,6 +290,8 @@ install-lib: ...@@ -288,6 +290,8 @@ install-lib:
install-tools: install-tools:
$(INSTALL) -d $(DESTDIR)${bindir} $(INSTALL) -d $(DESTDIR)${bindir}
$(INSTALL_PROGRAM) $(OUTPUT)cpupower $(DESTDIR)${bindir} $(INSTALL_PROGRAM) $(OUTPUT)cpupower $(DESTDIR)${bindir}
$(INSTALL) -d $(DESTDIR)${bash_completion_dir}
$(INSTALL_SCRIPT) cpupower-completion.sh '$(DESTDIR)${bash_completion_dir}/cpupower'
install-man: install-man:
$(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1 $(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1
......
# -*- shell-script -*-
# bash completion script for cpupower
# Taken from git.git's completion script.
_cpupower_commands="frequency-info frequency-set idle-info idle-set set info monitor"
_frequency_info ()
{
local flags="-f -w -l -d -p -g -a -s -y -o -m -n --freq --hwfreq --hwlimits --driver --policy --governors --related-cpus --affected-cpus --stats --latency --proc --human --no-rounding"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
local cur="${COMP_WORDS[COMP_CWORD]}"
case "$prev" in
frequency-info) COMPREPLY=($(compgen -W "$flags" -- "$cur")) ;;
esac
}
_frequency_set ()
{
local flags="-f -g --freq --governor -d --min -u --max -r --related"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
local cur="${COMP_WORDS[COMP_CWORD]}"
case "$prev" in
-f| --freq | -d | --min | -u | --max)
if [ -d /sys/devices/system/cpu/cpufreq/ ] ; then
COMPREPLY=($(compgen -W '$(cat $(ls -d /sys/devices/system/cpu/cpufreq/policy* | head -1)/scaling_available_frequencies)' -- "$cur"))
fi ;;
-g| --governor)
if [ -d /sys/devices/system/cpu/cpufreq/ ] ; then
COMPREPLY=($(compgen -W '$(cat $(ls -d /sys/devices/system/cpu/cpufreq/policy* | head -1)/scaling_available_governors)' -- "$cur"))
fi;;
frequency-set) COMPREPLY=($(compgen -W "$flags" -- "$cur")) ;;
esac
}
_idle_info()
{
local flags="-f --silent"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
local cur="${COMP_WORDS[COMP_CWORD]}"
case "$prev" in
idle-info) COMPREPLY=($(compgen -W "$flags" -- "$cur")) ;;
esac
}
_idle_set()
{
local flags="-d --disable -e --enable -D --disable-by-latency -E --enable-all"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
local cur="${COMP_WORDS[COMP_CWORD]}"
case "$prev" in
idle-set) COMPREPLY=($(compgen -W "$flags" -- "$cur")) ;;
esac
}
_set()
{
local flags="--perf-bias, -b"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
local cur="${COMP_WORDS[COMP_CWORD]}"
case "$prev" in
set) COMPREPLY=($(compgen -W "$flags" -- "$cur")) ;;
esac
}
_monitor()
{
local flags="-l -m -i -c -v"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
local cur="${COMP_WORDS[COMP_CWORD]}"
case "$prev" in
monitor) COMPREPLY=($(compgen -W "$flags" -- "$cur")) ;;
esac
}
_taskset()
{
local prev_to_prev="${COMP_WORDS[COMP_CWORD-2]}"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
local cur="${COMP_WORDS[COMP_CWORD]}"
case "$prev_to_prev" in
-c|--cpu) COMPREPLY=($(compgen -W "$_cpupower_commands" -- "$cur")) ;;
esac
case "$prev" in
frequency-info) _frequency_info ;;
frequency-set) _frequency_set ;;
idle-info) _idle_info ;;
idle-set) _idle_set ;;
set) _set ;;
monitor) _monitor ;;
esac
}
_cpupower ()
{
local i
local c=1
local command
while test $c -lt $COMP_CWORD; do
if test $c == 1; then
command="${COMP_WORDS[c]}"
fi
c=$((++c))
done
# Complete name of subcommand if the user has not finished typing it yet.
if test $c -eq $COMP_CWORD -a -z "$command"; then
COMPREPLY=($(compgen -W "help -v --version -c --cpu $_cpupower_commands" -- "${COMP_WORDS[COMP_CWORD]}"))
return
fi
# Complete arguments to subcommands.
case "$command" in
-v|--version) return ;;
-c|--cpu) _taskset ;;
help) COMPREPLY=($(compgen -W "$_cpupower_commands" -- "${COMP_WORDS[COMP_CWORD]}")) ;;
frequency-info) _frequency_info ;;
frequency-set) _frequency_set ;;
idle-info) _idle_info ;;
idle-set) _idle_set ;;
set) _set ;;
monitor) _monitor ;;
esac
}
complete -o bashdefault -o default -F _cpupower cpupower 2>/dev/null \
|| complete -o default -F _cpupower cpupower
...@@ -585,9 +585,9 @@ current_max_cpu = 0 ...@@ -585,9 +585,9 @@ current_max_cpu = 0
read_trace_data(filename) read_trace_data(filename)
clear_trace_file()
# Free the memory
if interval: if interval:
clear_trace_file()
# Free the memory
free_trace_buffer() free_trace_buffer()
if graph_data_present == False: if graph_data_present == False:
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment