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

Commit fdb7095f 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: Fix to system suspend due to missing wakelock"

parents 4e975d42 94627c9a
Loading
Loading
Loading
Loading
+41 −1
Original line number Original line Diff line number Diff line
@@ -2802,6 +2802,45 @@ void ipa_dec_client_disable_clks(void)
	ipa_active_clients_unlock();
	ipa_active_clients_unlock();
}
}


/**
* ipa_inc_acquire_wakelock() - Increase active clients counter, and
* acquire wakelock if necessary
*
* Return codes:
* None
*/
void ipa_inc_acquire_wakelock(void)
{
	unsigned long flags;

	spin_lock_irqsave(&ipa_ctx->wakelock_ref_cnt.spinlock, flags);
	ipa_ctx->wakelock_ref_cnt.cnt++;
	if (ipa_ctx->wakelock_ref_cnt.cnt == 1)
		__pm_stay_awake(&ipa_ctx->w_lock);
	IPADBG("active wakelock ref cnt = %d\n", ipa_ctx->wakelock_ref_cnt.cnt);
	spin_unlock_irqrestore(&ipa_ctx->wakelock_ref_cnt.spinlock, flags);
}

/**
 * ipa_dec_release_wakelock() - Decrease active clients counter
 *
 * In case if the ref count is 0, release the wakelock.
 *
 * Return codes:
 * None
 */
void ipa_dec_release_wakelock(void)
{
	unsigned long flags;

	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);
	if (ipa_ctx->wakelock_ref_cnt.cnt == 0)
		__pm_relax(&ipa_ctx->w_lock);
	spin_unlock_irqrestore(&ipa_ctx->wakelock_ref_cnt.spinlock, flags);
}

static int ipa_setup_bam_cfg(const struct ipa_plat_drv_res *res)
static int ipa_setup_bam_cfg(const struct ipa_plat_drv_res *res)
{
{
	void *ipa_bam_mmio;
	void *ipa_bam_mmio;
@@ -3552,7 +3591,8 @@ static int ipa_init(const struct ipa_plat_drv_res *resource_p,




	/* Create a wakeup source. */
	/* Create a wakeup source. */
	ipa_ctx->pdev->power.wakeup = wakeup_source_register("IPA_WS");
	wakeup_source_init(&ipa_ctx->w_lock, "IPA_WS");
	spin_lock_init(&ipa_ctx->wakelock_ref_cnt.spinlock);


	/* Initialize IPA RM (resource manager) */
	/* Initialize IPA RM (resource manager) */
	result = ipa_rm_initialize();
	result = ipa_rm_initialize();
+4 −4
Original line number Original line Diff line number Diff line
@@ -233,6 +233,7 @@ static void ipa_tx_switch_to_intr_mode(struct ipa_sys_context *sys)
	}
	}
	atomic_set(&sys->curr_polling_state, 0);
	atomic_set(&sys->curr_polling_state, 0);
	ipa_handle_tx_core(sys, true, false);
	ipa_handle_tx_core(sys, true, false);
	ipa_dec_release_wakelock();
	return;
	return;


fail:
fail:
@@ -246,7 +247,6 @@ static void ipa_handle_tx(struct ipa_sys_context *sys)
	int cnt;
	int cnt;


	ipa_inc_client_enable_clks();
	ipa_inc_client_enable_clks();
	pm_stay_awake(ipa_ctx->pdev);
	do {
	do {
		cnt = ipa_handle_tx_core(sys, true, true);
		cnt = ipa_handle_tx_core(sys, true, true);
		if (cnt == 0) {
		if (cnt == 0) {
@@ -259,7 +259,6 @@ static void ipa_handle_tx(struct ipa_sys_context *sys)
	} while (inactive_cycles <= POLLING_INACTIVITY_TX);
	} while (inactive_cycles <= POLLING_INACTIVITY_TX);


	ipa_tx_switch_to_intr_mode(sys);
	ipa_tx_switch_to_intr_mode(sys);
	pm_relax(ipa_ctx->pdev);
	ipa_dec_client_disable_clks();
	ipa_dec_client_disable_clks();
}
}


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


fail:
fail:
@@ -902,6 +903,7 @@ static void ipa_sps_irq_rx_notify(struct sps_event_notify *notify)
				IPAERR("sps_set_config() failed %d\n", ret);
				IPAERR("sps_set_config() failed %d\n", ret);
				break;
				break;
			}
			}
			ipa_inc_acquire_wakelock();
			atomic_set(&sys->curr_polling_state, 1);
			atomic_set(&sys->curr_polling_state, 1);
			queue_work(sys->wq, &sys->work);
			queue_work(sys->wq, &sys->work);
		}
		}
