From e23740bbebec60b8f8076491745f0e30dfb80cf3 Mon Sep 17 00:00:00 2001
From: Valentine Barshak <valentine.barshak@cogentembedded.com>
Date: Mon, 13 Aug 2018 15:13:52 +0300
Subject: [PATCH 060/122] media: i2c: soc_camera: Fix Bad of_node_put error

This fixes "OF: ERROR: Bad of_node_put()" error and possible kernel
crash when probing soc_camera sensor devices. When CONFIG_OF_DYNAMIC
is not enabled, bad of_node_put error is not displayed and everything
seems to work fine. However, there's an error in sensors' parse_dt
callbacks which causes inconsistent node reference counter management.

Move of_node_put() out of a loop scope to prevent bad of_node_put error.
We don't need to call of_node_put() for every node since subsequent
calls to of_graph_get_next_endpoint() decrement reference counter of
the previous node. We only need to call of_node_put() for the last node.

Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com>
---
 drivers/media/i2c/soc_camera/ap0101_ar014x.c | 4 ++--
 drivers/media/i2c/soc_camera/ar0132.c        | 4 ++--
 drivers/media/i2c/soc_camera/ar0220.c        | 3 ++-
 drivers/media/i2c/soc_camera/max9286.c       | 8 ++++----
 drivers/media/i2c/soc_camera/ov10635.c       | 4 ++--
 drivers/media/i2c/soc_camera/ov2775.c        | 4 ++--
 drivers/media/i2c/soc_camera/ov490_ov10640.c | 4 ++--
 drivers/media/i2c/soc_camera/ov495_ov2775.c  | 4 ++--
 drivers/media/i2c/soc_camera/ti9x4.c         | 4 ++--
 9 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/drivers/media/i2c/soc_camera/ap0101_ar014x.c b/drivers/media/i2c/soc_camera/ap0101_ar014x.c
index cae0b19..d8025a4 100644
--- a/drivers/media/i2c/soc_camera/ap0101_ar014x.c
+++ b/drivers/media/i2c/soc_camera/ap0101_ar014x.c
@@ -420,8 +420,6 @@ static int ap0101_parse_dt(struct device_node *np, struct ap0101_priv *priv)
 		if (!endpoint)
 			break;
 
-		of_node_put(endpoint);
-
 		rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0);
 		if (!rendpoint)
 			continue;
@@ -432,6 +430,8 @@ static int ap0101_parse_dt(struct device_node *np, struct ap0101_priv *priv)
 			break;
 	}
 
+	of_node_put(endpoint);
+
 	if (!priv->max9286_addr) {
 		dev_err(&client->dev, "deserializer does not present for AP0101\n");
 		return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/ar0132.c b/drivers/media/i2c/soc_camera/ar0132.c
index a7ee868..2865902 100644
--- a/drivers/media/i2c/soc_camera/ar0132.c
+++ b/drivers/media/i2c/soc_camera/ar0132.c
@@ -379,8 +379,6 @@ static int ar0132_parse_dt(struct device_node *np, struct ar0132_priv *priv)
 		if (!endpoint)
 			break;
 
-		of_node_put(endpoint);
-
 		of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order);
 
 		rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0);
@@ -399,6 +397,8 @@ static int ar0132_parse_dt(struct device_node *np, struct ar0132_priv *priv)
 			break;
 	}
 
+	of_node_put(endpoint);
+
 	if (!priv->max9286_addr && !priv->ti9x4_addr) {
 		dev_err(&client->dev, "deserializer does not present for AR0132\n");
 		return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/ar0220.c b/drivers/media/i2c/soc_camera/ar0220.c
index e00fe4a..8813522 100644
--- a/drivers/media/i2c/soc_camera/ar0220.c
+++ b/drivers/media/i2c/soc_camera/ar0220.c
@@ -358,7 +358,6 @@ static int ar0220_parse_dt(struct device_node *np, struct ar0220_priv *priv)
 		if (!endpoint)
 			break;
 
-		of_node_put(endpoint);
 
 		rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0);
 		if (!rendpoint)
@@ -371,6 +370,8 @@ static int ar0220_parse_dt(struct device_node *np, struct ar0220_priv *priv)
 			break;
 	}
 
+	of_node_put(endpoint);
+
 	if (!priv->ti9x4_addr) {
 		dev_err(&client->dev, "deserializer does not present\n");
 		return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c
index 6a5d0889..d01acdc 100644
--- a/drivers/media/i2c/soc_camera/max9286.c
+++ b/drivers/media/i2c/soc_camera/max9286.c
@@ -560,9 +560,8 @@ static int max9286_parse_dt(struct i2c_client *client)
 		if (!endpoint)
 			break;
 
-		of_node_put(endpoint);
-
 		if (of_property_read_u32(endpoint, "max9271-addr", &priv->max9271_addr_map[i])) {
+			of_node_put(endpoint);
 			dev_err(&client->dev, "max9271-addr not set\n");
 			return -EINVAL;
 		}
@@ -570,6 +569,7 @@ static int max9286_parse_dt(struct i2c_client *client)
 		priv->sd_fwnode[i] = of_fwnode_handle(endpoint);
 	}
 
