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

Commit 957d576e authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: msm_bus: Add new APIs for bus scaling"

parents ad0a77e5 3e569eb3
Loading
Loading
Loading
Loading
+131 −1
Original line number Diff line number Diff line
@@ -19,9 +19,11 @@
#include <linux/msm-bus.h>
#include "msm_bus_core.h"
#include "msm_bus_adhoc.h"
#include <trace/events/trace_msm_bus.h>

#define NUM_CL_HANDLES	50
#define NUM_LNODES	3
#define MAX_STR_CL	50

struct bus_search_type {
	struct list_head link;
@@ -951,6 +953,7 @@ 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__,
		cl, index, client->curr, client->pdata->usecase->num_paths);

	msm_bus_dbg_client_data(client->pdata, index , cl);
	for (i = 0; i < pdata->usecase->num_paths; i++) {
		src = client->pdata->usecase[index].vectors[i].src;
		dest = client->pdata->usecase[index].vectors[i].dst;
@@ -980,12 +983,135 @@ static int update_request_adhoc(uint32_t cl, unsigned int index)
		if (log_transaction)
			getpath_debug(src, lnode, pdata->active_only);
	}
	msm_bus_dbg_client_data(client->pdata, index , cl);
	trace_bus_update_request_end(pdata->name);
exit_update_request:
	mutex_unlock(&msm_bus_adhoc_lock);
	return ret;
}

static void free_cl_mem(struct msm_bus_client_handle *cl)
{
	if (cl) {
		kfree(cl->name);
		kfree(cl);
		cl = NULL;
	}
}

static int update_bw_adhoc(struct msm_bus_client_handle *cl, u64 ab, u64 ib)
{
	int ret = 0;
	char *test_cl = "test-client";
	bool log_transaction = false;

	mutex_lock(&msm_bus_adhoc_lock);

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

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

	msm_bus_dbg_rec_transaction(cl, ab, ib);

	if ((cl->cur_ib == ib) && (cl->cur_ab == ab)) {
		MSM_BUS_DBG("%s:no change in request", cl->name);
		goto exit_update_request;
	}

	ret = update_path(cl->mas, cl->slv, ib, ab, cl->cur_ib, cl->cur_ab,
						cl->first_hop, cl->active_only);

	if (ret) {
		MSM_BUS_ERR("%s: Update path failed! %d active_only %d\n",
				__func__, ret, cl->active_only);
		goto exit_update_request;
	}

	cl->cur_ib = ib;
	cl->cur_ab = ab;

	if (log_transaction)
		getpath_debug(cl->mas, cl->first_hop, cl->active_only);
	trace_bus_update_request_end(cl->name);
exit_update_request:
	mutex_unlock(&msm_bus_adhoc_lock);

	return ret;
}

static void unregister_adhoc(struct msm_bus_client_handle *cl)
{
	mutex_lock(&msm_bus_adhoc_lock);
	if (!cl) {
		MSM_BUS_ERR("%s: Null cl handle passed unregister\n",
				__func__);
		goto exit_unregister_client;
	}

	MSM_BUS_DBG("%s: Unregistering client %p", __func__, cl);

	remove_path(cl->mas, cl->slv, cl->cur_ib, cl->cur_ab,
				cl->first_hop, cl->active_only);

	msm_bus_dbg_remove_client(cl);
	kfree(cl);
exit_unregister_client:
	mutex_unlock(&msm_bus_adhoc_lock);
	return;
}