@@ -935,7 +937,6 @@ static void ipa_handle_rx(struct ipa_sys_context *sys)
	int cnt;
	int cnt;


	ipa_inc_client_enable_clks();
	ipa_inc_client_enable_clks();
	pm_stay_awake(ipa_ctx->pdev);
	do {
	do {
		cnt = ipa_handle_rx_core(sys, true, true);
		cnt = ipa_handle_rx_core(sys, true, true);
		if (cnt == 0) {
		if (cnt == 0) {
@@ -956,7 +957,6 @@ static void ipa_handle_rx(struct ipa_sys_context *sys)
	} while (inactive_cycles <= POLLING_INACTIVITY_RX);
	} while (inactive_cycles <= POLLING_INACTIVITY_RX);


	ipa_rx_switch_to_intr_mode(sys);
	ipa_rx_switch_to_intr_mode(sys);
	pm_relax(ipa_ctx->pdev);
	ipa_dec_client_disable_clks();
	ipa_dec_client_disable_clks();
}
}


+12 −0
Original line number Original line Diff line number Diff line
@@ -788,6 +788,11 @@ struct ipa_active_clients {
	int cnt;
	int cnt;
};
};


struct ipa_wakelock_ref_cnt {
	spinlock_t spinlock;
	int cnt;
};

