@@ -46,6 +46,17 @@ type FanController interface {
4646
4747 // UpdateCurve dynamically updates the curve reference
4848 UpdateCurve (curve curves.SpeedCurve )
49+
50+ // RunInitialization runs the fan initialization sequence.
51+ RunInitialization (ctx context.Context ) (map [int ]float64 , error )
52+ }
53+
54+ type FanStateSnapshot struct {
55+ // the ControlMode the fan was in before the controller started
56+ ControlMode fans.ControlMode
57+ // the raw pwm value read from the fan before the controller started
58+ // Note: this is the raw value, no pwmMap is applied to it
59+ PwmValue int
4960}
5061
5162type DefaultFanController struct {
@@ -61,11 +72,8 @@ type DefaultFanController struct {
6172 curve curves.SpeedCurve
6273 // rate to update the target fan speed
6374 updateRate time.Duration
64- // the original ControlMode state of the fan before starting the controller
65- originalControlMode fans.ControlMode
66- // the original pwm value of the fan before starting the controller
67- // Note: this is the raw value read from the fan, no pwmMap is applied to it
68- originalPwmValue int
75+ // the fan state as it was before the controller started (nil until captured)
76+ originalFanState * FanStateSnapshot
6977 // the last pwm value that was set to the fan, **before** applying the pwmMap to it
7078 lastTarget * int
7179 // a list of all pre-pwmMap pwm values where setPwm(x) != setPwm(y) for the controlled fan
@@ -180,26 +188,45 @@ func (f *DefaultFanController) prepareController() (err error) {
180188 return err
181189}
182190
191+ // storeCurrentFanState captures the current fan control mode and PWM value,
192+ // overwriting any previously saved snapshot in originalFanState.
183193func (f * DefaultFanController ) storeCurrentFanState () error {
184194 fan := f .fan
185195 // store original pwm value
186196 pwm , err := f .getPwm ()
187197 if err != nil {
188198 ui .Warning ("Cannot read pwm value of %s" , fan .GetId ())
189199 }
190- f .originalPwmValue = pwm
200+ snapshot := FanStateSnapshot {
201+ PwmValue : pwm ,
202+ }
191203
192204 // store original pwm_enable value
193205 if f .fan .Supports (fans .FeatureControlModeRead ) {
194206 controlMode , err := fan .GetControlMode ()
195207 if err != nil {
196208 ui .Warning ("Cannot read pwm_enable value of %s" , fan .GetId ())
197209 }
198- f . originalControlMode = controlMode
210+ snapshot . ControlMode = controlMode
199211 }
212+ f .originalFanState = & snapshot
200213 return nil
201214}
202215
216+ // storeInitialFanState stores the initial fan state snapshot if it hasn't been captured yet.
217+ // Subsequent calls are no-ops to preserve the state before any controller actions.
218+ func (f * DefaultFanController ) storeInitialFanState () error {
219+ if f .originalFanState != nil {
220+ return nil
221+ }
222+ return f .storeCurrentFanState ()
223+ }
224+
225+ // clearInitialFanState resets the captured initial fan state snapshot.
226+ func (f * DefaultFanController ) clearInitialFanState () {
227+ f .originalFanState = nil
228+ }
229+
203230func (f * DefaultFanController ) Run (ctx context.Context ) error {
204231 // prepare the controller by initializing persistence and checking the fan
205232 err := f .prepareController ()
@@ -208,7 +235,7 @@ func (f *DefaultFanController) Run(ctx context.Context) error {
208235 }
209236
210237 // store the current fan state to restore it when stopping the controller
211- err = f .storeCurrentFanState ()
238+ err = f .storeInitialFanState ()
212239 if err != nil {
213240 return err
214241 }
@@ -219,7 +246,7 @@ func (f *DefaultFanController) Run(ctx context.Context) error {
219246 // wait a bit to gather monitoring data
220247 time .Sleep (2 * time .Second + configuration .CurrentConfig .TempSensorPollingRate )
221248
222- fanPwmData , err := f .runInitializationIfNeeded ()
249+ fanPwmData , err := f .runInitializationIfNeeded (ctx )
223250 if err != nil {
224251 return err
225252 }
@@ -332,7 +359,7 @@ func (f *DefaultFanController) Run(ctx context.Context) error {
332359 return err
333360}
334361
335- func (f * DefaultFanController ) runInitializationIfNeeded () (map [int ]float64 , error ) {
362+ func (f * DefaultFanController ) runInitializationIfNeeded (ctx context. Context ) (map [int ]float64 , error ) {
336363 fan := f .fan
337364 // check if we have data for this fan in persistence,
338365 // if not we need to run the initialization sequence
@@ -342,7 +369,7 @@ func (f *DefaultFanController) runInitializationIfNeeded() (map[int]float64, err
342369 config := fan .GetConfig ()
343370 if config .HwMon != nil || config .Nvidia != nil {
344371 ui .Warning ("Fan '%s' has not yet been analyzed, starting initialization sequence..." , fan .GetId ())
345- fanCurveData , err := f .RunInitialization ()
372+ fanCurveData , err := f .RunInitialization (ctx )
346373 if err != nil {
347374 return nil , err
348375 }
@@ -356,7 +383,21 @@ func (f *DefaultFanController) runInitializationIfNeeded() (map[int]float64, err
356383 return fanRpmData , err
357384}
358385
359- func (f * DefaultFanController ) RunInitialization () (map [int ]float64 , error ) {
386+ func (f * DefaultFanController ) RunInitialization (ctx context.Context ) (map [int ]float64 , error ) {
387+ err := f .storeInitialFanState ()
388+ if err != nil {
389+ return nil , err
390+ }
391+
392+ curveData , err := f .runInitialization (ctx )
393+ if err != nil {
394+ f .restoreControlMode ()
395+ return nil , err
396+ }
397+ return curveData , nil
398+ }
399+
400+ func (f * DefaultFanController ) runInitialization (ctx context.Context ) (map [int ]float64 , error ) {
360401 fan := f .fan
361402
362403 err := f .computeFanSpecificMappings ()
@@ -366,9 +407,8 @@ func (f *DefaultFanController) RunInitialization() (map[int]float64, error) {
366407 }
367408
368409 fanAnalyzer := NewFanCurveAnalyzer (f )
369- curveData , err := fanAnalyzer .RunInitializationSequence ()
410+ curveData , err := fanAnalyzer .RunInitializationSequence (ctx )
370411 if err != nil {
371- f .restoreControlMode ()
372412 return nil , err
373413 }
374414
@@ -389,7 +429,6 @@ func (f *DefaultFanController) RunInitialization() (map[int]float64, error) {
389429
390430 fanRpmData , err := f .persistence .LoadFanRpmData (fan )
391431 if err != nil {
392- f .restoreControlMode ()
393432 return nil , err
394433 }
395434
@@ -582,6 +621,13 @@ func trySetManualPwm(fan fans.Fan) error {
582621}
583622
584623func (f * DefaultFanController ) restoreControlMode () {
624+ if f .originalFanState == nil {
625+ ui .Warning ("Skipping fan settings restore for %s, original state was never captured" , f .fan .GetId ())
626+ return
627+ }
628+ originalControlMode := f .originalFanState .ControlMode
629+ originalPwmValue := f .originalFanState .PwmValue
630+
585631 ui .Info ("Trying to restore fan settings for %s..." , f .fan .GetId ())
586632
587633 var onExit * configuration.OnExitConfig
@@ -602,7 +648,7 @@ func (f *DefaultFanController) restoreControlMode() {
602648 if onExit != nil {
603649 // determine control mode to set on exit, if any
604650 if onExit .Restore != nil {
605- controlModeToSet = & f . originalControlMode
651+ controlModeToSet = & originalControlMode
606652 } else if onExit .ControlMode != nil {
607653 parsedControlMode , err := parseControlModeValue (* onExit .ControlMode )
608654 if err != nil {
@@ -612,8 +658,8 @@ func (f *DefaultFanController) restoreControlMode() {
612658 }
613659 } else {
614660 // if no explicit control mode to set is provided, but the fan supports writing the control mode and the original mode was not automatic, restore the original mode
615- if f . originalControlMode != fans .ControlModeAutomatic {
616- controlModeToSet = & f . originalControlMode
661+ if originalControlMode != fans .ControlModeAutomatic {
662+ controlModeToSet = & originalControlMode
617663 }
618664 }
619665
@@ -623,14 +669,13 @@ func (f *DefaultFanController) restoreControlMode() {
623669 }
624670 } else {
625671 // default restore behavior
626- controlModeToSet = & f . originalControlMode
672+ controlModeToSet = & originalControlMode
627673 }
628674
629675 if pwmToSet == nil {
630676 // if the original control mode was manual, restore it to manual and set the original PWM value
631677 if controlModeToSet != nil && * controlModeToSet != fans .ControlModeAutomatic {
632678 // if control mode is set to manual but no speed is provided, set the original value
633- originalPwmValue := f .originalPwmValue
634679 pwmToSet = & originalPwmValue
635680 }
636681 }
0 commit comments