Index | Thread | Search

From:
Avon Robertson <avon.r@xtra.co.nz>
Subject:
Re: scmi: hook up to cpu_* to get apm working
To:
tech@openbsd.org
Date:
Fri, 23 May 2025 20:40:32 +1200

Download raw body.

Thread
  • Avon Robertson:

    scmi: hook up to cpu_* to get apm working

  • Hello Tobias, please see below.
    
    On Thu, May 22, 2025 at 07:16:17AM +0200, Tobias Heider wrote:
    > On Snapdragon X Elite chips we have to use ARM SCMI to control cpu performance.
    > Our driver now supports reading the current performance level, translating
    > it to HZ and exporting it as a sensor as well as setting initial levels.
    > 
    > I think it is time to hook everything up to cpu_setperf and cpu_clockspeed to
    > make those controls available to apm and hw.setperf.
    > Loosely inspired by aplcpu which deals with a similar problem on Apple machines.
    > 
    > ok? test feedback?
    > 
    > Index: scmi.c
    > ===================================================================
    > RCS file: /cvs/src/sys/dev/fdt/scmi.c,v
    > diff -u -p -r1.3 scmi.c
    > --- scmi.c	22 May 2025 03:04:01 -0000	1.3
    > +++ scmi.c	22 May 2025 03:37:38 -0000
    > @@ -484,6 +484,9 @@ int	scmi_perf_level_get(struct scmi_soft
    >  int	scmi_perf_level_set(struct scmi_softc *, int, int);
    >  void	scmi_perf_refresh_sensor(void *);
    >  
    > +int	scmi_perf_cpuspeed(int *);
    > +void	scmi_perf_cpusetperf(int);
    > +
    >  void
    >  scmi_attach_perf(struct scmi_softc *sc, int node)
    >  {
    > @@ -558,6 +561,10 @@ scmi_attach_perf(struct scmi_softc *sc, 
    >  	}
    >  	sensordev_install(&sc->sc_perf_sensordev);
    >  	sensor_task_register(sc, scmi_perf_refresh_sensor, 1);
    > +
    > +	cpu_setperf = scmi_perf_cpusetperf;
    > +	cpu_cpuspeed = scmi_perf_cpuspeed;
    A
    > +
    >  	return;
    >  err:
    >  	free(sc->sc_perf_fsensors, M_DEVBUF,
    > @@ -647,6 +654,63 @@ scmi_perf_level_set(struct scmi_softc *s
    >  		return -1;
    >  	}
    >  	return 0;
    > +}
    > +
    > +int
    > +scmi_perf_cpuspeed(int *freq)
    > +{
    > +	struct scmi_softc *sc;
    > +	int i, level = -1;
    > +	uint64_t opp_hz = 0;
    > +
    > +        for (i = 0; i < scmi_cd.cd_ndevs; i++) {
    > +                sc = scmi_cd.cd_devs[i];
    > +                if (sc == NULL)
    > +                        continue;
    > +
    > +		if (sc->sc_perf_domains == NULL)
    > +			continue;
    > +
    > +		for (i = 0; i < sc->sc_perf_ndomains; i++) {
    > +			if (sc->sc_perf_domains[i].pd_levels == NULL)
    > +				return EINVAL;
    > +
    > +			level = scmi_perf_level_get(sc, i);
    > +			opp_hz = MAX(opp_hz, (uint64_t)sc->sc_perf_domains[i].
    > +		    	    pd_levels[level].pl_ifreq * 1000);
    > +		}
    > +	}
    > +
    > +	if (opp_hz == 0)
    > +		return EINVAL;
    > +
    > +	*freq = opp_hz / 1000000;
    > +	return 0;
    > +}
    > +
    > +void
    > +scmi_perf_cpusetperf(int level)
    > +{
    > +	struct scmi_softc *sc;
    > +	size_t nlevels;
    > +	int i;
    > +
    > +        for (i = 0; i < scmi_cd.cd_ndevs; i++) {
    > +                sc = scmi_cd.cd_devs[i];
    > +                if (sc == NULL)
    > +			return;
    > +		if (sc->sc_perf_domains == NULL)
    > +			continue;
    > +
    > +		/* Find number of levels per domain */
    > +		for (i = 0; i < sc->sc_perf_ndomains; i++) {
    > +			nlevels = sc->sc_perf_domains[i].pd_nlevels;
    > +			if (nlevels == 0)
    > +				continue;
    > +			scmi_perf_level_set(sc, i,
    > +			    (level * (nlevels - 1) / 100));
    > +		}
    > +	}
    >  }
    >  
    >  void
    > 
    
    The below information was captured from an ASUS Vivobook S 15
    S5507QA_S5507QAD.
    
    Before patch applied.
    
    $ sysctl kern.version              
    kern.version=OpenBSD 7.7-current (GENERIC.MP) #382: Wed May 21 02:40:23 MDT 2025
        deraadt@arm64.openbsd.org:/usr/src/sys/arch/arm64/compile/GENERIC.MP
    
    
    $ sysctl hw.sensors | tail -n 6
    hw.sensors.scmi0.power0=0.23 W
    hw.sensors.scmi0.power1=0.33 W
    hw.sensors.scmi0.power2=0.36 W
    hw.sensors.scmi0.frequency0=2976000000.00 Hz
    hw.sensors.scmi0.frequency1=3417600000.00 Hz
    hw.sensors.scmi0.frequency2=3417600000.00 Hz
    
    $ sysctl hw.cpuspeed
    sysctl: hw.cpuspeed: value is not available
    
    $ sysctl hw.setperf  
    sysctl: hw.setperf: value is not available
    
    $ sysctl hw.perfpolicy
    sysctl: hw.perfpolicy: value is not available
    
    After patch applied
    
    $ sysctl kern.version              
    kern.version=OpenBSD 7.7-current (GENERIC.MP) #0: Fri May 23 12:32:09 NZST 2025
        aer@lts15.xan.priv:/sys/arch/arm64/compile/GENERIC.MP
    
    $ sysctl hw.sensors | tail -n 6
    hw.sensors.scmi0.power0=0.34 W
    hw.sensors.scmi0.power1=0.33 W
    hw.sensors.scmi0.power2=0.36 W
    hw.sensors.scmi0.frequency0=3417600000.00 Hz
    hw.sensors.scmi0.frequency1=3417600000.00 Hz
    hw.sensors.scmi0.frequency2=3417600000.00 Hz
    
    $ sysctl hw.cpuspeed
    hw.cpuspeed=3417
    
    $ sysctl hw.setperf  
    hw.setperf=100
    
    $ sysctl hw.perfpolicy
    hw.perfpolicy=high
    
    This may be helpful to you too.
    
    Guided by release(8) I also tried to build base without rebooting, and
    after a 'halt -p / and a cold restart'.  Both ended as shown at the 
    end of the following text that was captured from/in the tmux pane the
    build was attempted.
    
    The base build attempt was also perfomed as root.
    
    rm -f a.out [Ee]rrs mklog *.core y.tab.h       *.o *.out  
    ===> regress/misc/exceptions
    ===> regress/misc/exceptions/simple
    rm -f a.out [Ee]rrs mklog *.core y.tab.h  exceptions  exceptions.o    exceptions.d
    rm -f /usr/src/regress/misc/exceptions/simple/tags
    ===> regress/misc/exceptions/simple2
    rm -f a.out [Ee]rrs mklog *.core y.tab.h  simple2  simple2.o    simple2.d
    rm -f /usr/src/regress/misc/exceptions/simple2/tags
    ===> regress/misc/exceptions/libbar
    rm -f a.out [Ee]rrs mklog *.core y.tab.h     bar.d
    rm -f libbar.a bar.o
    rm -f libbar_g.a 
    rm -f libbar_p.a bar.po
    rm -f libbar.so.*.* bar.so .ldadd
    rm -f libbar_d.a bar.do
    rm -f /usr/src/regress/misc/exceptions/libbar/tags
    ===> regress/misc/exceptions/foo
    rm -f a.out [Ee]rrs mklog *.core y.tab.h  foo  foo.o    foo.d
    rm -f /usr/src/regress/misc/exceptions/foo/tags
    ===> regress/misc/exceptions/threads
    rm -f a.out [Ee]rrs mklog *.core y.tab.h  exceptions  exceptions.o    exceptions.d
    rm -f /usr/src/regress/misc/exceptions/threads/tags
    ===> regress/misc/os-test
    rm -f uname.out os-test.html
    rm -rf io io.expect udp udp.expect
    ===> regress/misc/posixtestsuite
    rm -f logfile *.log uname.out posixtestsuite.html
    rm -rf conformance functional
    ===> regress/misc/sse2
    ===> regress/gnu
    ===> regress/gnu/egcs
    ===> regress/gnu/egcs/gcc-bounds
    rm -f a.out [Ee]rrs mklog *.core y.tab.h        
    ===> regress/gnu/egcs/gcc-builtins
    rm -f a.out [Ee]rrs mklog *.core y.tab.h        
    ===> regress/gnu/lib
    ===> regress/gnu/lib/libexecinfo
    rm -f a.out [Ee]rrs mklog *.core y.tab.h  t_backtrace  t_backtrace.o atf-c.o    t_backtrace.d atf-c.d
    rm -f /usr/src/regress/gnu/lib/libexecinfo/tags
    exec make includes
    cd /usr/src/include &&  su build -c 'exec make prereq' &&  exec make includes
    make: getcwd: Permission denied		<<<<<<
    *** Error 2 in . (Makefile:55 'includes')
    *** Error 2 in . (Makefile:87 'do-build')
    *** Error 2 in /usr/src (Makefile:74 'build')
    lts15:/usr/src
    # gtmuxpane /root/base_build.err
    
    Note: there is no getcwd binary on this system.
    
    -- 
    aer
    
    
  • Avon Robertson:

    scmi: hook up to cpu_* to get apm working