Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a34bf670 authored by Mukund Madhusudan Atre's avatar Mukund Madhusudan Atre
Browse files

msm: camera: Add fixes to axi bandwidth voting v2 path



Adding static internal bw config to avoid memory leak during
flush. Adding fix for divide by zero errors in generic blob
handler for isp and icp. Also, adding mutex lock to avoid
data corruption while traversing node tree in cpas apply vote.

Change-Id: I4679e31e0f8953f239c969c8a7bae29b9b69f377
Signed-off-by: default avatarMukund Madhusudan Atre <matre@codeaurora.org>
parent 93df147c
Loading
Loading
Loading
Loading
+11 −17
Original line number Diff line number Diff line
@@ -241,7 +241,6 @@ static int cam_cpas_util_axi_cleanup(struct cam_cpas *cpas_core,
			&cpas_core->axi_port[i].bus_client);
		of_node_put(cpas_core->axi_port[i].axi_port_node);
		cpas_core->axi_port[i].axi_port_node = NULL;
		mutex_destroy(&cpas_core->axi_port[i].lock);
	}

	return 0;
@@ -259,8 +258,6 @@ static int cam_cpas_util_axi_setup(struct cam_cpas *cpas_core,
			axi_port_mnoc_node, &cpas_core->axi_port[i].bus_client);
		if (rc)
			goto bus_register_fail;

		mutex_init(&cpas_core->axi_port[i].lock);
	}

	return 0;
