https://bugs.freedesktop.org/show_bug.cgi?id=102646
George Scorer georgescorer@yahoo.co.uk changed:
What |Removed |Added ---------------------------------------------------------------------------- Priority|high |low Severity|major |minor
--- Comment #70 from George Scorer georgescorer@yahoo.co.uk --- Building on julien tempel's workaround, here's a somewhat more complex script to manage the memory p-state jumps. It switches between low and high memory p-states very reluctantly, so minimizing instances of flickering. I'm not a bash expert so please excuse the clumsy coding, but this works for me.
#!/bin/bash
# Each memory p-state switch causes a screen flicker. Tweak these variables to match # your personal 'flicker aversion' vs efficiency trade-off. CORE_P_STATE_UP=6 # The gpu core p-state at which we should jump up to memory p-state 2 CORE_P_STATE_DOWN=1 # The gpu core p-state at which we should drop down to low memory p-state UP_DELAY=2 # in seconds. How long to stay in low memory p-state before checking whether we can jump up to 2. DOWN_DELAY=10 # in seconds. How long to stay in memory p-state 2 before checking whether we can drop down to low. SLEEP_INTERVAL=1 # in seconds. How frequently we should poll the core p-state. LOW_MEM_STATE=0 # Choose between 0 & 1
# Sysfs paths here are hardcoded for one amdgpu card at card0; adjust as needed. FILE_PERF_LEVEL=/sys/class/drm/card0/device/power_dpm_force_performance_level FILE_MEM_P_STATE=/sys/class/drm/card0/device/pp_dpm_mclk FILE_CORE_P_STATE=/sys/class/drm/card0/device/pp_dpm_sclk
# check for root privileges if [ $UID -ne 0 ] then echo "Writing to sysfs requires root privileges; relaunch as root" exit 1 fi
# Set gpu performance level control to manual # echo "Setting performance level control to manual" echo "manual" > "$FILE_PERF_LEVEL"
# Read the current core p-state and set a corresponding initial memory p-state
CORE_P_STATE="$(grep -F '*' $FILE_CORE_P_STATE)" CORE_P_STATE=${CORE_P_STATE:0:1}
if [ "$CORE_P_STATE" -ge "$CORE_P_STATE_UP" ]; then MEM_P_STATE=2 else MEM_P_STATE=$LOW_MEM_STATE fi
echo "$MEM_P_STATE" > "$FILE_MEM_P_STATE" PROPOSED_MEM_P_STATE=$MEM_P_STATE
function check_core_p_state {
CORE_P_STATE="$(grep -F '*' $FILE_CORE_P_STATE)" CORE_P_STATE=${CORE_P_STATE:0:1}
# Propose what the corresponding memory p-state should be OLD_PROPOSED_MEM_P_STATE=$PROPOSED_MEM_P_STATE PROPOSED_MEM_P_STATE=$MEM_P_STATE if [ "$CORE_P_STATE" -ge "$CORE_P_STATE_UP" ]; then PROPOSED_MEM_P_STATE=2 elif [ "$CORE_P_STATE" -le "$CORE_P_STATE_DOWN" ]; then PROPOSED_MEM_P_STATE=$LOW_MEM_STATE fi
if [ "$PROPOSED_MEM_P_STATE" -ne "$MEM_P_STATE" ]; then # We want to change so determine where we are in the countdown. if [ "$PROPOSED_MEM_P_STATE" -ne "$OLD_PROPOSED_MEM_P_STATE" ]; then if [ "$PROPOSED_MEM_P_STATE" -eq 2 ]; then CHANGE_COUNTDOWN=$UP_DELAY else CHANGE_COUNTDOWN=$DOWN_DELAY fi fi (( CHANGE_COUNTDOWN = $CHANGE_COUNTDOWN - $SLEEP_INTERVAL ))
if [ $CHANGE_COUNTDOWN -le 0 ]; then # The countdown has reached 0 so change the memory p-state. MEM_P_STATE=$PROPOSED_MEM_P_STATE echo "$MEM_P_STATE" > "$FILE_MEM_P_STATE" fi # else # we don't want to change. fi
# echo "Old Prop Mem Core Countdown" # echo " $OLD_PROPOSED_MEM_P_STATE $PROPOSED_MEM_P_STATE $MEM_P_STATE $CORE_P_STATE $CHANGE_COUNTDOWN" # echo "" }
function reset_on_fail { echo "Exiting, setting memory p-state to 2" echo "manual" > "$FILE_PERF_LEVEL" echo "2" > "$FILE_MEM_P_STATE" exit 1 }
# always try to fix memory p-state 2 on failure trap "reset_on_fail" SIGINT SIGTERM
function run_daemon { while :; do sleep $SLEEP_INTERVAL check_core_p_state done }
# start the loop
run_daemon