[PATCH v1 2/8] platform/mellanox: mlxreg-hotplug: Improve mechanism of ASIC health discovery

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Extend the logic of ASIC health discovery.
ASIC device can indicate its health state as a good, booting or dormant.
During ASIC reset the device is dropped to dormant state and should get to
the stable good health state through the intermediate booting state.
The sequence for getting to the steady state health after reset is:
dormant -> booting -> [booting -> good -> dormant -> booting] -> good.
The sequence in brackets can be repeated several times.
Initial implementation assumes that the this sequence is always repeated
by the constant number. This patch allows to perform health steady state
discovery independently of the repetitions number.

Signed-off-by: Vadim Pasternak <vadimp@xxxxxxxxxxxx>
---
 drivers/platform/mellanox/mlxreg-hotplug.c | 38 +++++++++++++++++++++++++++---
 1 file changed, 35 insertions(+), 3 deletions(-)

diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c
index ac97aa0..f32637e 100644
--- a/drivers/platform/mellanox/mlxreg-hotplug.c
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
@@ -51,8 +51,9 @@
 #define MLXREG_HOTPLUG_AGGR_MASK_OFF	1
 
 /* ASIC health parameters. */
+#define MLXREG_HOTPLUG_DOWN_MASK	0x00
 #define MLXREG_HOTPLUG_HEALTH_MASK	0x02
-#define MLXREG_HOTPLUG_RST_CNTR		3
+#define MLXREG_HOTPLUG_RST_CNTR		2
 
 #define MLXREG_HOTPLUG_ATTRS_MAX	24
 #define MLXREG_HOTPLUG_NOT_ASSERT	3
@@ -325,20 +326,51 @@ mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv,
 			goto out;
 
 		regval &= data->mask;
-		item->cache = regval;
+		/*
+		 * ASIC health indication is provided through two bits. Bits
+		 * value 0x2 indicates that ASIC reached the good health, value
+		 * 0x0 indicates ASIC the bad health or dormant state and value
+		 * 0x2 indicates the booting state. During ASIC reset it should
+		 * pass the following states: dormant -> booting -> good.
+		 * The transition from dormant to booting state and from
+		 * booting to good state are indicated by ASIC twice, so actual
+		 * sequence for getting to the steady state after reset is:
+		 * dormant -> booting -> booting -> good -> good. It is
+		 * possible that due to some hardware noise, the transition
+		 * sequence will look like: dormant -> booting -> [ booting ->
+		 * good -> dormant -> booting ] -> good -> good.
+		 */
 		if (regval == MLXREG_HOTPLUG_HEALTH_MASK) {
-			if ((data->health_cntr++ == MLXREG_HOTPLUG_RST_CNTR) ||
+			if ((++data->health_cntr == MLXREG_HOTPLUG_RST_CNTR) ||
 			    !priv->after_probe) {
+				/*
+				 * ASIC is in steady state. Connect associated
+				 * device, if configured.
+				 */
 				mlxreg_hotplug_device_create(priv, data);
 				data->attached = true;
 			}
 		} else {
 			if (data->attached) {
+				/*
+				 * ASIC health is dropped after ASIC has been
+				 * in steady state. Disconnect associated
+				 * device, if it has been connected.
+				 */
 				mlxreg_hotplug_device_destroy(data);
 				data->attached = false;
 				data->health_cntr = 0;
+			} else if (regval == MLXREG_HOTPLUG_DOWN_MASK &&
+				   item->cache == MLXREG_HOTPLUG_HEALTH_MASK) {
+				/*
+				 * Decrease counter, if health has been dropped
+				 * before ASIC reaches the steady state, like:
+				 * good -> dormant -> booting.
+				 */
+				data->health_cntr--;
 			}
 		}
+		item->cache = regval;
 
 		/* Acknowledge event. */
 		ret = regmap_write(priv->regmap, data->reg +
-- 
2.1.4




[Index of Archives]     [Linux Kernel Development]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux