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

Commit 7609c586 authored by Skylar Chang's avatar Skylar Chang
Browse files

msm: ipa: use bitmap for wakelock ref_count



Current wakelock ref_count is shared with all
the clients. There is a possibility that each
client could increase wakelock ref_count by
accident. Change the wakelock ref_count to bitmap
so each client can only update its own bit once.

Change-Id: I87f47cf54dc34a76dc2c4a537108f9be7b6bdba8
Signed-off-by: default avatarSkylar Chang <chiaweic@codeaurora.org>
parent d8a56111
Loading
Loading
Loading
Loading
+16 −7
Original line number Diff line number Diff line
@@ -3206,15 +3206,21 @@ void ipa2_dec_client_disable_clks(struct ipa2_active_client_logging_info *id)
* Return codes:
* None
*/
void ipa_inc_acquire_wakelock(void)
void ipa_inc_acquire_wakelock(enum ipa_wakelock_ref_client ref_client)
{
	unsigned long flags;

	if (ref_client >= IPA_WAKELOCK_REF_CLIENT_MAX)
		return;
	spin_lock_irqsave(&ipa_ctx->wakelock_ref_cnt.spinlock, flags);
	ipa_ctx->wakelock_ref_cnt.cnt++;
	if (ipa_ctx->wakelock_ref_cnt.cnt == 1)
	if (ipa_ctx->wakelock_ref_cnt.cnt & (1 << ref_client))
		IPAERR("client enum %d mask already set. ref cnt = %d\n",
		ref_client, ipa_ctx->wakelock_ref_cnt.cnt);
	ipa_ctx->wakelock_ref_cnt.cnt |= (1 << ref_client);
	if (ipa_ctx->wakelock_ref_cnt.cnt)
		__pm_stay_awake(&ipa_ctx->w_lock);
	IPADBG("active wakelock ref cnt = %d\n", ipa_ctx->wakelock_ref_cnt.cnt);
	IPADBG("active wakelock ref cnt = %d client enum %d\n",
		ipa_ctx->wakelock_ref_cnt.cnt, ref_client);
	spin_unlock_irqrestore(&ipa_ctx->wakelock_ref_cnt.spinlock, flags);
}

@@ -3226,13 +3232,16 @@ void ipa_inc_acquire_wakelock(void)
 * Return codes:
 * None
 */
void ipa_dec_release_wakelock(void)
void ipa_dec_release_wakelock(enum ipa_wakelock_ref_client ref_client)
{
	unsigned long flags;

	if (ref_client >= IPA_WAKELOCK_REF_CLIENT_MAX)
		return;
	spin_lock_irqsave(&ipa_ctx->wakelock_ref_cnt.spinlock, flags);
	ipa_ctx->wakelock_ref_cnt.cnt--;
	IPADBG("active wakelock ref cnt = %d\n", ipa_ctx->wakelock_ref_cnt.cnt);
	ipa_ctx->wakelock_ref_cnt.cnt &= ~(1 << ref_client);
	IPADBG("active wakelock ref cnt = %d client enum %d\n",
		ipa_ctx->wakelock_ref_cnt.cnt, ref_client);
	if (ipa_ctx->wakelock_ref_cnt.cnt == 0)
		__pm_relax(&ipa_ctx->w_lock);
	spin_unlock_irqrestore(&ipa_ctx->wakelock_ref_cnt.spinlock, flags);
+11 −4
Original line number Diff line number Diff line
@@ -242,7 +242,6 @@ static void ipa_tx_switch_to_intr_mode(struct ipa_sys_context *sys)
	}
	atomic_set(&sys->curr_polling_state, 0);
	ipa_handle_tx_core(sys, true, false);
	ipa_dec_release_wakelock();
	return;

fail:
@@ -726,7 +725,6 @@ static void ipa_sps_irq_tx_notify(struct sps_event_notify *notify)
				IPAERR("sps_set_config() failed %d\n", ret);
				break;
			}
			ipa_inc_acquire_wakelock();
			atomic_set(&sys->curr_polling_state, 1);
			queue_work(sys->wq, &sys->work);
		}
@@ -842,7 +840,7 @@ static void ipa_rx_switch_to_intr_mode(struct ipa_sys_context *sys)
	}
	atomic_set(&sys->curr_polling_state, 0);
	ipa_handle_rx_core(sys, true, false);
	ipa_dec_release_wakelock();
	ipa_dec_release_wakelock(sys->ep->wakelock_client);
	return;

fail:
@@ -960,7 +958,7 @@ static void ipa_sps_irq_rx_notify(struct sps_event_notify *notify)
				IPAERR("sps_set_config() failed %d\n", ret);
				break;
			}
			ipa_inc_acquire_wakelock();
			ipa_inc_acquire_wakelock(sys->ep->wakelock_client);
			atomic_set(&sys->curr_polling_state, 1);
			trace_intr_to_poll(sys->ep->client);
			queue_work(sys->wq, &sys->work);
