Resolve fan errors when they become functional

Add Witherspoon dbus-monitor rules to watch for fans becoming
functional, which will invoke the callback that resolves all errors
that called out that fan.

This will cause the fault LEDs to turn off when the fan
is replaced and spins back up to speed.

Resolves openbmc/openbmc#2513

Change-Id: I7f787854915ca2bb1b66508b343eaa137cede6fd
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/meta-openbmc-machines/meta-openpower/meta-ibm/meta-witherspoon/recipes-phosphor/fans/witherspoon-fan-policy/fan-errors.yaml b/meta-openbmc-machines/meta-openpower/meta-ibm/meta-witherspoon/recipes-phosphor/fans/witherspoon-fan-policy/fan-errors.yaml
index 1fa1530..d6aef5f 100644
--- a/meta-openbmc-machines/meta-openpower/meta-ibm/meta-witherspoon/recipes-phosphor/fans/witherspoon-fan-policy/fan-errors.yaml
+++ b/meta-openbmc-machines/meta-openpower/meta-ibm/meta-witherspoon/recipes-phosphor/fans/witherspoon-fan-policy/fan-errors.yaml
@@ -1,11 +1,15 @@
 # Witherspoon fan error policy for PDM.
 #
-# Create a NotPresent error if fan 0, 1, 2, or 3 is not present for more
-# than 20 seconds. Create a Nonfunctional error if fan 0, 1, 2, or 3 is not
-# functional for any amount of time.
+# * Create a NotPresent error if fan 0, 1, 2, or 3 is not present for more
+#   than 20 seconds.
+# * Create a Nonfunctional error if fan 0, 1, 2, or 3 is not
+#   functional for any amount of time.
+#
 # The system must be powered on in both of these cases.
 # If a water cooled system, don't create errors for fan 1.
 # Note: An error is created each time the chassis powers on.
+#
+# * Watch for fans to become functional, and then resolve their errors
 
 - name: fan0
   class: group
@@ -179,6 +183,42 @@
   properties: fan functional
   callback: check power fan3 functional
 
+- name: watch fan0 functional for resolving error logs
+  description: >
+    'On fan functional state changes, check if errors need to be resolved.'
+  class: watch
+  watch: property
+  paths: fan0
+  properties: fan functional
+  callback: resolve fan0 errors if functional
+
+- name: watch fan1 functional for resolving error logs
+  description: >
+    'On fan functional state changes, check if errors need to be resolved.'
+  class: watch
+  watch: property
+  paths: fan1
+  properties: fan functional
+  callback: resolve fan1 errors if functional
+
+- name: watch fan2 functional for resolving error logs
+  description: >
+    'On fan functional state changes, check if errors need to be resolved.'
+  class: watch
+  watch: property
+  paths: fan2
+  properties: fan functional
+  callback: resolve fan2 errors if functional
+
+- name: watch fan3 functional for resolving error logs
+  description: >
+    'On fan functional state changes, check if errors need to be resolved.'
+  class: watch
+  watch: property
+  paths: fan3
+  properties: fan functional
+  callback: resolve fan3 errors if functional
+
 - name: check power
   description: >
     'If the chassis has power, check all fans.'
@@ -539,3 +579,83 @@
       value: /xyz/openbmc_project/inventory/system/chassis/motherboard/fan3
       type: string
 
+- name: resolve fan0 errors if functional
+  description: >
+    'If fan0 is functional, call the resolve fan0 errors callback.'
+  class: condition
+  condition: count
+  paths: fan0
+  properties: fan functional
+  callback: resolve fan0 errors
+  countop: '>'
+  countbound: 0
+  op: '=='
+  bound: true
+
+#Go ahead and do this on water cooled as well
+- name: resolve fan1 errors if functional
+  description: >
+    'If fan1 is functional, call the resolve fan1 errors callback.'
+  class: condition
+  condition: count
+  paths: fan1
+  properties: fan functional
+  callback: resolve fan1 errors
+  countop: '>'
+  countbound: 0
+  op: '=='
+  bound: true
+
+- name: resolve fan2 errors if functional
+  description: >
+    'If fan2 is functional, call the resolve fan2 errors callback.'
+  class: condition
+  condition: count
+  paths: fan2
+  properties: fan functional
+  callback: resolve fan2 errors
+  countop: '>'
+  countbound: 0
+  op: '=='
+  bound: true
+
+- name: resolve fan3 errors if functional
+  description: >
+    'If fan3 is functional, call the resolve fan3 errors callback.'
+  class: condition
+  condition: count
+  paths: fan3
+  properties: fan functional
+  callback: resolve fan3 errors
+  countop: '>'
+  countbound: 0
+  op: '=='
+  bound: true
+
+- name: resolve fan0 errors
+  class: callback
+  callback: resolve callout
+  paths: fan0
+  properties: fan functional
+  callout: /xyz/openbmc_project/inventory/system/chassis/motherboard/fan0
+
+- name: resolve fan1 errors
+  class: callback
+  callback: resolve callout
+  paths: fan1
+  properties: fan functional
+  callout: /xyz/openbmc_project/inventory/system/chassis/motherboard/fan1
+
+- name: resolve fan2 errors
+  class: callback
+  callback: resolve callout
+  paths: fan2
+  properties: fan functional
+  callout: /xyz/openbmc_project/inventory/system/chassis/motherboard/fan2
+
+- name: resolve fan3 errors
+  class: callback
+  callback: resolve callout
+  paths: fan3
+  properties: fan functional
+  callout: /xyz/openbmc_project/inventory/system/chassis/motherboard/fan3