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

Commit c06df416 authored by Michael Adisumarta's avatar Michael Adisumarta Committed by Gerrit - the friendly Code Review server
Browse files

msm: ipa4: Introduce IPA PM to IPA



Introduce a new framework to allow power management between
different clients. Allows string based client registration,
synchronous/asynchronous activation and deactivation, and
scales clock based on activated clients throughput with
the option to override for a specific use case.

Change-Id: I0028e006a0a50f408694bca9b59fbc900125be8d
CRs-Fixed: 2097404
Signed-off-by: default avatarMichael Adisumarta <madisuma@codeaurora.org>
parent f5d98565
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -4,6 +4,6 @@ obj-$(CONFIG_IPA3) += ipat.o
ipat-y := ipa.o ipa_debugfs.o ipa_hdr.o ipa_flt.o ipa_rt.o ipa_dp.o ipa_client.o \
	ipa_utils.o ipa_nat.o ipa_intf.o teth_bridge.o ipa_interrupts.o \
	ipa_uc.o ipa_uc_wdi.o ipa_dma.o ipa_uc_mhi.o ipa_mhi.o ipa_uc_ntn.o \
	ipa_hw_stats.o
	ipa_hw_stats.o ipa_pm.o

obj-$(CONFIG_RMNET_IPA3) += rmnet_ipa.o ipa_qmi_service_v01.o ipa_qmi_service.o rmnet_ipa_fd_ioctl.o
+47 −0
Original line number Diff line number Diff line
@@ -3712,6 +3712,53 @@ void ipa3_dec_release_wakelock(void)
	spin_unlock_irqrestore(&ipa3_ctx->wakelock_ref_cnt.spinlock, flags);
}

int ipa3_set_clock_plan_from_pm(int idx)
{
	u32 clk_rate;

	IPADBG_LOW("idx = %d\n", idx);

	if (idx <= 0 || idx >= ipa3_ctx->ctrl->msm_bus_data_ptr->num_usecases) {
		IPAERR("bad voltage\n");
		return -EINVAL;
	}

	if (idx == 1)
		clk_rate = ipa3_ctx->ctrl->ipa_clk_rate_svs;
	else if (idx == 2)
		clk_rate = ipa3_ctx->ctrl->ipa_clk_rate_nominal;
	else if (idx == 3)
		clk_rate = ipa3_ctx->ctrl->ipa_clk_rate_turbo;
	else {
		IPAERR("bad voltage\n");
		WARN_ON(1);
		return -EFAULT;
	}

	if (clk_rate == ipa3_ctx->curr_ipa_clk_rate) {
		IPADBG_LOW("Same voltage\n");
		return 0;
	}

	mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex);
	ipa3_ctx->curr_ipa_clk_rate = clk_rate;
	ipa3_ctx->ipa3_active_clients.bus_vote_idx = idx;
	IPADBG_LOW("setting clock rate to %u\n", ipa3_ctx->curr_ipa_clk_rate);
	if (atomic_read(&ipa3_ctx->ipa3_active_clients.cnt) > 0) {
		if (ipa3_clk)
			clk_set_rate(ipa3_clk, ipa3_ctx->curr_ipa_clk_rate);
		if (msm_bus_scale_client_update_request(ipa3_ctx->ipa_bus_hdl,
				ipa3_get_bus_vote()))
			WARN_ON(1);
	} else {
		IPADBG_LOW("clocks are gated, not setting rate\n");
	}
	mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex);
	IPADBG_LOW("Done\n");

	return 0;
}