@@ -2863,6 +2861,7 @@ static int ipa_assign_policy(struct ipa_sys_connect_params *in,
		}
	} else if (ipa_ctx->ipa_hw_type >= IPA_HW_v2_0) {
		sys->ep->status.status_en = true;
		sys->ep->wakelock_client = IPA_WAKELOCK_REF_CLIENT_MAX;
		if (IPA_CLIENT_IS_PROD(in->client)) {
			if (!sys->ep->skip_ep_cfg) {
				sys->policy = IPA_POLICY_NOINTR_MODE;
@@ -2910,11 +2909,15 @@ static int ipa_assign_policy(struct ipa_sys_connect_params *in,
					IPA_GENERIC_AGGR_BYTE_LIMIT;
					in->ipa_ep_cfg.aggr.aggr_pkt_limit =
					IPA_GENERIC_AGGR_PKT_LIMIT;
					sys->ep->wakelock_client =
					IPA_WAKELOCK_REF_CLIENT_LAN_RX;
				} else if (in->client ==
						IPA_CLIENT_APPS_WAN_CONS) {
					sys->pyld_hdlr = ipa_wan_rx_pyld_hdlr;
					sys->rx_pool_sz =
						ipa_ctx->wan_rx_ring_size;
					sys->ep->wakelock_client =
					IPA_WAKELOCK_REF_CLIENT_WAN_RX;
					if (ipa_ctx->
					ipa_client_apps_wan_cons_agg_gro) {
						IPAERR("get close-by %u\n",
@@ -2988,6 +2991,8 @@ static int ipa_assign_policy(struct ipa_sys_connect_params *in,
				sys->get_skb = ipa_get_skb_ipa_rx;
				sys->free_skb = ipa_free_skb_rx;
				in->ipa_ep_cfg.aggr.aggr_en = IPA_BYPASS_AGGR;
				sys->ep->wakelock_client =
					IPA_WAKELOCK_REF_CLIENT_WLAN_RX;
			} else if (IPA_CLIENT_IS_ODU_CONS(in->client)) {
				IPADBG("assigning policy to client:%d",
					in->client);
@@ -3012,6 +3017,8 @@ static int ipa_assign_policy(struct ipa_sys_connect_params *in,
				sys->get_skb = ipa_get_skb_ipa_rx;
				sys->free_skb = ipa_free_skb_rx;
				sys->repl_hdlr = ipa_replenish_rx_cache;
				sys->ep->wakelock_client =
					IPA_WAKELOCK_REF_CLIENT_ODU_RX;
			} else if (in->client ==
					IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS) {
				IPADBG("assigning policy to client:%d",
+14 −3
Original line number Diff line number Diff line
@@ -606,6 +606,16 @@ struct ipa_status_stats {
	int curr;
};

enum ipa_wakelock_ref_client {
	IPA_WAKELOCK_REF_CLIENT_TX  = 0,
	IPA_WAKELOCK_REF_CLIENT_LAN_RX = 1,
	IPA_WAKELOCK_REF_CLIENT_WAN_RX = 2,
	IPA_WAKELOCK_REF_CLIENT_WLAN_RX = 3,
	IPA_WAKELOCK_REF_CLIENT_ODU_RX = 4,
	IPA_WAKELOCK_REF_CLIENT_SPS = 5,
	IPA_WAKELOCK_REF_CLIENT_MAX
};

/**
 * struct ipa_ep_context - IPA end point context
 * @valid: flag indicating id EP context is valid
@@ -665,6 +675,7 @@ struct ipa_ep_context {
	u32 rx_replenish_threshold;
	bool disconnect_in_progress;
	u32 qmi_request_sent;
	enum ipa_wakelock_ref_client wakelock_client;

	/* sys MUST be the last element of this struct */
	struct ipa_sys_context *sys;
@@ -915,7 +926,7 @@ struct ipa_active_clients {

struct ipa_wakelock_ref_cnt {
	spinlock_t spinlock;
	int cnt;
	u32 cnt;
};

struct ipa_tag_completion {
@@ -2137,7 +2148,7 @@ void ipa_flow_control(enum ipa_client_type ipa_client, bool enable,
			uint32_t qmap_id);
int ipa2_restore_suspend_handler(void);
void ipa_sps_irq_control_all(bool enable);
void ipa_inc_acquire_wakelock(void);
void ipa_dec_release_wakelock(void);
void ipa_inc_acquire_wakelock(enum ipa_wakelock_ref_client ref_client);
void ipa_dec_release_wakelock(enum ipa_wakelock_ref_client ref_client);
const char *ipa_rm_resource_str(enum ipa_rm_resource_name resource_name);
#endif /* _IPA_I_H_ */