@@ -617,6 +614,7 @@ static int cam_cpas_util_apply_client_axi_vote(
		par_camnoc_old = 0, par_mnoc_ab_old = 0, par_mnoc_ib_old = 0;
	int rc = 0, i = 0;

	mutex_lock(&cpas_core->tree_lock);
	if (!cpas_client->tree_node_valid) {
		/*
		 * This is by assuming apply_client_axi_vote is called
@@ -643,7 +641,7 @@ static int cam_cpas_util_apply_client_axi_vote(
		CAM_ERR(CAM_PERF, "Failed in bw consolidation, Client [%s][%d]",
			cpas_client->data.identifier,
			cpas_client->data.cell_index);
		return rc;
		goto unlock_tree;
	}

	con_axi_vote = &cpas_client->axi_vote;
@@ -711,7 +709,7 @@ static int cam_cpas_util_apply_client_axi_vote(
			} else {
				CAM_ERR(CAM_CPAS, "Invalid Merge type");
				rc = -EINVAL;
				return rc;
				goto unlock_tree;
			}

			if (!par_tree_node->parent_node) {
@@ -721,7 +719,7 @@ static int cam_cpas_util_apply_client_axi_vote(
					CAM_ERR(CAM_CPAS,
					"AXI port index invalid");
					rc = -EINVAL;
					return rc;
					goto unlock_tree;
				}

				cpas_core->axi_port
@@ -743,7 +741,8 @@ static int cam_cpas_util_apply_client_axi_vote(

	if (!par_tree_node) {
		CAM_DBG(CAM_CPAS, "No change in BW for all paths");
		return 0;
		rc = 0;
		goto unlock_tree;
	}

vote_start_clients:
@@ -753,8 +752,6 @@ static int cam_cpas_util_apply_client_axi_vote(
		else
			continue;

		mutex_lock(&axi_port->lock);

		CAM_DBG(CAM_PERF, "Port[%s] : ab=%lld ib=%lld additional=%lld",
			axi_port->axi_port_name, axi_port->ab_bw,
			axi_port->ib_bw, axi_port->additional_bw);
@@ -775,19 +772,16 @@ static int cam_cpas_util_apply_client_axi_vote(
			CAM_ERR(CAM_CPAS,
				"Failed in mnoc vote ab[%llu] ib[%llu] rc=%d",
				mnoc_ab_bw, mnoc_ib_bw, rc);
			goto unlock_axi_port;
			goto unlock_tree;
		}
		mutex_unlock(&axi_port->lock);
	}

	rc = cam_cpas_util_set_camnoc_axi_clk_rate(cpas_hw);
	if (rc)
		CAM_ERR(CAM_CPAS, "Failed in setting axi clk rate rc=%d", rc);

	return rc;

unlock_axi_port:
	mutex_unlock(&axi_port->lock);
unlock_tree:
	mutex_unlock(&cpas_core->tree_lock);
	return rc;
}

@@ -1817,7 +1811,7 @@ int cam_cpas_hw_probe(struct platform_device *pdev,
deinit_platform_res:
	cam_cpas_soc_deinit_resources(&cpas_hw->soc_info);
release_workq:
	cam_cpas_node_tree_cleanup(cpas_hw->soc_info.soc_private);
	cam_cpas_node_tree_cleanup(cpas_core, cpas_hw->soc_info.soc_private);
	flush_workqueue(cpas_core->work_queue);
	destroy_workqueue(cpas_core->work_queue);
release_mem:
@@ -1848,7 +1842,7 @@ int cam_cpas_hw_remove(struct cam_hw_intf *cpas_hw_intf)
	}

	cam_cpas_util_axi_cleanup(cpas_core, &cpas_hw->soc_info);
	cam_cpas_node_tree_cleanup(cpas_hw->soc_info.soc_private);
	cam_cpas_node_tree_cleanup(cpas_core, cpas_hw->soc_info.soc_private);
	cam_cpas_util_unregister_bus_client(&cpas_core->ahb_bus_client);
	cam_cpas_util_client_cleanup(cpas_hw);
	cam_cpas_soc_deinit_resources(&cpas_hw->soc_info);
+2 −2
Original line number Diff line number Diff line
@@ -148,7 +148,6 @@ struct cam_cpas_bus_client {
 * struct cam_cpas_axi_port : AXI port information
 *
 * @axi_port_name: Name of this AXI port
 * @lock: Mutex lock for accessing this port
 * @bus_client: bus client info for this port
 * @ib_bw_voting_needed: if this port can update ib bw dynamically
 * @axi_port_node: Node representing AXI Port info in device tree
@@ -158,7 +157,6 @@ struct cam_cpas_bus_client {
 */
struct cam_cpas_axi_port {
	const char *axi_port_name;
	struct mutex lock;
	struct cam_cpas_bus_client bus_client;
	bool ib_bw_voting_needed;
	struct device_node *axi_port_node;
@@ -173,6 +171,7 @@ struct cam_cpas_axi_port {
 * @hw_caps: CPAS hw capabilities
 * @cpas_client: Array of pointers to CPAS clients info
 * @client_mutex: Mutex for accessing client info
 * @tree_lock: Mutex lock for accessing CPAS node tree
 * @num_clients: Total number of clients that CPAS supports
 * @num_axi_ports: Total number of axi ports found in device tree
 * @registered_clients: Number of Clients registered currently
@@ -188,6 +187,7 @@ struct cam_cpas {
	struct cam_cpas_hw_caps hw_caps;
	struct cam_cpas_client *cpas_client[CAM_CPAS_MAX_CLIENTS];
	struct mutex client_mutex[CAM_CPAS_MAX_CLIENTS];
	struct mutex tree_lock;
	uint32_t num_clients;
	uint32_t num_axi_ports;
	uint32_t registered_clients;
+4 −2
Original line number Diff line number Diff line
@@ -88,7 +88,7 @@ void cam_cpas_util_debug_parse_data(
	CAM_INFO(CAM_CPAS, "NUMBER OF NODES PARSED: %d", i);
}

int cam_cpas_node_tree_cleanup(
int cam_cpas_node_tree_cleanup(struct cam_cpas *cpas_core,
	struct cam_cpas_private_soc *soc_private)
{
	int i = 0;
@@ -108,6 +108,7 @@ int cam_cpas_node_tree_cleanup(

	of_node_put(soc_private->camera_bus_node);
	soc_private->camera_bus_node = NULL;
	mutex_destroy(&cpas_core->tree_lock);

	return 0;
}
@@ -337,6 +338,7 @@ static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core,
			}
		}
	}
	mutex_init(&cpas_core->tree_lock);
	cam_cpas_util_debug_parse_data(soc_private);

	return 0;
@@ -507,7 +509,7 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw,
	return 0;

cleanup_tree:
	cam_cpas_node_tree_cleanup(soc_private);
	cam_cpas_node_tree_cleanup(cpas_core, soc_private);
cleanup_clients:
	cam_cpas_util_client_cleanup(cpas_hw);
	return rc;
+2 −1
Original line number Diff line number Diff line
@@ -110,7 +110,8 @@ void cam_cpas_dump_axi_vote_info(
	const struct cam_cpas_client *cpas_client,
	const char *identifier,
	struct cam_axi_vote *axi_vote);
int cam_cpas_node_tree_cleanup(struct cam_cpas_private_soc *soc_private);
int cam_cpas_node_tree_cleanup(struct cam_cpas *cpas_core,
	struct cam_cpas_private_soc *soc_private);
int cam_cpas_soc_init_resources(struct cam_hw_soc_info *soc_info,
	irq_handler_t vfe_irq_handler, struct cam_hw_info *cpas_hw);
int cam_cpas_soc_deinit_resources(struct cam_hw_soc_info *soc_info);
+12 −8
Original line number Diff line number Diff line
@@ -4132,15 +4132,19 @@ static int cam_icp_packet_generic_blob_handler(void *user_data,
		}

		/* Check for integer overflow */
		if (sizeof(struct cam_axi_per_path_bw_vote) > ((UINT_MAX -
		if (soc_req_v2->num_paths != 1) {
			if (sizeof(struct cam_axi_per_path_bw_vote) >
				((UINT_MAX -
				sizeof(struct cam_icp_clk_bw_request_v2)) /
				(soc_req_v2->num_paths - 1))) {
				CAM_ERR(CAM_ICP,
					"Size exceeds limit paths:%u size per path:%lu",
					soc_req_v2->num_paths - 1,
				sizeof(struct cam_axi_per_path_bw_vote));
					sizeof(
					struct cam_axi_per_path_bw_vote));
				return -EINVAL;
			}
		}

		clk_update_size = sizeof(struct cam_icp_clk_bw_request_v2) +
			((soc_req_v2->num_paths - 1) *
Loading