static struct msm_bus_client_handle*
register_adhoc(uint32_t mas, uint32_t slv, char *name, bool active_only)
{
	struct msm_bus_client_handle *client = NULL;
	int len = 0;

	mutex_lock(&msm_bus_adhoc_lock);

	if (!(mas && slv && name)) {
		pr_err("%s: Error: src dst name num_paths are required",
								 __func__);
		goto exit_register;
	}

	client = kzalloc(sizeof(struct msm_bus_client_handle), GFP_KERNEL);
	if (!client) {
		MSM_BUS_ERR("%s: Error allocating client data", __func__);
		goto exit_register;
	}

	len = strnlen(name, MAX_STR_CL);
	client->name = kzalloc(len, GFP_KERNEL);
	if (!client->name) {
		MSM_BUS_ERR("%s: Error allocating client name buf", __func__);
		free_cl_mem(client);
		goto exit_register;
	}
	strlcpy(client->name, name, MAX_STR_CL);
	client->active_only = active_only;

	client->mas = mas;
	client->slv = slv;
	client->first_hop = getpath(client->mas, client->slv);
	if (client->first_hop < 0) {
		MSM_BUS_ERR("%s:Failed to find path.src %d dest %d",
			__func__, client->mas, client->slv);
		free_cl_mem(client);
		goto exit_register;
	}

	MSM_BUS_DBG("%s:Client handle %p %s", __func__, client,
						client->name);
	msm_bus_dbg_add_client(client);
exit_register:
	mutex_unlock(&msm_bus_adhoc_lock);
	return client;
}
/**
 *  msm_bus_arb_setops_adhoc() : Setup the bus arbitration ops
 *  @ arb_ops: pointer to the arb ops.
@@ -995,4 +1121,8 @@ void msm_bus_arb_setops_adhoc(struct msm_bus_arb_ops *arb_ops)
	arb_ops->register_client = register_client_adhoc;
	arb_ops->update_request = update_request_adhoc;
	arb_ops->unregister_client = unregister_client_adhoc;

	arb_ops->register_cl = register_adhoc;
	arb_ops->unregister = unregister_adhoc;
	arb_ops->update_bw = update_bw_adhoc;
}
+59 −0
Original line number Diff line number Diff line
@@ -81,3 +81,62 @@ void msm_bus_scale_unregister_client(uint32_t cl)
	}
}
EXPORT_SYMBOL(msm_bus_scale_unregister_client);

/**
 * msm_bus_scale_register() - Register the clients with the msm bus
 * driver
 * @pdata: Platform data of the client, containing src, dest, ab, ib.
 * Return non-zero value in case of success, 0 in case of failure.
 *
 * Client data contains the vectors specifying arbitrated bandwidth (ab)
 * and instantaneous bandwidth (ib) requested between a particular
 * src and dest.
 */
struct msm_bus_client_handle*
msm_bus_scale_register(uint32_t mas, uint32_t slv, char *name, bool active_only)
{
	if (arb_ops.register_cl)
		return arb_ops.register_cl(mas, slv, name, active_only);
	else {
		pr_err("%s: Bus driver not ready.",
				__func__);
		return ERR_PTR(-EPROBE_DEFER);

	}
}
EXPORT_SYMBOL(msm_bus_scale_register);

/**
 * msm_bus_scale_client_update_bw() - Update the request for bandwidth
 * from a particular client
 *
 * 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_update_bw(struct msm_bus_client_handle *cl, u64 ab, u64 ib)
{
	if (arb_ops.update_request)
		return arb_ops.update_bw(cl, ab, ib);
	else {
		pr_err("%s: Bus driver not ready.", __func__);
		return -EPROBE_DEFER;
	}
}
EXPORT_SYMBOL(msm_bus_scale_update_bw);

/**
 * msm_bus_scale_unregister() - Update the request for bandwidth
 * from a particular client
 *
 * cl: Handle to the client
 */
void msm_bus_scale_unregister(struct msm_bus_client_handle *cl)
{
	if (arb_ops.unregister)
		arb_ops.unregister(cl);
	else
		pr_err("%s: Bus driver not ready.",
				__func__);
}
EXPORT_SYMBOL(msm_bus_scale_unregister);
+27 −0
Original line number Diff line number Diff line
@@ -58,6 +58,11 @@ struct msm_bus_arb_ops {
	uint32_t (*register_client)(struct msm_bus_scale_pdata *pdata);
	int (*update_request)(uint32_t cl, unsigned int index);
	void (*unregister_client)(uint32_t cl);
	struct msm_bus_client_handle*
		(*register_cl)(uint32_t mas, uint32_t slv, char *name,
						bool active_only);
	int (*update_bw)(struct msm_bus_client_handle *cl, u64 ab, u64 ib);
	void (*unregister)(struct msm_bus_client_handle *cl);
};

