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

Commit 9d66f3f0 authored by David Dai's avatar David Dai
Browse files

msm: msm_bus: Introduce TCS Query APIs



Introduce new Query API to allow clients who are interested in
managing their own RPMH communication or used by other
execution environment that are unable to generate their own to fetch
sets of TCS commands based on their registered usecases. Bug fix.

Change-Id: I6171a646c6982bf8c781f9bfdbdffb601980d56b
Signed-off-by: default avatarDavid Dai <daidavid1@codeaurora.org>
Signed-off-by: default avatarGeorge Shen <sqiao@codeaurora.org>
parent a7654c6b
Loading
Loading
Loading
Loading
+69 −0
Original line number Diff line number Diff line
@@ -1111,6 +1111,75 @@ static int update_client_paths(struct msm_bus_client *client, bool log_trns,
	return ret;
}

static int query_client_paths(struct msm_bus_client *client, bool log_trns,
							unsigned int idx)
{
	int lnode, src, dest, cur_idx;
	uint64_t req_clk, req_bw, curr_clk, curr_bw, slp_clk, slp_bw;
	int i, 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_paths;
	}

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

	cur_idx = client->curr;
	client->curr = idx;
	for (i = 0; i < pdata->usecase->num_paths; i++) {
		src = pdata->usecase[idx].vectors[i].src;
		dest = pdata->usecase[idx].vectors[i].dst;

		lnode = client->src_pnode[i];
		src_dev = client->src_devs[i];
		req_clk = client->pdata->usecase[idx].vectors[i].ib;
		req_bw = client->pdata->usecase[idx].vectors[i].ab;
		if (cur_idx < 0) {
			curr_clk = 0;
			curr_bw = 0;
		} else {
			curr_clk =
				client->pdata->usecase[cur_idx].vectors[i].ib;
			curr_bw = client->pdata->usecase[cur_idx].vectors[i].ab;
			MSM_BUS_DBG("%s:ab: %llu ib: %llu\n", __func__,
					curr_bw, curr_clk);
		}

		if (pdata->active_only) {
			slp_clk = 0;
			slp_bw = 0;
		} else {
			slp_clk = req_clk;
			slp_bw = req_bw;
		}

		ret = update_path(src_dev, dest, req_clk, req_bw, slp_clk,
			slp_bw, curr_clk, curr_bw, 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_paths;
		}

		if (log_trns)
			getpath_debug(src, lnode, pdata->active_only);
	}
	commit_data();
exit_update_client_paths:
	return ret;
}


static int update_context(uint32_t cl, bool active_only,
					unsigned int ctx_idx)
{
+366 −2
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ static struct handle_type handle_list;
static LIST_HEAD(input_list);
static LIST_HEAD(apply_list);
static LIST_HEAD(commit_list);
static LIST_HEAD(query_list);

DEFINE_RT_MUTEX(msm_bus_adhoc_lock);

@@ -537,6 +538,74 @@ static void bcm_update_bus_req(struct device *dev, int ctx)
	return;
}

static void bcm_query_bus_req(struct device *dev, int ctx)
{
	struct msm_bus_node_device_type *cur_dev = NULL;
	struct msm_bus_node_device_type *bcm_dev = NULL;
	int i;
	uint64_t max_query_ib = 0;
	uint64_t max_query_ab = 0;
	int lnode_idx = 0;

	cur_dev = to_msm_bus_node(dev);
	if (!cur_dev) {
		MSM_BUS_ERR("%s: Null device ptr", __func__);
		goto exit_bcm_query_bus_req;
	}

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

	for (i = 0; i < cur_dev->node_info->num_bcm_devs; i++) {
		bcm_dev = to_msm_bus_node(cur_dev->node_info->bcm_devs[i]);

		if (!bcm_dev)
			goto exit_bcm_query_bus_req;

		lnode_idx = cur_dev->node_info->bcm_req_idx;
		bcm_dev->lnode_list[lnode_idx].lnode_query_ib[ctx] =
			msm_bus_div64(cur_dev->node_info->agg_params.buswidth,
					cur_dev->node_bw[ctx].max_query_ib *
					(uint64_t)bcm_dev->bcmdev->width);

		bcm_dev->lnode_list[lnode_idx].lnode_query_ab[ctx] =
			msm_bus_div64(cur_dev->node_info->agg_params.buswidth,
					cur_dev->node_bw[ctx].sum_query_ab *
					(uint64_t)bcm_dev->bcmdev->width);

		for (i = 0; i < bcm_dev->num_lnodes; i++) {
			if (ctx == ACTIVE_CTX) {
				max_query_ib = max(max_query_ib,
				max(bcm_dev->lnode_list[i].
					lnode_query_ib[ACTIVE_CTX],
				bcm_dev->lnode_list[i].
					lnode_query_ib[DUAL_CTX]));

				max_query_ab = max(max_query_ab,
				bcm_dev->lnode_list[i].
						lnode_query_ab[ACTIVE_CTX] +
				bcm_dev->lnode_list[i].
						lnode_query_ab[DUAL_CTX]);
			} else {
				max_query_ib = max(max_query_ib,
					bcm_dev->lnode_list[i].
						lnode_query_ib[ctx]);
				max_query_ab = max(max_query_ab,
					bcm_dev->lnode_list[i].
						lnode_query_ab[ctx]);
			}
		}

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

	}
exit_bcm_query_bus_req:
	return;
}



