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

Commit bee66230 authored by David Dai's avatar David Dai
Browse files

msm: msm_bus: Introduce ALC voting



Expand upon existing bus scaling APIs to allow clients
to vote on the ALC(Active Latency Client) BCM by specifying
FAL(First Access Latency) and Idle Time requirements. Make internal
aggregation and voting to BCM queues generic to allow optimization of
WAKE/SLEEP TCS sets by comparing scalar vectors as opposed to
strictly bandwidth. Using existing Qcom Bus Scaling APIs, clients
can register and update their requests by providing ALC vectors in
pdata.

Change-Id: I97093dc9fd9d5e7e21f6f8feeb3f54cf5bdc48d3
Signed-off-by: default avatarDavid Dai <daidavid1@codeaurora.org>
parent 66204ed7
Loading
Loading
Loading
Loading
+19 −1
Original line number Original line Diff line number Diff line
@@ -218,7 +218,16 @@ using the following properties:
				master-id, slave-id, arbitrated bandwidth
				master-id, slave-id, arbitrated bandwidth
				in KBps, instantaneous bandwidth in KBps
				in KBps, instantaneous bandwidth in KBps


Example:
The following are optional properties for client's device nodes:

- qcom,msm-bus,alc-voter:	Boolean alc_voter flag to indicate that client
				will vote as an Active Latency Client.
- qcom,msm-bus,vectors-alc:	Arrays of unsigned integers representing:
				first access latency, idle time in ns, this
				property is required if qcom,msm-bus,alc-voter
				is present.

Example for default client:


	qcom,msm-bus,name = "client-name";
	qcom,msm-bus,name = "client-name";
	qcom,msm-bus,num-cases = <3>;
	qcom,msm-bus,num-cases = <3>;
@@ -229,3 +238,12 @@ Example:
			<22 512 320000 3200000>, <26 512 3200000 3200000>,
			<22 512 320000 3200000>, <26 512 3200000 3200000>,
			<22 512 160000 1600000>, <26 512 1600000 1600000>;
			<22 512 160000 1600000>, <26 512 1600000 1600000>;


Example for ALC client:

	qcom,msm-bus,name = "client-name";
	qcom,msm-bus,num-cases = <2>;
	qcom,msm-bus,active-only;
	qcom,msm-bus,alc-voter;
	qcom,msm-bus,vectors-alc =
			<0 0>,
			<500 1600>;
+198 −9
Original line number Original line Diff line number Diff line
@@ -24,6 +24,8 @@
#define NUM_LNODES	3
#define NUM_LNODES	3
#define MAX_STR_CL	50
#define MAX_STR_CL	50


#define MSM_BUS_MAS_ALC	144

struct bus_search_type {
struct bus_search_type {
	struct list_head link;
	struct list_head link;
	struct list_head node_list;
	struct list_head node_list;
@@ -123,6 +125,9 @@ static void bcm_add_bus_req(struct device *dev)
		goto exit_bcm_add_bus_req;
		goto exit_bcm_add_bus_req;
	}
	}


	if (cur_dev->node_info->bcm_req_idx != -1)
		goto exit_bcm_add_bus_req;

	if (!cur_dev->node_info->num_bcm_devs)
	if (!cur_dev->node_info->num_bcm_devs)
		goto exit_bcm_add_bus_req;
		goto exit_bcm_add_bus_req;


@@ -179,8 +184,6 @@ static void bcm_add_bus_req(struct device *dev)
		cur_dev->node_info->bcm_req_idx = lnode_idx;
		cur_dev->node_info->bcm_req_idx = lnode_idx;
		memset(lnode->lnode_ib, 0, sizeof(uint64_t) * NUM_CTX);
		memset(lnode->lnode_ib, 0, sizeof(uint64_t) * NUM_CTX);
		memset(lnode->lnode_ab, 0, sizeof(uint64_t) * NUM_CTX);
		memset(lnode->lnode_ab, 0, sizeof(uint64_t) * NUM_CTX);
		MSM_BUS_ERR("%s: Added %d entry to bcm %d @ %d\n", __func__,
			lnode->bus_dev_id, bcm_dev->node_info->id, lnode_idx);
	}
	}