struct ipa_tag_completion {
struct ipa_tag_completion {
	struct completion comp;
	struct completion comp;
	atomic_t cnt;
	atomic_t cnt;
@@ -1160,6 +1165,8 @@ struct ipacm_client_info {
 * @ipa_num_pipes: The number of pipes used by IPA HW
 * @ipa_num_pipes: The number of pipes used by IPA HW
 * @skip_uc_pipe_reset: Indicates whether pipe reset via uC needs to be avoided
 * @skip_uc_pipe_reset: Indicates whether pipe reset via uC needs to be avoided
 * @ipa_client_apps_wan_cons_agg_gro: RMNET_IOCTL_INGRESS_FORMAT_AGG_DATA
 * @ipa_client_apps_wan_cons_agg_gro: RMNET_IOCTL_INGRESS_FORMAT_AGG_DATA
 * @w_lock: Indicates the wakeup source.
 * @wakelock_ref_cnt: Indicates the number of times wakelock is acquired


 * IPA context - holds all relevant info about IPA driver and its state
 * IPA context - holds all relevant info about IPA driver and its state
 */
 */
@@ -1261,6 +1268,9 @@ struct ipa_context {
	u32 peer_bam_map_cnt;
	u32 peer_bam_map_cnt;
	u32 wdi_map_cnt;
	u32 wdi_map_cnt;
	bool use_dma_zone;
	bool use_dma_zone;
	struct wakeup_source w_lock;
	struct ipa_wakelock_ref_cnt wakelock_ref_cnt;

	/* RMNET_IOCTL_INGRESS_FORMAT_AGG_DATA */
	/* RMNET_IOCTL_INGRESS_FORMAT_AGG_DATA */
	bool ipa_client_apps_wan_cons_agg_gro;
	bool ipa_client_apps_wan_cons_agg_gro;
	/* M-release support to know client pipes */
	/* M-release support to know client pipes */
@@ -1988,4 +1998,6 @@ void ipa_flow_control(enum ipa_client_type ipa_client, bool enable,
			uint32_t qmap_id);
			uint32_t qmap_id);
int ipa2_restore_suspend_handler(void);
int ipa2_restore_suspend_handler(void);
void ipa_sps_irq_control_all(bool enable);
void ipa_sps_irq_control_all(bool enable);
void ipa_inc_acquire_wakelock(void);
void ipa_dec_release_wakelock(void);
#endif /* _IPA_I_H_ */
#endif /* _IPA_I_H_ */
+45 −0
Original line number Original line Diff line number Diff line
@@ -2881,6 +2881,47 @@ void ipa3_dec_client_disable_clks(void)
	ipa3_active_clients_unlock();
	ipa3_active_clients_unlock();
}
}


/**
* ipa3_inc_acquire_wakelock() - Increase active clients counter, and
* acquire wakelock if necessary
*
* Return codes:
* None
*/
void ipa3_inc_acquire_wakelock(void)
{
	unsigned long flags;

	spin_lock_irqsave(&ipa3_ctx->wakelock_ref_cnt.spinlock, flags);
	ipa3_ctx->wakelock_ref_cnt.cnt++;
	if (ipa3_ctx->wakelock_ref_cnt.cnt == 1)
		__pm_stay_awake(&ipa3_ctx->w_lock);
	IPADBG("active wakelock ref cnt = %d\n",
		ipa3_ctx->wakelock_ref_cnt.cnt);
	spin_unlock_irqrestore(&ipa3_ctx->wakelock_ref_cnt.spinlock, flags);
}

/**
 * ipa3_dec_release_wakelock() - Decrease active clients counter
 *
 * In case if the ref count is 0, release the wakelock.
 *
 * Return codes:
 * None
 */
void ipa3_dec_release_wakelock(void)
{
	unsigned long flags;

	spin_lock_irqsave(&ipa3_ctx->wakelock_ref_cnt.spinlock, flags);
	ipa3_ctx->wakelock_ref_cnt.cnt--;
	IPADBG("active wakelock ref cnt = %d\n",
		ipa3_ctx->wakelock_ref_cnt.cnt);
	if (ipa3_ctx->wakelock_ref_cnt.cnt == 0)
		__pm_relax(&ipa3_ctx->w_lock);
	spin_unlock_irqrestore(&ipa3_ctx->wakelock_ref_cnt.spinlock, flags);
}

int ipa3_set_required_perf_profile(enum ipa_voltage_level floor_voltage,
int ipa3_set_required_perf_profile(enum ipa_voltage_level floor_voltage,
				  u32 bandwidth_mbps)
				  u32 bandwidth_mbps)
{
{
@@ -3625,6 +3666,10 @@ static int ipa3_init(const struct ipa3_plat_drv_res *resource_p,
		goto fail_nat_dev_add;
		goto fail_nat_dev_add;
	}
	}


	/* Create a wakeup source. */
	wakeup_source_init(&ipa3_ctx->w_lock, "IPA_WS");
	spin_lock_init(&ipa3_ctx->wakelock_ref_cnt.spinlock);

	/* Initialize IPA RM (resource manager) */
	/* Initialize IPA RM (resource manager) */
	result = ipa3_rm_initialize();
	result = ipa3_rm_initialize();
	if (result) {
	if (result) {
+8 −2
Original line number Original line Diff line number Diff line
@@ -212,6 +212,7 @@ static void ipa3_tx_switch_to_intr_mode(struct ipa3_sys_context *sys)


	if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI) {
	if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI) {
		atomic_set(&sys->curr_polling_state, 0);
		atomic_set(&sys->curr_polling_state, 0);
		ipa3_dec_release_wakelock();
		ret = gsi_config_channel_mode(sys->ep->gsi_chan_hdl,
		ret = gsi_config_channel_mode(sys->ep->gsi_chan_hdl,
			GSI_CHAN_MODE_CALLBACK);
			GSI_CHAN_MODE_CALLBACK);
		if (ret != GSI_STATUS_SUCCESS) {
		if (ret != GSI_STATUS_SUCCESS) {
@@ -239,8 +240,8 @@ static void ipa3_tx_switch_to_intr_mode(struct ipa3_sys_context *sys)
		}
		}
		atomic_set(&sys->curr_polling_state, 0);
		atomic_set(&sys->curr_polling_state, 0);
		ipa3_handle_tx_core(sys, true, false);
		ipa3_handle_tx_core(sys, true, false);
		ipa3_dec_release_wakelock();
	}
	}

	return;
	return;


fail:
fail:
@@ -775,6 +776,7 @@ static void ipa3_sps_irq_tx_notify(struct sps_event_notify *notify)
				IPAERR("sps_set_config() failed %d\n", ret);
				IPAERR("sps_set_config() failed %d\n", ret);
				break;
				break;
			}
			}
			ipa3_inc_acquire_wakelock();
			atomic_set(&sys->curr_polling_state, 1);
			atomic_set(&sys->curr_polling_state, 1);
			queue_work(sys->wq, &sys->work);
			queue_work(sys->wq, &sys->work);
		}
		}