int bcm_remove_handoff_req(struct device *dev, void *data)
{
	struct msm_bus_node_device_type *bcm_dev = NULL;
@@ -571,8 +640,6 @@ int bcm_remove_handoff_req(struct device *dev, void *data)
	return ret;
}



static void aggregate_bus_req(struct msm_bus_node_device_type *bus_dev,
									int ctx)
{
@@ -597,6 +664,31 @@ static void aggregate_bus_req(struct msm_bus_node_device_type *bus_dev,
	return;
}

static void aggregate_bus_query_req(struct msm_bus_node_device_type *bus_dev,
									int ctx)
{
	int i;
	uint64_t max_ib = 0;
	uint64_t sum_ab = 0;

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

	for (i = 0; i < bus_dev->num_lnodes; i++) {
		max_ib = max(max_ib,
				bus_dev->lnode_list[i].lnode_query_ib[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].max_query_ib = max_ib;

exit_agg_bus_req:
	return;
}

static void del_inp_list(struct list_head *list)
{
@@ -688,6 +780,14 @@ static void add_node_to_clist(struct msm_bus_node_device_type *node)
	}
}

static void add_node_to_query_list(struct msm_bus_node_device_type *node)
{
	if (!node->query_dirty) {
		list_add_tail(&node->query_link, &query_list);
		node->query_dirty = true;
	}
}

static int update_path(struct device *src_dev, int dest, uint64_t act_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,
@@ -768,6 +868,71 @@ static int update_path(struct device *src_dev, int dest, uint64_t act_req_ib,
	return ret;
}

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 slp_req_bw, uint64_t cur_ib, uint64_t cur_bw,
			int src_idx)
{
	struct device *next_dev = NULL;
	struct link_node *lnode = NULL;
	struct msm_bus_node_device_type *dev_info = NULL;
	int curr_idx;
	int ret = 0;

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

	next_dev = src_dev;

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

	while (next_dev) {
		int i;

		dev_info = to_msm_bus_node(next_dev);

		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_query_path;
		}

		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_query_path;
		}
		lnode->lnode_query_ib[ACTIVE_CTX] = act_req_ib;
		lnode->lnode_query_ab[ACTIVE_CTX] = act_req_bw;
		lnode->lnode_query_ib[DUAL_CTX] = slp_req_ib;
		lnode->lnode_query_ab[DUAL_CTX] = slp_req_bw;

		for (i = 0; i < NUM_CTX; i++) {
			aggregate_bus_query_req(dev_info, i);
			bcm_query_bus_req(next_dev, i);
		}

		add_node_to_query_list(dev_info);

		next_dev = lnode->next_dev;
		curr_idx = lnode->next;
	}

exit_query_path:
	return ret;
}