exit_bcm_add_bus_req:
exit_bcm_add_bus_req:
@@ -316,7 +319,6 @@ static int prune_path(struct list_head *route_list, int dest, int src,
		MSM_BUS_ERR("%s: Can't find dest dev %d", __func__, dest);
		MSM_BUS_ERR("%s: Can't find dest dev %d", __func__, dest);
		goto exit_prune_path;
		goto exit_prune_path;
	}
	}
	MSM_BUS_ERR("%s: dest dev %d", __func__, dest);


	lnode_hop = gen_lnode(dest_dev, search_dev_id, lnode_hop, cl_name);
	lnode_hop = gen_lnode(dest_dev, search_dev_id, lnode_hop, cl_name);
	bcm_add_bus_req(dest_dev);
	bcm_add_bus_req(dest_dev);
@@ -520,7 +522,6 @@ static void bcm_update_bus_req(struct device *dev, int ctx)
				max_ib = max(max_ib,
				max_ib = max(max_ib,
				max(bcm_dev->lnode_list[i].lnode_ib[ACTIVE_CTX],
				max(bcm_dev->lnode_list[i].lnode_ib[ACTIVE_CTX],
				bcm_dev->lnode_list[i].lnode_ib[DUAL_CTX]));
				bcm_dev->lnode_list[i].lnode_ib[DUAL_CTX]));

				max_ab = max(max_ab,
				max_ab = max(max_ab,
				bcm_dev->lnode_list[i].lnode_ab[ACTIVE_CTX] +
				bcm_dev->lnode_list[i].lnode_ab[ACTIVE_CTX] +
				bcm_dev->lnode_list[i].lnode_ab[DUAL_CTX]);
				bcm_dev->lnode_list[i].lnode_ab[DUAL_CTX]);
@@ -531,9 +532,14 @@ static void bcm_update_bus_req(struct device *dev, int ctx)
					bcm_dev->lnode_list[i].lnode_ab[ctx]);
					bcm_dev->lnode_list[i].lnode_ab[ctx]);
			}
			}
		}
		}

		bcm_dev->node_bw[ctx].max_ab = max_ab;
		bcm_dev->node_bw[ctx].max_ab = max_ab;
		bcm_dev->node_bw[ctx].max_ib = max_ib;
		bcm_dev->node_bw[ctx].max_ib = max_ib;

		max_ab = msm_bus_div64(max_ab, bcm_dev->bcmdev->unit_size);
		max_ib = msm_bus_div64(max_ib, bcm_dev->bcmdev->unit_size);

		bcm_dev->node_vec[ctx].vec_a = max_ab;
		bcm_dev->node_vec[ctx].vec_b = max_ib;
	}
	}
exit_bcm_update_bus_req:
exit_bcm_update_bus_req:
	return;
	return;
@@ -598,15 +604,51 @@ static void bcm_query_bus_req(struct device *dev, int ctx)
			}
			}
		}
		}


		max_query_ab = msm_bus_div64(max_query_ab,
						bcm_dev->bcmdev->unit_size);
		max_query_ib = msm_bus_div64(max_query_ib,
						bcm_dev->bcmdev->unit_size);

		bcm_dev->node_bw[ctx].max_query_ab = max_query_ab;
		bcm_dev->node_bw[ctx].max_query_ab = max_query_ab;
		bcm_dev->node_bw[ctx].max_query_ib = max_query_ib;
		bcm_dev->node_bw[ctx].max_query_ib = max_query_ib;

	}
	}
exit_bcm_query_bus_req:
exit_bcm_query_bus_req:
	return;
	return;
}
}


static void bcm_update_alc_req(struct msm_bus_node_device_type *dev, int ctx)
{
	struct msm_bus_node_device_type *bcm_dev = NULL;
	int i;
	uint64_t max_alc = 0;

	if (!dev || !to_msm_bus_node(dev->node_info->bus_device)) {
		MSM_BUS_ERR("Bus node pointer is Invalid");
		goto exit_bcm_update_alc_req;
	}

	for (i = 0; i < dev->num_lnodes; i++)
		max_alc = max(max_alc, dev->lnode_list[i].alc_idx[ctx]);


	dev->node_bw[ctx].max_alc = max_alc;

	bcm_dev = to_msm_bus_node(dev->node_info->bcm_devs[0]);

	if (ctx == ACTIVE_CTX) {
		max_alc = max(max_alc,
				max(dev->node_bw[ACTIVE_CTX].max_alc,
				dev->node_bw[DUAL_CTX].max_alc));
	} else {
		max_alc = dev->node_bw[ctx].max_alc;
	}

	bcm_dev->node_bw[ctx].max_alc = max_alc;
	bcm_dev->node_vec[ctx].vec_a = max_alc;
	bcm_dev->node_vec[ctx].vec_b = 0;

exit_bcm_update_alc_req:
	return;
}