@@ -852,6 +854,7 @@ static void ipa3_rx_switch_to_intr_mode(struct ipa3_sys_context *sys)


	if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI) {
	if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI) {
		atomic_set(&sys->curr_polling_state, 0);
		atomic_set(&sys->curr_polling_state, 0);
		ipa3_dec_release_wakelock();
		ret = gsi_config_channel_mode(sys->ep->gsi_chan_hdl,
		ret = gsi_config_channel_mode(sys->ep->gsi_chan_hdl,
			GSI_CHAN_MODE_CALLBACK);
			GSI_CHAN_MODE_CALLBACK);
		if (ret != GSI_STATUS_SUCCESS) {
		if (ret != GSI_STATUS_SUCCESS) {
@@ -879,8 +882,8 @@ static void ipa3_rx_switch_to_intr_mode(struct ipa3_sys_context *sys)
		}
		}
		atomic_set(&sys->curr_polling_state, 0);
		atomic_set(&sys->curr_polling_state, 0);
		ipa3_handle_rx_core(sys, true, false);
		ipa3_handle_rx_core(sys, true, false);
		ipa3_dec_release_wakelock();
	}
	}

	return;
	return;


fail:
fail:
@@ -927,6 +930,7 @@ static void ipa3_sps_irq_rx_notify(struct sps_event_notify *notify)
				IPAERR("sps_set_config() failed %d\n", ret);
				IPAERR("sps_set_config() failed %d\n", ret);
				break;
				break;
			}
			}
			ipa3_inc_acquire_wakelock();
			atomic_set(&sys->curr_polling_state, 1);
			atomic_set(&sys->curr_polling_state, 1);
			queue_work(sys->wq, &sys->work);
			queue_work(sys->wq, &sys->work);
		}
		}
@@ -3296,6 +3300,7 @@ static void ipa_gsi_irq_rx_notify_cb(struct gsi_chan_xfer_notify *notify)
			/* put the gsi channel into polling mode */
			/* put the gsi channel into polling mode */
			gsi_config_channel_mode(sys->ep->gsi_chan_hdl,
			gsi_config_channel_mode(sys->ep->gsi_chan_hdl,
				GSI_CHAN_MODE_POLL);
				GSI_CHAN_MODE_POLL);
			ipa3_inc_acquire_wakelock();
			atomic_set(&sys->curr_polling_state, 1);
			atomic_set(&sys->curr_polling_state, 1);
			queue_work(sys->wq, &sys->work);
			queue_work(sys->wq, &sys->work);
		}
		}
@@ -3341,6 +3346,7 @@ static void ipa_dma_gsi_irq_rx_notify_cb(struct gsi_chan_xfer_notify *notify)
			/* put the gsi channel into polling mode */
			/* put the gsi channel into polling mode */
			gsi_config_channel_mode(sys->ep->gsi_chan_hdl,
			gsi_config_channel_mode(sys->ep->gsi_chan_hdl,
				GSI_CHAN_MODE_POLL);
				GSI_CHAN_MODE_POLL);
			ipa3_inc_acquire_wakelock();
			atomic_set(&sys->curr_polling_state, 1);
			atomic_set(&sys->curr_polling_state, 1);
			queue_work(sys->wq, &sys->work);
			queue_work(sys->wq, &sys->work);
		}
		}
Loading