+	of_node_put(endpoint);
 	return 0;
 }
 
@@ -586,8 +586,6 @@ static void max9286_setup_remote_endpoint(struct i2c_client *client)
 		if (!endpoint)
 			break;
 
-		of_node_put(endpoint);
-
 		rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0);
 		if (!rendpoint)
 			continue;
@@ -604,6 +602,8 @@ static void max9286_setup_remote_endpoint(struct i2c_client *client)
 		if (dvp_order_prop)
 			of_update_property(rendpoint, dvp_order_prop);
 	}
+
+	of_node_put(endpoint);
 }
 
 static int max9286_probe(struct i2c_client *client,
diff --git a/drivers/media/i2c/soc_camera/ov10635.c b/drivers/media/i2c/soc_camera/ov10635.c
index eacf015..8289b76 100644
--- a/drivers/media/i2c/soc_camera/ov10635.c
+++ b/drivers/media/i2c/soc_camera/ov10635.c
@@ -555,8 +555,6 @@ static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv)
 		if (!endpoint)
 			break;
 
-		of_node_put(endpoint);
-
 		of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order);
 
 		rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0);
@@ -581,6 +579,8 @@ static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv)
 			break;
 	}
 
+	of_node_put(endpoint);
+
 	if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) {
 		dev_err(&client->dev, "deserializer does not present for OV10635\n");
 		return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/ov2775.c b/drivers/media/i2c/soc_camera/ov2775.c
index feb547f..cb41764 100644
--- a/drivers/media/i2c/soc_camera/ov2775.c
+++ b/drivers/media/i2c/soc_camera/ov2775.c
@@ -355,8 +355,6 @@ static int ov2775_parse_dt(struct device_node *np, struct ov2775_priv *priv)
 		if (!endpoint)
 			break;
 
-		of_node_put(endpoint);
-
 		rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0);
 		if (!rendpoint)
 			continue;
@@ -368,6 +366,8 @@ static int ov2775_parse_dt(struct device_node *np, struct ov2775_priv *priv)
 			break;
 	}
 
+	of_node_put(endpoint);
+
 	if (!priv->ti9x4_addr) {
 		dev_err(&client->dev, "deserializer does not present\n");
 		return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.c b/drivers/media/i2c/soc_camera/ov490_ov10640.c
index e698f59..4b51a92 100644
--- a/drivers/media/i2c/soc_camera/ov490_ov10640.c
+++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c
@@ -904,8 +904,6 @@ static int ov490_parse_dt(struct device_node *np, struct ov490_priv *priv)
 		if (!endpoint)
 			break;
 
-		of_node_put(endpoint);
-
 		of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order);
 
 		rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0);
@@ -933,6 +931,8 @@ static int ov490_parse_dt(struct device_node *np, struct ov490_priv *priv)
 			break;
 	}
 
+	of_node_put(endpoint);
+
 	if (!priv->max9286_addr && !priv->ti9x4_addr) {
 		dev_err(&client->dev, "deserializer does not present for OV490\n");
 		return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/ov495_ov2775.c b/drivers/media/i2c/soc_camera/ov495_ov2775.c
index bb5991c..32b5078 100644
--- a/drivers/media/i2c/soc_camera/ov495_ov2775.c
+++ b/drivers/media/i2c/soc_camera/ov495_ov2775.c
@@ -464,8 +464,6 @@ static int ov495_parse_dt(struct device_node *np, struct ov495_priv *priv)
 		if (!endpoint)
 			break;
 
-		of_node_put(endpoint);
-
 		rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0);
 		if (!rendpoint)
 			continue;
@@ -477,6 +475,8 @@ static int ov495_parse_dt(struct device_node *np, struct ov495_priv *priv)
 			break;
 	}
 
+	of_node_put(endpoint);
+
 	if (!priv->ti9x4_addr) {
 		dev_err(&client->dev, "deserializer does not present for OV495\n");
 		return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c
index 2ce98b4..7704bfa 100644
--- a/drivers/media/i2c/soc_camera/ti9x4.c
+++ b/drivers/media/i2c/soc_camera/ti9x4.c
@@ -406,10 +406,9 @@ static int ti9x4_parse_dt(struct i2c_client *client)
 		if (!endpoint)
 			break;
 
-		of_node_put(endpoint);
-
 		if (i < priv->links) {
 			if (of_property_read_u32(endpoint, "ti9x3-addr", &priv->ti9x3_addr_map[i])) {
+				of_node_put(endpoint);
 				dev_err(&client->dev, "ti9x3-addr not set\n");
 				return -EINVAL;
 			}
@@ -431,6 +430,7 @@ static int ti9x4_parse_dt(struct i2c_client *client)
 			of_update_property(rendpoint, dvp_order_prop);
 	}
 
+	of_node_put(endpoint);
 	return 0;
 }
 
-- 
2.7.4