static int remove_path(struct device *src_dev, int dst, uint64_t cur_ib,
			uint64_t cur_ab, int src_idx, int active_only)
{
@@ -1126,6 +1291,92 @@ static int update_client_paths(struct msm_bus_client *client, bool log_trns,
	return ret;
}

static int query_usecase(struct msm_bus_client *client, bool log_trns,
					unsigned int idx,
					struct msm_bus_tcs_usecase *tcs_usecase)
{
	int lnode, src, dest, cur_idx;
	uint64_t req_clk, req_bw, curr_clk, curr_bw, slp_clk, slp_bw;
	int i, ret = 0;
	struct msm_bus_scale_pdata *pdata;
	struct device *src_dev;
	struct msm_bus_node_device_type *node = NULL;
	struct msm_bus_node_device_type *node_tmp = NULL;

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

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

	cur_idx = client->curr;
	client->curr = idx;
	for (i = 0; i < pdata->usecase->num_paths; i++) {
		src = pdata->usecase[idx].vectors[i].src;
		dest = pdata->usecase[idx].vectors[i].dst;

		lnode = client->src_pnode[i];
		src_dev = client->src_devs[i];
		req_clk = client->pdata->usecase[idx].vectors[i].ib;
		req_bw = client->pdata->usecase[idx].vectors[i].ab;
		if (cur_idx < 0) {
			curr_clk = 0;
			curr_bw = 0;
		} else {
			curr_clk =
				client->pdata->usecase[cur_idx].vectors[i].ib;
			curr_bw = client->pdata->usecase[cur_idx].vectors[i].ab;
			MSM_BUS_DBG("%s:ab: %llu ib: %llu\n", __func__,
					curr_bw, curr_clk);
		}

		ret = query_path(src_dev, dest, req_clk, req_bw, slp_clk,
			slp_bw, curr_clk, curr_bw, lnode);

		if (ret) {
			MSM_BUS_ERR("%s: Query path failed! %d ctx %d\n",
					__func__, ret, pdata->active_only);
			goto exit_query_usecase;
		}
	}
	msm_bus_query_gen(&query_list, tcs_usecase);
	INIT_LIST_HEAD(&query_list);

	for (i = 0; i < pdata->usecase->num_paths; i++) {
		src = pdata->usecase[idx].vectors[i].src;
		dest = pdata->usecase[idx].vectors[i].dst;

		lnode = client->src_pnode[i];
		src_dev = client->src_devs[i];

		ret = query_path(src_dev, dest, 0, 0, 0, 0,
						curr_clk, curr_bw, lnode);

		if (ret) {
			MSM_BUS_ERR("%s: Clear query path failed! %d ctx %d\n",
					__func__, ret, pdata->active_only);
			goto exit_query_usecase;
		}
	}

	list_for_each_entry_safe(node, node_tmp, &query_list, query_link) {
		node->query_dirty = false;
		list_del_init(&node->query_link);
	}

	INIT_LIST_HEAD(&query_list);

exit_query_usecase:
	return ret;
}

static int update_context(uint32_t cl, bool active_only,
					unsigned int ctx_idx)
{
@@ -1244,6 +1495,117 @@ static int update_request_adhoc(uint32_t cl, unsigned int index)
	return ret;
}

static int query_client_usecase(struct msm_bus_tcs_usecase *tcs_usecase,
					uint32_t cl, unsigned int index)
{
	int ret = 0;
	struct msm_bus_scale_pdata *pdata;
	struct msm_bus_client *client;
	const char *test_cl = "Null";
	bool log_transaction = false;

	rt_mutex_lock(&msm_bus_adhoc_lock);

	if (!cl) {
		MSM_BUS_ERR("%s: Invalid client handle %d", __func__, cl);
		ret = -ENXIO;
		goto exit_query_client_usecase;
	}

	client = handle_list.cl_list[cl];
	if (!client) {
		MSM_BUS_ERR("%s: Invalid client pointer ", __func__);
		ret = -ENXIO;
		goto exit_query_client_usecase;
	}

	pdata = client->pdata;
	if (!pdata) {
		MSM_BUS_ERR("%s: Client data Null.[client didn't register]",
				__func__);
		ret = -ENXIO;
		goto exit_query_client_usecase;
	}

	if (index >= pdata->num_usecases) {
		MSM_BUS_ERR("Client %u passed invalid index: %d\n",
			cl, index);
		ret = -ENXIO;
		goto exit_query_client_usecase;
	}

	if (!strcmp(test_cl, pdata->name))
		log_transaction = true;

	MSM_BUS_DBG("%s: cl: %u index: %d curr: %d num_paths: %d\n", __func__,
		cl, index, client->curr, client->pdata->usecase->num_paths);
	ret = query_usecase(client, log_transaction, index, tcs_usecase);
	if (ret) {
		pr_err("%s: Err updating path\n", __func__);
		goto exit_query_client_usecase;
	}

//	trace_bus_update_request_end(pdata->name);

exit_query_client_usecase:
	rt_mutex_unlock(&msm_bus_adhoc_lock);
	return ret;
}

static int query_client_usecase_all(struct msm_bus_tcs_handle *tcs_handle,
					uint32_t cl)
{
	int ret = 0;
	struct msm_bus_scale_pdata *pdata;
	struct msm_bus_client *client;
	const char *test_cl = "Null";
	bool log_transaction = false;
	int i = 0;

	rt_mutex_lock(&msm_bus_adhoc_lock);

	if (!cl) {
		MSM_BUS_ERR("%s: Invalid client handle %d", __func__, cl);
		ret = -ENXIO;
		goto exit_query_client_usecase_all;
	}

	client = handle_list.cl_list[cl];
	if (!client) {
		MSM_BUS_ERR("%s: Invalid client pointer ", __func__);
		ret = -ENXIO;
		goto exit_query_client_usecase_all;
	}

	pdata = client->pdata;
	if (!pdata) {
		MSM_BUS_ERR("%s: Client data Null.[client didn't register]",
				__func__);
		ret = -ENXIO;
		goto exit_query_client_usecase_all;
	}

	if (!strcmp(test_cl, pdata->name))
		log_transaction = true;

	MSM_BUS_ERR("%s: query_start", __func__);
	for (i = 0; i < pdata->num_usecases; i++)
		query_usecase(client, log_transaction, i,
						&tcs_handle->usecases[i]);
	tcs_handle->num_usecases = pdata->num_usecases;

	if (ret) {
		pr_err("%s: Err updating path\n", __func__);
		goto exit_query_client_usecase_all;
	}

//	trace_bus_update_request_end(pdata->name);

exit_query_client_usecase_all:
	rt_mutex_unlock(&msm_bus_adhoc_lock);
	return ret;
}

static void free_cl_mem(struct msm_bus_client_handle *cl)
{
	if (cl) {
@@ -1446,4 +1808,6 @@ void msm_bus_arb_setops_adhoc(struct msm_bus_arb_ops *arb_ops)
	arb_ops->unregister = unregister_adhoc;
	arb_ops->update_bw = update_bw_adhoc;
	arb_ops->update_bw_context = update_bw_context;
	arb_ops->query_usecase = query_client_usecase;
	arb_ops->query_usecase_all = query_client_usecase_all;
}
+39 −0
Original line number Diff line number Diff line
@@ -173,3 +173,42 @@ void msm_bus_scale_unregister(struct msm_bus_client_handle *cl)
				__func__);
}
EXPORT_SYMBOL(msm_bus_scale_unregister);