int bcm_remove_handoff_req(struct device *dev, void *data)
int bcm_remove_handoff_req(struct device *dev, void *data)
{
{
@@ -684,7 +726,6 @@ static void aggregate_bus_query_req(struct msm_bus_node_device_type *bus_dev,
		sum_ab += bus_dev->lnode_list[i].lnode_query_ab[ctx];
		sum_ab += bus_dev->lnode_list[i].lnode_query_ab[ctx];
	}
	}


	MSM_BUS_ERR("aggregate: query_ab:%llu\n", sum_ab);
	bus_dev->node_bw[ctx].sum_query_ab = sum_ab;
	bus_dev->node_bw[ctx].sum_query_ab = sum_ab;
	bus_dev->node_bw[ctx].max_query_ib = max_ib;
	bus_dev->node_bw[ctx].max_query_ib = max_ib;


@@ -870,6 +911,63 @@ static int update_path(struct device *src_dev, int dest, uint64_t act_req_ib,
	return ret;
	return ret;
}
}


static int update_alc_vote(struct device *alc_dev, uint64_t act_req_fa_lat,
			uint64_t act_req_idle_time, uint64_t slp_req_fa_lat,
			uint64_t slp_req_idle_time, uint64_t cur_fa_lat,
			uint64_t cur_idle_time, int idx, int ctx)
{
	struct link_node *lnode = NULL;
	struct msm_bus_node_device_type *dev_info = NULL;
	int curr_idx, i;
	int ret = 0;

	if (IS_ERR_OR_NULL(alc_dev)) {
		MSM_BUS_ERR("%s: No source device", __func__);
		ret = -ENODEV;
		goto exit_update_alc_vote;
	}

	if (idx < 0) {
		MSM_BUS_ERR("%s: Invalid lnode idx %d", __func__, idx);
		ret = -ENXIO;
		goto exit_update_alc_vote;
	}

	dev_info = to_msm_bus_node(alc_dev);
	curr_idx = idx;

	if (curr_idx >= dev_info->num_lnodes) {
		MSM_BUS_ERR("%s: Invalid lnode Idx %d num lnodes %d",
				 __func__, curr_idx, dev_info->num_lnodes);
		ret = -ENXIO;
		goto exit_update_alc_vote;
	}

	lnode = &dev_info->lnode_list[curr_idx];
	if (!lnode) {
		MSM_BUS_ERR("%s: Invalid lnode ptr lnode %d",
			 __func__, curr_idx);
		ret = -ENXIO;
		goto exit_update_alc_vote;
	}

	/*
	 * Add aggregation and mapping logic once LUT is avail.
	 * Use default values for time being.
	 */
	lnode->alc_idx[ACTIVE_CTX] = 12;
	lnode->alc_idx[DUAL_CTX] = 0;

	for (i = 0; i < NUM_CTX; i++)
		bcm_update_alc_req(dev_info, i);

	add_node_to_clist(dev_info);

exit_update_alc_vote:
	return ret;
}