enum {
@@ -313,6 +318,11 @@ void msm_bus_dbg_client_data(struct msm_bus_scale_pdata *pdata, int index,
	uint32_t cl);
void msm_bus_dbg_commit_data(const char *fabname, void *cdata,
	int nmasters, int nslaves, int ntslaves, int op);
int msm_bus_dbg_add_client(const struct msm_bus_client_handle *pdata);
int msm_bus_dbg_rec_transaction(const struct msm_bus_client_handle *pdata,
						u64 ab, u64 ib);
void msm_bus_dbg_remove_client(const struct msm_bus_client_handle *pdata);

#else
static inline void msm_bus_dbg_client_data(struct msm_bus_scale_pdata *pdata,
	int index, uint32_t cl)
@@ -323,6 +333,23 @@ static inline void msm_bus_dbg_commit_data(const char *fabname,
	int op)
{
}
static inline void void msm_bus_dbg_remove_client
		(const struct msm_bus_client_handle *pdata)
{
}

static inline int
msm_bus_dbg_rec_transaction(const struct msm_bus_client_handle *pdata,
						u64 ab, u64 ib)
{
	return 0;
}

static inline int
msm_bus_dbg_add_client(const struct msm_bus_client_handle *pdata)
{
	return 0;
}
#endif

#ifdef CONFIG_CORESIGHT
+94 −2
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ struct msm_bus_dbg_state {

struct msm_bus_cldata {
	const struct msm_bus_scale_pdata *pdata;
	const struct msm_bus_client_handle *handle;
	int index;
	uint32_t clid;
	int size;
@@ -285,14 +286,17 @@ static ssize_t client_data_read(struct file *file, char __user *buf,
	int bsize = 0;
	uint32_t cl = (uint32_t)(uintptr_t)file->private_data;
	struct msm_bus_cldata *cldata = NULL;
	const struct msm_bus_client_handle *handle = file->private_data;
	int found = 0;

	list_for_each_entry(cldata, &cl_list, list) {
		if (cldata->clid == cl) {
		if ((cldata->clid == cl) ||
			(cldata->handle && (cldata->handle == handle))) {
			found = 1;
			break;
		}
	}

	if (!found)
		return 0;

@@ -323,6 +327,93 @@ struct dentry *msm_bus_dbg_create(const char *name, mode_t mode,
		&client_data_fops);
}

int msm_bus_dbg_add_client(const struct msm_bus_client_handle *pdata)

{
	struct msm_bus_cldata *cldata;

	cldata = kzalloc(sizeof(struct msm_bus_cldata), GFP_KERNEL);
	if (!cldata) {
		MSM_BUS_DBG("Failed to allocate memory for client data\n");
		return -ENOMEM;
	}
	cldata->handle = pdata;
	list_add_tail(&cldata->list, &cl_list);
	return 0;
}

int msm_bus_dbg_rec_transaction(const struct msm_bus_client_handle *pdata,
						u64 ab, u64 ib)
{
	struct msm_bus_cldata *cldata;
	int i;
	struct timespec ts;
	bool found = false;
	char *buf = NULL;

	list_for_each_entry(cldata, &cl_list, list) {
		if (cldata->handle == pdata) {
			found = true;
			break;
		}
	}

	if (!found)
		return -ENOENT;

	if (cldata->file == NULL) {
		if (pdata->name == NULL) {
			MSM_BUS_DBG("Client doesn't have a name\n");
			return -EINVAL;
		}
		pr_err("\n%s setting up debugfs %s", __func__, pdata->name);
		cldata->file = debugfs_create_file(pdata->name, S_IRUGO,
				clients, (void *)pdata, &client_data_fops);
	}

	if (cldata->size < (MAX_BUFF_SIZE - FILL_LIMIT))
		i = cldata->size;
	else {
		i = 0;
		cldata->size = 0;
	}
	buf = cldata->buffer;
	ts = ktime_to_timespec(ktime_get());
	i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n%d.%d\n",
		(int)ts.tv_sec, (int)ts.tv_nsec);
	i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "master: ");

	i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "%d  ", pdata->mas);
	i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\nslave : ");
	i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "%d  ", pdata->slv);
	i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\nab     : ");
	i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "%llu  ", ab);

	i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\nib     : ");
	i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "%llu  ", ib);
	i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n");
	cldata->size = i;

	trace_bus_update_request((int)ts.tv_sec, (int)ts.tv_nsec,
		pdata->name, pdata->mas, pdata->slv, ab, ib);

	return i;
}