/**
 * msm_bus_scale_query_tcs_cmd() - Query for a list of TCS commands for
 * an aggregated votes of paths from a single usecase.
 *
 * tcs_usecase: pointer to client allocated memory blob
 * cl: Handle to the client
 * index: Index into the vector, to which the bw and clock values need to be
 * updated
 */
int msm_bus_scale_query_tcs_cmd(struct msm_bus_tcs_usecase *tcs_usecase,
					uint32_t cl, unsigned int index)
{
	if (arb_ops.query_usecase)
		return arb_ops.query_usecase(tcs_usecase, cl, index);
	pr_err("%s: Bus driver not ready.",
			__func__);
	return -EPROBE_DEFER;
}
EXPORT_SYMBOL(msm_bus_scale_query_tcs_cmd);

/**
 * msm_bus_scale_query_tcs_cmd_all() - Query for a list of TCS commands for
 * an aggregated vote of paths for all usecases registered by client
 *
 * tcs_handle: pointer to client allocated memory blob
 * cl: Handle to the client
 *
 */
int msm_bus_scale_query_tcs_cmd_all(struct msm_bus_tcs_handle *tcs_handle,
					uint32_t cl)
{
	if (arb_ops.query_usecase)
		return arb_ops.query_usecase_all(tcs_handle, cl);
	pr_err("%s: Bus driver not ready.",
			__func__);
	return -EPROBE_DEFER;
}
EXPORT_SYMBOL(msm_bus_scale_query_tcs_cmd_all);
+5 −0
Original line number Diff line number Diff line
@@ -69,6 +69,11 @@ struct msm_bus_arb_ops {
	void (*unregister)(struct msm_bus_client_handle *cl);
	int (*update_bw_context)(struct msm_bus_client_handle *cl, u64 act_ab,
				u64 act_ib, u64 slp_ib, u64 slp_ab);
	int (*query_usecase)(struct msm_bus_tcs_usecase *tcs_usecase,
				uint32_t cl, unsigned int index);
	int (*query_usecase_all)(struct msm_bus_tcs_handle *tcs_handle,
				uint32_t cl);

};