static int query_path(struct device *src_dev, int dest, uint64_t act_req_ib,
static int query_path(struct device *src_dev, int dest, uint64_t act_req_ib,
			uint64_t act_req_bw, uint64_t slp_req_ib,
			uint64_t act_req_bw, uint64_t slp_req_ib,
			uint64_t slp_req_bw, uint64_t cur_ib, uint64_t cur_bw,
			uint64_t slp_req_bw, uint64_t cur_ib, uint64_t cur_bw,
@@ -1160,6 +1258,40 @@ static uint32_t register_client_adhoc(struct msm_bus_scale_pdata *pdata)
	}
	}
	client->pdata = pdata;
	client->pdata = pdata;


	if (pdata->alc) {
		client->curr = -1;
		lnode = kzalloc(sizeof(int), GFP_KERNEL);

		if (ZERO_OR_NULL_PTR(lnode)) {
			MSM_BUS_ERR("%s: Error allocating lnode!", __func__);
			goto exit_lnode_malloc_fail;
		}
		client->src_pnode = lnode;

		client->src_devs = kzalloc(sizeof(struct device *),
							GFP_KERNEL);
		if (IS_ERR_OR_NULL(client->src_devs)) {
			MSM_BUS_ERR("%s: Error allocating src_dev!", __func__);
			goto exit_src_dev_malloc_fail;
		}
		src = MSM_BUS_MAS_ALC;
		dev = bus_find_device(&msm_bus_type, NULL,
				(void *) &src,
				msm_bus_device_match_adhoc);
		if (IS_ERR_OR_NULL(dev)) {
			MSM_BUS_ERR("%s:Failed to find alc device",
				__func__);
			goto exit_invalid_data;
		}
		gen_lnode(dev, MSM_BUS_MAS_ALC, 0, pdata->name);
		bcm_add_bus_req(dev);

		client->src_devs[0] = dev;

		handle = gen_handle(client);
		goto exit_register_client;
	}

	lnode = kcalloc(pdata->usecase->num_paths, sizeof(int), GFP_KERNEL);
	lnode = kcalloc(pdata->usecase->num_paths, sizeof(int), GFP_KERNEL);
	if (ZERO_OR_NULL_PTR(lnode)) {
	if (ZERO_OR_NULL_PTR(lnode)) {
		MSM_BUS_ERR("%s: Error allocating pathnode ptr!", __func__);
		MSM_BUS_ERR("%s: Error allocating pathnode ptr!", __func__);
@@ -1293,6 +1425,58 @@ static int update_client_paths(struct msm_bus_client *client, bool log_trns,
	return ret;
	return ret;
}
}


static int update_client_alc(struct msm_bus_client *client, bool log_trns,
							unsigned int idx)
{
	int lnode, cur_idx;
	uint64_t req_idle_time, req_fal, dual_idle_time, dual_fal,
	cur_idle_time, cur_fal;
	int ret = 0;
	struct msm_bus_scale_pdata *pdata;
	struct device *src_dev;

	if (!client) {
		MSM_BUS_ERR("Client handle  Null");
		ret = -ENXIO;
		goto exit_update_client_alc;
	}

	pdata = client->pdata;
	if (!pdata) {
		MSM_BUS_ERR("Client pdata Null");
		ret = -ENXIO;
		goto exit_update_client_alc;
	}

	cur_idx = client->curr;
	client->curr = idx;
	req_fal = pdata->usecase_lat[idx].fal_ns;
	req_idle_time = pdata->usecase_lat[idx].idle_t_ns;
	lnode = client->src_pnode[0];
	src_dev = client->src_devs[0];

	if (pdata->active_only) {
		dual_fal = 0;
		dual_idle_time = 0;
	} else {
		dual_fal = req_fal;
		dual_idle_time = req_idle_time;
	}

	ret = update_alc_vote(src_dev, req_fal, req_idle_time, dual_fal,
		dual_idle_time, cur_fal, cur_idle_time, lnode,
		pdata->active_only);

	if (ret) {
		MSM_BUS_ERR("%s: Update path failed! %d ctx %d\n",
				__func__, ret, pdata->active_only);
		goto exit_update_client_alc;
	}
	commit_data();
exit_update_client_alc:
	return ret;
}

static int query_usecase(struct msm_bus_client *client, bool log_trns,
static int query_usecase(struct msm_bus_client *client, bool log_trns,
					unsigned int idx,
					unsigned int idx,
					struct msm_bus_tcs_usecase *tcs_usecase)
					struct msm_bus_tcs_usecase *tcs_usecase)
@@ -1483,8 +1667,13 @@ static int update_request_adhoc(uint32_t cl, unsigned int index)


	MSM_BUS_DBG("%s: cl: %u index: %d curr: %d num_paths: %d\n", __func__,
	MSM_BUS_DBG("%s: cl: %u index: %d curr: %d num_paths: %d\n", __func__,
		cl, index, client->curr, client->pdata->usecase->num_paths);
		cl, index, client->curr, client->pdata->usecase->num_paths);

	if (pdata->alc)
		ret = update_client_alc(client, log_transaction, index);
	else {
		msm_bus_dbg_client_data(client->pdata, index, cl);
		msm_bus_dbg_client_data(client->pdata, index, cl);
		ret = update_client_paths(client, log_transaction, index);
		ret = update_client_paths(client, log_transaction, index);
	}
	if (ret) {
	if (ret) {
		pr_err("%s: Err updating path\n", __func__);
		pr_err("%s: Err updating path\n", __func__);
		goto exit_update_request;
		goto exit_update_request;
+1 −2
Original line number Original line Diff line number Diff line
/* Copyright (c) 2010-2012, 2014-2016, The Linux Foundation. All rights
/* Copyright (c) 2010-2012, 2014-2017, The Linux Foundation. All rights
 * reserved.
 * reserved.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
@@ -439,7 +439,6 @@ static void msm_bus_dbg_free_client(uint32_t clid)


	list_for_each_entry(cldata, &cl_list, list) {
	list_for_each_entry(cldata, &cl_list, list) {
		if (cldata->clid == clid) {
		if (cldata->clid == clid) {
			debugfs_remove(cldata->file);
			list_del(&cldata->list);
			list_del(&cldata->list);
			kfree(cldata);
			kfree(cldata);
			break;
			break;
+27 −31
Original line number Original line Diff line number Diff line
@@ -265,27 +265,23 @@ static int setrate_nodeclk(struct nodeclk *nclk, long rate)
}
}


static int tcs_cmd_gen(struct msm_bus_node_device_type *cur_bcm,
static int tcs_cmd_gen(struct msm_bus_node_device_type *cur_bcm,
				struct tcs_cmd *cmd, uint64_t ib,
				struct tcs_cmd *cmd, uint64_t vec_a,
					uint64_t ab, bool commit)
					uint64_t vec_b, bool commit)
{
{
	int ret = 0;
	int ret = 0;
	bool valid = true;
	bool valid = true;


	if (ib == 0 && ab == 0) {
	if (vec_a == 0 && vec_b == 0)
		valid = false;
		valid = false;
	} else {
		do_div(ib, cur_bcm->bcmdev->unit_size);
		do_div(ab, cur_bcm->bcmdev->unit_size);
	}


	if (ib > BCM_TCS_CMD_VOTE_MASK)
	if (vec_a > BCM_TCS_CMD_VOTE_MASK)
		ib = BCM_TCS_CMD_VOTE_MASK;
		vec_a = BCM_TCS_CMD_VOTE_MASK;


	if (ab > BCM_TCS_CMD_VOTE_MASK)
	if (vec_b > BCM_TCS_CMD_VOTE_MASK)
		ab = BCM_TCS_CMD_VOTE_MASK;
		vec_b = BCM_TCS_CMD_VOTE_MASK;


	cmd->addr = cur_bcm->bcmdev->addr;
	cmd->addr = cur_bcm->bcmdev->addr;
	cmd->data = BCM_TCS_CMD(commit, valid, ab, ib);
	cmd->data = BCM_TCS_CMD(commit, valid, vec_a, vec_b);
	cmd->complete = commit;
	cmd->complete = commit;


	return ret;
	return ret;
@@ -333,8 +329,8 @@ static int tcs_cmd_list_gen(int *n_active,
				idx++;
				idx++;
			}
			}
			tcs_cmd_gen(cur_bcm, &cmdlist_active[k],
			tcs_cmd_gen(cur_bcm, &cmdlist_active[k],
				cur_bcm->node_bw[ACTIVE_CTX].max_ib,
				cur_bcm->node_vec[ACTIVE_CTX].vec_a,
				cur_bcm->node_bw[ACTIVE_CTX].max_ab, commit);
				cur_bcm->node_vec[ACTIVE_CTX].vec_b, commit);
			k++;
			k++;
			last_tcs = k;
			last_tcs = k;
			cur_bcm->updated = true;
			cur_bcm->updated = true;
@@ -352,10 +348,10 @@ static int tcs_cmd_list_gen(int *n_active,
			continue;
			continue;
		list_for_each_entry(cur_bcm, &cur_bcm_clist[i], link) {
		list_for_each_entry(cur_bcm, &cur_bcm_clist[i], link) {
			commit = false;
			commit = false;
			if ((cur_bcm->node_bw[DUAL_CTX].max_ab ==
			if ((cur_bcm->node_vec[DUAL_CTX].vec_a ==
				cur_bcm->node_bw[ACTIVE_CTX].max_ab) &&
				cur_bcm->node_vec[ACTIVE_CTX].vec_a) &&
				(cur_bcm->node_bw[DUAL_CTX].max_ib ==
				(cur_bcm->node_vec[DUAL_CTX].vec_b ==
				cur_bcm->node_bw[ACTIVE_CTX].max_ib)) {
				cur_bcm->node_vec[ACTIVE_CTX].vec_b)) {
				if (last_tcs != -1 &&
				if (last_tcs != -1 &&
					list_is_last(&cur_bcm->link,
					list_is_last(&cur_bcm->link,
					&cur_bcm_clist[i])) {
					&cur_bcm_clist[i])) {
@@ -378,11 +374,11 @@ static int tcs_cmd_list_gen(int *n_active,
			}
			}


			tcs_cmd_gen(cur_bcm, &cmdlist_wake[k],
			tcs_cmd_gen(cur_bcm, &cmdlist_wake[k],
				cur_bcm->node_bw[ACTIVE_CTX].max_ib,
				cur_bcm->node_vec[ACTIVE_CTX].vec_a,
				cur_bcm->node_bw[ACTIVE_CTX].max_ab, commit);
				cur_bcm->node_vec[ACTIVE_CTX].vec_b, commit);
			tcs_cmd_gen(cur_bcm, &cmdlist_sleep[k],
			tcs_cmd_gen(cur_bcm, &cmdlist_sleep[k],
				cur_bcm->node_bw[DUAL_CTX].max_ib,
				cur_bcm->node_vec[DUAL_CTX].vec_a,
				cur_bcm->node_bw[DUAL_CTX].max_ab, commit);
				cur_bcm->node_vec[DUAL_CTX].vec_b, commit);
			k++;
			k++;
		}
		}
	}
	}
@@ -485,10 +481,10 @@ static int bcm_clist_clean(struct msm_bus_node_device_type *cur_dev)


	cur_bcm = to_msm_bus_node(cur_dev->node_info->bcm_devs[0]);
	cur_bcm = to_msm_bus_node(cur_dev->node_info->bcm_devs[0]);


	if (cur_bcm->node_bw[DUAL_CTX].max_ab == 0 &&
	if (cur_bcm->node_vec[DUAL_CTX].vec_a == 0 &&
			cur_bcm->node_bw[ACTIVE_CTX].max_ab == 0 &&
			cur_bcm->node_vec[ACTIVE_CTX].vec_a == 0 &&
			cur_bcm->node_bw[DUAL_CTX].max_ib == 0 &&
			cur_bcm->node_vec[DUAL_CTX].vec_b == 0 &&
			cur_bcm->node_bw[ACTIVE_CTX].max_ib == 0) {
			cur_bcm->node_vec[ACTIVE_CTX].vec_b == 0) {
		cur_bcm->dirty = false;
		cur_bcm->dirty = false;
		list_del_init(&cur_bcm->link);
		list_del_init(&cur_bcm->link);
	}
	}
@@ -550,10 +546,10 @@ int msm_bus_commit_data(struct list_head *clist)
		if (list_empty(&cur_bcm_clist[i]))
		if (list_empty(&cur_bcm_clist[i]))
			continue;
			continue;
		list_for_each_entry(cur_bcm, &cur_bcm_clist[i], link) {
		list_for_each_entry(cur_bcm, &cur_bcm_clist[i], link) {
			if ((cur_bcm->node_bw[DUAL_CTX].max_ab !=
			if ((cur_bcm->node_vec[DUAL_CTX].vec_a !=
				cur_bcm->node_bw[ACTIVE_CTX].max_ab) ||
				cur_bcm->node_vec[ACTIVE_CTX].vec_a) ||
				(cur_bcm->node_bw[DUAL_CTX].max_ib !=
				(cur_bcm->node_vec[DUAL_CTX].vec_b !=
				cur_bcm->node_bw[ACTIVE_CTX].max_ib)) {
				cur_bcm->node_vec[ACTIVE_CTX].vec_b)) {
				cnt_sleep++;
				cnt_sleep++;
				cnt_wake++;
				cnt_wake++;
			}
			}
@@ -563,7 +559,6 @@ int msm_bus_commit_data(struct list_head *clist)
		cnt_vcd++;
		cnt_vcd++;
	}
	}


	MSM_BUS_ERR("%s: cmd_gen\n", __func__);
	n_active = kcalloc(cnt_vcd+1, sizeof(int), GFP_KERNEL);
	n_active = kcalloc(cnt_vcd+1, sizeof(int), GFP_KERNEL);
	n_wake = kcalloc(cnt_vcd+1, sizeof(int), GFP_KERNEL);
	n_wake = kcalloc(cnt_vcd+1, sizeof(int), GFP_KERNEL);
	n_sleep = kcalloc(cnt_vcd+1, sizeof(int), GFP_KERNEL);
	n_sleep = kcalloc(cnt_vcd+1, sizeof(int), GFP_KERNEL);
@@ -1086,6 +1081,7 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata,


	node_info->name = pdata_node_info->name;
	node_info->name = pdata_node_info->name;
	node_info->id =  pdata_node_info->id;
	node_info->id =  pdata_node_info->id;
	node_info->bcm_req_idx = -1;
	node_info->bus_device_id = pdata_node_info->bus_device_id;
	node_info->bus_device_id = pdata_node_info->bus_device_id;
	node_info->mas_rpm_id = pdata_node_info->mas_rpm_id;
	node_info->mas_rpm_id = pdata_node_info->mas_rpm_id;
	node_info->slv_rpm_id = pdata_node_info->slv_rpm_id;
	node_info->slv_rpm_id = pdata_node_info->slv_rpm_id;
+38 −1
Original line number Original line Diff line number Diff line
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * it under the terms of the GNU General Public License version 2 and
@@ -46,6 +46,7 @@ static struct msm_bus_scale_pdata *get_pdata(struct platform_device *pdev,
{
{
	struct msm_bus_scale_pdata *pdata = NULL;
	struct msm_bus_scale_pdata *pdata = NULL;
	struct msm_bus_paths *usecase = NULL;
	struct msm_bus_paths *usecase = NULL;
	struct msm_bus_lat_vectors *usecase_lat = NULL;
	int i = 0, j, ret, num_usecases = 0, num_paths, len;
	int i = 0, j, ret, num_usecases = 0, num_paths, len;
	const uint32_t *vec_arr = NULL;
	const uint32_t *vec_arr = NULL;
	bool mem_err = false;
	bool mem_err = false;
@@ -85,6 +86,42 @@ static struct msm_bus_scale_pdata *get_pdata(struct platform_device *pdev,
		pr_debug("Using dual context by default\n");
		pr_debug("Using dual context by default\n");
	}
	}


	pdata->alc = of_property_read_bool(of_node, "qcom,msm-bus,alc-voter");

	if (pdata->alc) {
		usecase_lat = devm_kzalloc(&pdev->dev,
				(sizeof(struct msm_bus_lat_vectors) *
				pdata->num_usecases), GFP_KERNEL);
		if (!usecase_lat) {
			mem_err = true;
			goto err;
		}

		vec_arr = of_get_property(of_node,
					"qcom,msm-bus,vectors-alc", &len);
		if (vec_arr == NULL) {
			pr_err("Error: Lat vector array not found\n");
			goto err;
		}

		if (len != num_usecases * sizeof(uint32_t) * 2) {
			pr_err("Error: Length-error on getting vectors\n");
			goto err;
		}

		for (i = 0; i < num_usecases; i++) {
			int index = i * 2;

			usecase_lat[i].fal_ns = (uint64_t)
				KBTOB(be32_to_cpu(vec_arr[index]));
			usecase_lat[i].idle_t_ns = (uint64_t)
				KBTOB(be32_to_cpu(vec_arr[index + 1]));
		}

		pdata->usecase_lat = usecase_lat;
		return pdata;
	}

	usecase = devm_kzalloc(&pdev->dev, (sizeof(struct msm_bus_paths) *
	usecase = devm_kzalloc(&pdev->dev, (sizeof(struct msm_bus_paths) *
		pdata->num_usecases), GFP_KERNEL);
		pdata->num_usecases), GFP_KERNEL);
	if (!usecase) {
	if (!usecase) {
Loading