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

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

Merge "msm: ipa: change ipa_active_clients locking scheme"

parents 78bb0bc5 17e9d691
Loading
Loading
Loading
Loading
+31 −31
Original line number Diff line number Diff line
@@ -1586,6 +1586,7 @@ void ipa_disable_clks(void)
	if (msm_bus_scale_client_update_request(ipa_ctx->ipa_bus_hdl, 0))
		WARN_ON(1);
}

/**
 * ipa_start_tag_process() - Send TAG packet and wait for it to come back
 *
@@ -1602,10 +1603,7 @@ static void ipa_start_tag_process(struct work_struct *work)
	int res;

	IPADBG("starting TAG process\n");
	mutex_lock(&ipa_ctx->ipa_active_clients_lock);
	ipa_ctx->start_tag_process_again = false;
	mutex_unlock(&ipa_ctx->ipa_active_clients_lock);

	/* close aggregation frames on all pipes */
	res = ipa_tag_aggr_force_close(-1);
	if (res) {
@@ -1613,20 +1611,20 @@ static void ipa_start_tag_process(struct work_struct *work)
		return;
	}

	mutex_lock(&ipa_ctx->ipa_active_clients_lock);
	ipa_ctx->ipa_active_clients--;
	if (ipa_ctx->ipa_active_clients == 0) {
	ipa_active_clients_lock();
	ipa_ctx->ipa_active_clients.cnt--;
	if (ipa_ctx->ipa_active_clients.cnt == 0) {
		/* check if during tag process a client used IPA */
		if (ipa_ctx->start_tag_process_again) {
			IPADBG("Starting TAG process again\n");
			ipa_ctx->ipa_active_clients = 1;
			mutex_unlock(&ipa_ctx->ipa_active_clients_lock);
			ipa_ctx->ipa_active_clients.cnt = 1;
			ipa_active_clients_unlock();
			queue_work(ipa_ctx->power_mgmt_wq, &ipa_tag_work);
			return;
		}
		ipa_disable_clks();
	}
	mutex_unlock(&ipa_ctx->ipa_active_clients_lock);
	ipa_active_clients_unlock();

	IPADBG("TAG process done\n");
	return;
@@ -1641,12 +1639,12 @@ static void ipa_start_tag_process(struct work_struct *work)
*/
void ipa_inc_client_enable_clks(void)
{
	mutex_lock(&ipa_ctx->ipa_active_clients_lock);
	ipa_ctx->ipa_active_clients++;
	IPADBG("active clients = %d\n", ipa_ctx->ipa_active_clients);
	if (ipa_ctx->ipa_active_clients == 1)
	ipa_active_clients_lock();
	ipa_ctx->ipa_active_clients.cnt++;
	if (ipa_ctx->ipa_active_clients.cnt == 1)
		ipa_enable_clks();
	mutex_unlock(&ipa_ctx->ipa_active_clients_lock);
	IPADBG("active clients = %d\n", ipa_ctx->ipa_active_clients.cnt);
	ipa_active_clients_unlock();
}

/**
@@ -1661,17 +1659,18 @@ int ipa_inc_client_enable_clks_no_block(void)
{
	int res = 0;

	if (mutex_trylock(&ipa_ctx->ipa_active_clients_lock) == 0)
	if (ipa_active_clients_trylock() == 0)
		return -EPERM;
	if (ipa_ctx->ipa_active_clients == 0) {

	if (ipa_ctx->ipa_active_clients.cnt == 0) {
		res = -EPERM;
		goto bail;
	}

	ipa_ctx->ipa_active_clients++;
	IPADBG("active clients = %d\n", ipa_ctx->ipa_active_clients);
	ipa_ctx->ipa_active_clients.cnt++;
	IPADBG("active clients = %d\n", ipa_ctx->ipa_active_clients.cnt);
bail:
	mutex_unlock(&ipa_ctx->ipa_active_clients_lock);
	ipa_active_clients_unlock();

	return res;
}
@@ -1689,18 +1688,18 @@ bail:
 */
void ipa_dec_client_disable_clks(void)
{
	mutex_lock(&ipa_ctx->ipa_active_clients_lock);
	ipa_active_clients_lock();
	ipa_ctx->start_tag_process_again = true;
	ipa_ctx->ipa_active_clients--;
	IPADBG("active clients = %d\n", ipa_ctx->ipa_active_clients);
	if (ipa_ctx->ipa_active_clients == 0) {
	ipa_ctx->ipa_active_clients.cnt--;
	IPADBG("active clients = %d\n", ipa_ctx->ipa_active_clients.cnt);
	if (ipa_ctx->ipa_active_clients.cnt == 0) {
		/* when TAG process ends, active clients will be decreased */
		ipa_ctx->ipa_active_clients = 1;
		mutex_unlock(&ipa_ctx->ipa_active_clients_lock);
		ipa_ctx->ipa_active_clients.cnt = 1;
		ipa_active_clients_unlock();
		queue_work(ipa_ctx->power_mgmt_wq, &ipa_tag_work);
		return;
	}
	mutex_unlock(&ipa_ctx->ipa_active_clients_lock);
	ipa_active_clients_unlock();
}

static int ipa_setup_bam_cfg(const struct ipa_plat_drv_res *res)
@@ -1779,14 +1778,14 @@ int ipa_set_required_perf_profile(enum ipa_voltage_level floor_voltage,
		return 0;
	}

	mutex_lock(&ipa_ctx->ipa_active_clients_lock);
	ipa_active_clients_lock();
	ipa_ctx->curr_ipa_clk_rate = clk_rate;
	IPADBG("setting clock rate to %u\n", ipa_ctx->curr_ipa_clk_rate);
	if (ipa_ctx->ipa_active_clients > 0)
	if (ipa_ctx->ipa_active_clients.cnt > 0)
		clk_set_rate(ipa_clk, ipa_ctx->curr_ipa_clk_rate);
	else
		IPADBG("clocks are gated, not setting rate\n");
	mutex_unlock(&ipa_ctx->ipa_active_clients_lock);
	ipa_active_clients_unlock();
	IPADBG("Done\n");
	return 0;
}
@@ -2194,8 +2193,9 @@ static int ipa_init(const struct ipa_plat_drv_res *resource_p,
	idr_init(&ipa_ctx->ipa_idr);
	spin_lock_init(&ipa_ctx->idr_lock);

	mutex_init(&ipa_ctx->ipa_active_clients_lock);
	ipa_ctx->ipa_active_clients = 1;
	mutex_init(&ipa_ctx->ipa_active_clients.mutex);
	spin_lock_init(&ipa_ctx->ipa_active_clients.spinlock);
	ipa_ctx->ipa_active_clients.cnt = 1;

	/* wlan related member */
	spin_lock_init(&ipa_ctx->wlan_spinlock);
+2 −2
Original line number Diff line number Diff line
@@ -729,7 +729,7 @@ static ssize_t ipa_read_stats(struct file *file, char __user *ubuf,
			ipa_ctx->stats.stat_compl,
			ipa_ctx->stats.aggr_close,
			ipa_ctx->stats.wan_aggr_close,
			ipa_ctx->ipa_active_clients,
			ipa_ctx->ipa_active_clients.cnt,
			connect);
		cnt += nbytes;

@@ -755,7 +755,7 @@ static ssize_t ipa_read_stats(struct file *file, char __user *ubuf,
			ipa_ctx->stats.rx_pkts,
			ipa_ctx->stats.rx_repl_repost,
			ipa_ctx->stats.rx_q_len,
			ipa_ctx->ipa_active_clients,
			ipa_ctx->ipa_active_clients.cnt,
			connect);
	cnt += nbytes;

+11 −3
Original line number Diff line number Diff line
@@ -593,6 +593,12 @@ struct ipa_wlan_stats {
	u32 tx_pkts_dropped;
};

struct ipa_active_clients {
	struct mutex mutex;
	spinlock_t spinlock;
	bool mutex_locked;
	int cnt;
};

struct ipa_controller;

@@ -644,6 +650,7 @@ struct ipa_controller;
 * @start_tag_process_again: indicates whether to start tag process again
 * @pipe_mem_pool: pipe memory pool
 * @dma_pool: special purpose DMA pool
 * @ipa_active_clients: structure for reference counting connected IPA clients
 * @ipa_hw_type: type of IPA HW type (e.g. IPA 1.0, IPA 1.1 etc')
 * @ipa_hw_mode: mode of IPA HW mode (e.g. Normal, Virtual or over PCIe)
 * @use_ipa_teth_bridge: use tethering bridge driver
@@ -698,8 +705,7 @@ struct ipa_context {
	struct ipa_mem_buffer empty_rt_tbl_mem;
	struct gen_pool *pipe_mem_pool;
	struct dma_pool *dma_pool;
	struct mutex ipa_active_clients_lock;
	int ipa_active_clients;
	struct ipa_active_clients ipa_active_clients;
	struct workqueue_struct *power_mgmt_wq;
	bool start_tag_process_again;
	u32 clnt_hdl_cmd;
@@ -948,6 +954,8 @@ int ipa_resume_resource(enum ipa_rm_resource_name name);
bool ipa_should_pipe_be_suspended(enum ipa_client_type client);
int ipa_tag_aggr_force_close(int pipe_num);


void ipa_active_clients_lock(void);
int ipa_active_clients_trylock(void);
void ipa_active_clients_unlock(void);

#endif /* _IPA_I_H_ */
+37 −5
Original line number Diff line number Diff line
@@ -230,6 +230,37 @@ static struct msm_bus_scale_pdata ipa_bus_client_pdata_v2_0 = {
	.name = "ipa",
};

void ipa_active_clients_lock(void)
{
	mutex_lock(&ipa_ctx->ipa_active_clients.mutex);
	spin_lock(&ipa_ctx->ipa_active_clients.spinlock);
	ipa_ctx->ipa_active_clients.mutex_locked = true;
	spin_unlock(&ipa_ctx->ipa_active_clients.spinlock);
}

int ipa_active_clients_trylock(void)
{
	spin_lock(&ipa_ctx->ipa_active_clients.spinlock);
	if (ipa_ctx->ipa_active_clients.mutex_locked) {
		spin_unlock(&ipa_ctx->ipa_active_clients.spinlock);
		return 0;
	}

	return 1;
}

void ipa_active_clients_unlock(void)
{
	if (ipa_ctx->ipa_active_clients.mutex_locked) {
		spin_lock(&ipa_ctx->ipa_active_clients.spinlock);
		ipa_ctx->ipa_active_clients.mutex_locked = false;
		spin_unlock(&ipa_ctx->ipa_active_clients.spinlock);
		mutex_unlock(&ipa_ctx->ipa_active_clients.mutex);
		return;
	}
	spin_unlock(&ipa_ctx->ipa_active_clients.spinlock);
}

/**
 * ipa_get_clients_from_rm_resource() - get IPA clients which are related to an
 * IPA_RM resource
@@ -381,9 +412,9 @@ int ipa_suspend_resource_no_block(enum ipa_rm_resource_name resource)
	struct ipa_ep_cfg_ctrl suspend;
	int ipa_ep_idx;

	if (mutex_trylock(&ipa_ctx->ipa_active_clients_lock) == 0)
	if (ipa_active_clients_trylock() == 0)
		return -EPERM;
	if (ipa_ctx->ipa_active_clients == 1) {
	if (ipa_ctx->ipa_active_clients.cnt == 1) {
		res = -EPERM;
		goto bail;
	}
@@ -414,11 +445,12 @@ int ipa_suspend_resource_no_block(enum ipa_rm_resource_name resource)
	}

	if (res == 0) {
		ipa_ctx->ipa_active_clients--;
		IPADBG("active clients = %d\n", ipa_ctx->ipa_active_clients);
		ipa_ctx->ipa_active_clients.cnt--;
		IPADBG("active clients = %d\n",
		       ipa_ctx->ipa_active_clients.cnt);
	}
bail:
	mutex_unlock(&ipa_ctx->ipa_active_clients_lock);
	ipa_active_clients_unlock();

	return res;
}