enum {
+117 −1
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@
static int msm_bus_dev_init_qos(struct device *dev, void *data);

struct list_head bcm_clist_inorder[VCD_MAX_CNT];
struct list_head bcm_query_list_inorder[VCD_MAX_CNT];
static struct rpmh_client *mbox_apps;

struct bcm_db {
@@ -393,6 +394,41 @@ static int tcs_cmd_list_gen(int *n_active,
	return k;
}

static int tcs_cmd_query_list_gen(struct tcs_cmd *cmdlist_active)
{
	struct msm_bus_node_device_type *cur_bcm = NULL;
	struct list_head *bcm_list_inorder = NULL;
	int i = 0;
	int k = 0;
	bool commit = false;
	int ret = 0;

	if (!cmdlist_active)
		goto exit_tcs_cmd_list_gen;

	bcm_list_inorder = bcm_query_list_inorder;

	for (i = 0; i < VCD_MAX_CNT; i++) {
		if (list_empty(&bcm_list_inorder[i]))
			continue;
		list_for_each_entry(cur_bcm, &bcm_list_inorder[i], query_link) {
			commit = false;
			if (list_is_last(&cur_bcm->query_link,
						&bcm_list_inorder[i])) {
				commit = true;
			}
			tcs_cmd_gen(cur_bcm, &cmdlist_active[k],
				cur_bcm->node_bw[ACTIVE_CTX].max_query_ib,
				cur_bcm->node_bw[ACTIVE_CTX].max_query_ab,
								commit);
			k++;
		}
	}

exit_tcs_cmd_list_gen:
	return ret;
}

static int bcm_clist_add(struct msm_bus_node_device_type *cur_dev)
{
	int ret = 0;
@@ -414,6 +450,26 @@ static int bcm_clist_add(struct msm_bus_node_device_type *cur_dev)
	return ret;
}

static int bcm_query_list_add(struct msm_bus_node_device_type *cur_dev)
{
	int ret = 0;
	int cur_vcd = 0;
	struct msm_bus_node_device_type *cur_bcm = NULL;

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

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

	if (!cur_bcm->query_dirty)
		list_add_tail(&cur_bcm->query_link,
					&bcm_query_list_inorder[cur_vcd]);

exit_bcm_query_list_add:
	return ret;
}

static int bcm_clist_clean(struct msm_bus_node_device_type *cur_dev)
{
	int ret = 0;
@@ -436,6 +492,24 @@ static int bcm_clist_clean(struct msm_bus_node_device_type *cur_dev)
	return ret;
}

static int bcm_query_list_clean(struct msm_bus_node_device_type *cur_dev)
{
	int ret = 0;
	struct msm_bus_node_device_type *cur_bcm = NULL;

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

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

	MSM_BUS_ERR("%s: removing bcm %d\n", __func__, cur_bcm->node_info->id);
	cur_bcm->query_dirty = false;
	list_del_init(&cur_bcm->query_link);

exit_bcm_clist_add:
	return ret;
}

int msm_bus_commit_data(struct list_head *clist)
{
	int ret = 0;
@@ -518,6 +592,46 @@ int msm_bus_commit_data(struct list_head *clist)
	return ret;
}

int msm_bus_query_gen(struct list_head *query_list,
				struct msm_bus_tcs_usecase *tcs_usecase)
{
	int ret = 0;
	struct msm_bus_node_device_type *node = NULL;
	struct msm_bus_node_device_type *node_tmp = NULL;
	struct msm_bus_node_device_type *cur_bcm = NULL;
	int *n_active = NULL;
	int cnt_vcd = 0;
	int cnt_active = 0;
	int i = 0;

	list_for_each_entry_safe(node, node_tmp, query_list, query_link)
		bcm_query_list_add(node);

	for (i = 0; i < VCD_MAX_CNT; i++) {
		if (list_empty(&bcm_query_list_inorder[i]))
			continue;
		list_for_each_entry(cur_bcm, &bcm_query_list_inorder[i],
							query_link) {
			cnt_active++;
		}
		cnt_vcd++;
	}

	tcs_usecase->num_cmds = cnt_active;
	ret = tcs_cmd_query_list_gen(tcs_usecase->cmds);

	list_for_each_entry_safe(node, node_tmp, query_list, query_link) {
		bcm_query_list_clean(node);
		node->query_dirty = false;
		list_del_init(&node->query_link);
	}

	kfree(n_active);
	return ret;
}



void *msm_bus_realloc_devmem(struct device *dev, void *p, size_t old_size,
					size_t new_size, gfp_t flags)
{
@@ -817,8 +931,10 @@ static int msm_bus_bcm_init(struct device *dev,
	bcmdev->num_bus_devs = 0;

	// Add way to count # of VCDs, initialize LL
	for (i = 0; i < VCD_MAX_CNT; i++)
	for (i = 0; i < VCD_MAX_CNT; i++) {
		INIT_LIST_HEAD(&bcm_clist_inorder[i]);
		INIT_LIST_HEAD(&bcm_query_list_inorder[i]);
	}

exit_bcm_init:
	return ret;
Loading