void msm_bus_dbg_remove_client(const struct msm_bus_client_handle *pdata)
{
	struct msm_bus_cldata *cldata = NULL;

	list_for_each_entry(cldata, &cl_list, list) {
		if (cldata->handle == pdata) {
			debugfs_remove(cldata->file);
			list_del(&cldata->list);
			kfree(cldata);
			break;
		}
	}
}

static int msm_bus_dbg_record_client(const struct msm_bus_scale_pdata *pdata,
	int index, uint32_t clid, struct dentry *file)
{
@@ -416,12 +507,13 @@ static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata,

	for (j = 0; j < pdata->usecase->num_paths; j++)
		trace_bus_update_request((int)ts.tv_sec, (int)ts.tv_nsec,
		pdata->name, index,
		pdata->name,
		pdata->usecase[index].vectors[j].src,
		pdata->usecase[index].vectors[j].dst,
		pdata->usecase[index].vectors[j].ab,
		pdata->usecase[index].vectors[j].ib);

	cldata->index = index;
	cldata->size = i;
	return i;
}
+35 −0
Original line number Diff line number Diff line
@@ -66,6 +66,16 @@ struct msm_bus_scale_pdata {
	unsigned int active_only;
};

struct msm_bus_client_handle {
	char *name;
	int mas;
	int slv;
	int first_hop;
	u64 cur_ib;
	u64 cur_ab;
	bool active_only;
};

/* Scaling APIs */

/*
@@ -79,12 +89,19 @@ int __init msm_bus_fabric_init_driver(void);
uint32_t msm_bus_scale_register_client(struct msm_bus_scale_pdata *pdata);
int msm_bus_scale_client_update_request(uint32_t cl, unsigned int index);
void msm_bus_scale_unregister_client(uint32_t cl);

struct msm_bus_client_handle*
msm_bus_scale_register(uint32_t mas, uint32_t slv, char *name,
							bool active_only);
void msm_bus_scale_unregister(struct msm_bus_client_handle *cl);
int msm_bus_scale_update_bw(struct msm_bus_client_handle *cl, u64 ab, u64 ib);
/* AXI Port configuration APIs */
int msm_bus_axi_porthalt(int master_port);
int msm_bus_axi_portunhalt(int master_port);

#else
static inline int __init msm_bus_fabric_init_driver(void) { return 0; }
static struct msm_bus_client_handle dummy_cl;

static inline uint32_t
msm_bus_scale_register_client(struct msm_bus_scale_pdata *pdata)
@@ -112,6 +129,24 @@ static inline int msm_bus_axi_portunhalt(int master_port)
{
	return 0;
}

static inline struct msm_bus_client_handle*
msm_bus_scale_register(uint32_t mas, uint32_t slv, char *name,
							bool active_only)
{
	return &dummy_cl;
}

static inline void msm_bus_scale_unregister(struct msm_bus_client_handle *cl)
{
}

static inline int
msm_bus_scale_update_bw(uint32_t cl, u64 ab, u64 ib)
{
	return 0;
}

#endif

#if defined(CONFIG_OF) && defined(CONFIG_MSM_BUS_SCALING)
Loading