int ipa3_set_required_perf_profile(enum ipa_voltage_level floor_voltage,
				  u32 bandwidth_mbps)
{
+2 −0
Original line number Diff line number Diff line
@@ -869,6 +869,7 @@ struct ipa3_stats {
struct ipa3_active_clients {
	struct mutex mutex;
	atomic_t cnt;
	int bus_vote_idx;
};

struct ipa3_wakelock_ref_cnt {
@@ -2226,4 +2227,5 @@ void ipa3_disable_prefetch(enum ipa_client_type client);
int ipa3_alloc_common_event_ring(void);
int ipa3_allocate_dma_task_for_gsi(void);
void ipa3_free_dma_task_for_gsi(void);
int ipa3_set_clock_plan_from_pm(int idx);
#endif /* _IPA3_I_H_ */
+1301 −0

File added.

Preview size limit exceeded, changes collapsed.

+110 −0
Original line number Diff line number Diff line
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
 *
 * 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
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifndef _IPA_PM_H_
#define _IPA_PM_H_

#include <linux/msm_ipa.h>

/* internal to ipa */
#define IPA_PM_MAX_CLIENTS 10
#define IPA_PM_MAX_EX_CL 64
#define IPA_PM_THRESHOLD_MAX 2
#define IPA_PM_EXCEPTION_MAX 2
#define IPA_PM_DEFERRED_TIMEOUT 100
#define IPA_PM_STATE_MAX 7

/*
 * ipa_pm group names
 *
 * Default stands for individual clients while other groups share one throughput
 * Some groups also have special flags like modem which do not vote for clock
 * but is accounted for in clock scaling while activated
 */
enum ipa_pm_group {
	IPA_PM_GROUP_DEFAULT,
	IPA_PM_GROUP_APPS,
	IPA_PM_GROUP_MODEM,
	IPA_PM_GROUP_MAX,
};

/*
 * ipa_pm_cb_event
 *
 * specifies what kind of callback is being called.
 * IPA_PM_CLIENT_ACTIVATED: the client has completed asynchronous activation
 * IPA_PM_REQUEST_WAKEUP: wake up the client after it has been suspended
 */
enum ipa_pm_cb_event {
	IPA_PM_CLIENT_ACTIVATED,
	IPA_PM_REQUEST_WAKEUP,
	IPA_PM_CB_EVENT_MAX,
};

/*
 * struct ipa_pm_exception - clients included in exception and its threshold
 * @usecase: comma separated client names
 * @threshold: the threshold values for the exception
 */
struct ipa_pm_exception {
	const char *usecase;
	int threshold[IPA_PM_THRESHOLD_MAX];
};

/*
 * struct ipa_pm_init_params - parameters needed for initializng the pm
 * @default_threshold: the thresholds used if no exception passes
 * @threshold_size: size of the threshold
 * @exceptions: list of exceptions  for the pm
 * @exception_size: size of the exception_list
 */
struct ipa_pm_init_params {
	int default_threshold[IPA_PM_THRESHOLD_MAX];
	int threshold_size;
	struct ipa_pm_exception exceptions[IPA_PM_EXCEPTION_MAX];
	int exception_size;
};

/*
 * struct ipa_pm_register_params - parameters needed to register a client
 * @name: name of the client
 * @callback: pointer to the client's callback function
 * @user_data: pointer to the client's callback parameters
 * @group: group number of the client
 * @skip_clk_vote: 0 if client votes for clock when activated, 1 if no vote
 */
struct ipa_pm_register_params {
	const char *name;
	void (*callback)(void*, enum ipa_pm_cb_event);
	void *user_data;
	enum ipa_pm_group group;
	bool skip_clk_vote;
};

int ipa_pm_register(struct ipa_pm_register_params *params, u32 *hdl);
int ipa_pm_associate_ipa_cons_to_client(u32 hdl, enum ipa_client_type consumer);
int ipa_pm_activate(u32 hdl);
int ipa_pm_activate_sync(u32 hdl);
int ipa_pm_deferred_deactivate(u32 hdl);
int ipa_pm_deactivate_sync(u32 hdl);
int ipa_pm_set_perf_profile(u32 hdl, int throughput);
int ipa_pm_deregister(u32 hdl);

/* IPA Internal Functions */
int ipa_pm_init(struct ipa_pm_init_params *params);
int ipa_pm_destroy(void);
int ipa_pm_handle_suspend(u32 pipe_bitmask);
int ipa_pm_deactivate_all_deferred(void);
int ipa_pm_stat(char *buf, int size);
int ipa_pm_exceptions_stat(char *buf, int size);

#endif /* _IPA_PM_H_ */