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

Commit a3ba0d9f authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ipa: ipa gsb driver"

parents 786e83fb 9b9ea7c3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
obj-$(CONFIG_IPA3) += ipa_usb.o odu_bridge.o ipa_mhi_client.o ipa_uc_offload.o ipa_wdi3.o
obj-$(CONFIG_IPA3) += ipa_usb.o odu_bridge.o ipa_mhi_client.o ipa_uc_offload.o ipa_wdi3.o ipa_gsb.o
obj-$(CONFIG_IPA) += odu_bridge.o ipa_mhi_client.o ipa_uc_offload.o ipa_wdi3.o
obj-$(CONFIG_ECM_IPA) += ecm_ipa.o
obj-$(CONFIG_RNDIS_IPA) += rndis_ipa.o
+1074 −0

File added.

Preview size limit exceeded, changes collapsed.

+0 −380
Original line number Diff line number Diff line
@@ -1259,385 +1259,5 @@ int odu_bridge_cleanup(void)
}
EXPORT_SYMBOL(odu_bridge_cleanup);

/* IPA Bridge implementation */
#ifdef CONFIG_IPA3

static void ipa_br_rm_notify(void *user_data, enum ipa_rm_event event,
	unsigned long data)
{
	if (event == IPA_RM_RESOURCE_GRANTED)
		complete(&odu_bridge_ctx->rm_comp);
}

static int ipa_br_request_prod(void)
{
	int res;

	ODU_BRIDGE_FUNC_ENTRY();

	reinit_completion(&odu_bridge_ctx->rm_comp);
	ODU_BRIDGE_DBG("requesting odu prod\n");
	res = ipa_rm_request_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD);
	if (res) {
		if (res != -EINPROGRESS) {
			ODU_BRIDGE_ERR("failed to request prod %d\n", res);
			return res;
		}
		wait_for_completion(&odu_bridge_ctx->rm_comp);
	}

	ODU_BRIDGE_FUNC_EXIT();
	return 0;

}

static int ipa_br_release_prod(void)
{
	int res;

	ODU_BRIDGE_FUNC_ENTRY();

	reinit_completion(&odu_bridge_ctx->rm_comp);
	ODU_BRIDGE_DBG("requesting odu prod\n");
	res = ipa_rm_release_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD);
	if (res) {
		ODU_BRIDGE_ERR("failed to release prod %d\n", res);
		return res;
	}

	ODU_BRIDGE_FUNC_EXIT();
	return 0;

}

static int ipa_br_cons_request(void)
{
	ODU_BRIDGE_FUNC_ENTRY();
	if (odu_bridge_ctx->is_suspended)
		odu_bridge_ctx->wakeup_request(odu_bridge_ctx->priv);
	ODU_BRIDGE_FUNC_EXIT();
	return 0;
}

static int ipa_br_cons_release(void)
{
	ODU_BRIDGE_FUNC_ENTRY();
	ODU_BRIDGE_FUNC_EXIT();
	return 0;
}

static void ipa_br_pm_cb(void *p, enum ipa_pm_cb_event event)
{
	ODU_BRIDGE_FUNC_ENTRY();
	if (event != IPA_PM_REQUEST_WAKEUP) {
		ODU_BRIDGE_ERR("Unexpected event %d\n", event);
		WARN_ON(1);
		return;
	}

	if (odu_bridge_ctx->is_suspended)
		odu_bridge_ctx->wakeup_request(odu_bridge_ctx->priv);
	ODU_BRIDGE_FUNC_EXIT();
}

static int ipa_br_register_pm(void)
{
	struct ipa_pm_register_params reg_params;
	int ret;

	memset(&reg_params, 0, sizeof(reg_params));
	reg_params.name = "ODU Bridge";
	reg_params.callback = ipa_br_pm_cb;
	reg_params.group = IPA_PM_GROUP_DEFAULT;

	ret = ipa_pm_register(&reg_params,
		&odu_bridge_ctx->pm_hdl);
	if (ret) {
		ODU_BRIDGE_ERR("fail to register with PM %d\n", ret);
		goto fail_pm_reg;
	}

	ret = ipa_pm_associate_ipa_cons_to_client(odu_bridge_ctx->pm_hdl,
		IPA_CLIENT_ODU_EMB_CONS);
	if (ret) {
		ODU_BRIDGE_ERR("fail to associate cons with PM %d\n", ret);
		goto fail_pm_cons;
	}

	return 0;

fail_pm_cons:
	ipa_pm_deregister(odu_bridge_ctx->pm_hdl);
	odu_bridge_ctx->pm_hdl = ~0;
fail_pm_reg:
	return ret;
}

static int ipa_br_create_rm_resources(void)
{
	int ret;
	struct ipa_rm_create_params create_params;

	/* create IPA RM resources for power management */
	init_completion(&odu_bridge_ctx->rm_comp);
	memset(&create_params, 0, sizeof(create_params));
	create_params.name = IPA_RM_RESOURCE_ODU_ADAPT_PROD;
	create_params.reg_params.user_data = odu_bridge_ctx;
	create_params.reg_params.notify_cb = ipa_br_rm_notify;
	create_params.floor_voltage = IPA_VOLTAGE_SVS;
	ret = ipa_rm_create_resource(&create_params);
	if (ret) {
		ODU_BRIDGE_ERR("failed to create RM prod %d\n", ret);
		goto fail_rm_prod;
	}

	ret = ipa_rm_add_dependency_sync(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
		IPA_RM_RESOURCE_APPS_CONS);
	if (ret) {
		ODU_BRIDGE_ERR("failed to add ODU->APPS dependency %d\n", ret);
		goto fail_add_dep;
	}

	memset(&create_params, 0, sizeof(create_params));
	create_params.name = IPA_RM_RESOURCE_ODU_ADAPT_CONS;
	create_params.request_resource = ipa_br_cons_request;
	create_params.release_resource = ipa_br_cons_release;
	create_params.floor_voltage = IPA_VOLTAGE_SVS;
	ret = ipa_rm_create_resource(&create_params);
	if (ret) {
		ODU_BRIDGE_ERR("failed to create RM cons %d\n", ret);
		goto fail_rm_cons;
	}

	return 0;

fail_rm_cons:
	ipa_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
		IPA_RM_RESOURCE_APPS_CONS);
fail_add_dep:
	ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD);
fail_rm_prod:
	return ret;
}

/* IPA Bridge API is the new API which will replaces old odu_bridge API */
int ipa_bridge_init(struct ipa_bridge_init_params *params, u32 *hdl)
{
	int ret;

	if (!params || !params->wakeup_request || !hdl) {
		ODU_BRIDGE_ERR("NULL arg\n");
		return -EINVAL;
	}


	ret = odu_bridge_init(&params->info);
	if (ret)
		return ret;

	odu_bridge_ctx->wakeup_request = params->wakeup_request;

	if (ipa_pm_is_used())
		ret = ipa_br_register_pm();
	else
		ret = ipa_br_create_rm_resources();
	if (ret) {
		ODU_BRIDGE_ERR("fail to register woth RM/PM %d\n", ret);
		goto fail_pm;
	}

	/* handle is ignored for now */
	*hdl = 0;

	return 0;

fail_pm:
	odu_bridge_cleanup();
	return ret;
}
EXPORT_SYMBOL(ipa_bridge_init);

int ipa_bridge_connect(u32 hdl)
{
	int ret;

	if (!odu_bridge_ctx) {
		ODU_BRIDGE_ERR("Not initialized\n");
		return -EFAULT;
	}

	if (odu_bridge_ctx->is_connected) {
		ODU_BRIDGE_ERR("already connected\n");
		return -EFAULT;
	}

	if (ipa_pm_is_used())
		ret = ipa_pm_activate_sync(odu_bridge_ctx->pm_hdl);
	else
		ret = ipa_br_request_prod();
	if (ret)
		return ret;

	return odu_bridge_connect();
}
EXPORT_SYMBOL(ipa_bridge_connect);

int ipa_bridge_set_perf_profile(u32 hdl, u32 bandwidth)
{
	struct ipa_rm_perf_profile profile = {0};
	int ret;

	if (ipa_pm_is_used())
		return ipa_pm_set_perf_profile(odu_bridge_ctx->pm_hdl,
			bandwidth);

	profile.max_supported_bandwidth_mbps = bandwidth;
	ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_ODU_ADAPT_PROD, &profile);
	if (ret) {
		ODU_BRIDGE_ERR("failed to set perf profile to prod %d\n", ret);
		return ret;
	}

	ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_ODU_ADAPT_CONS, &profile);
	if (ret) {
		ODU_BRIDGE_ERR("failed to set perf profile to cons %d\n", ret);
		return ret;
	}

	return 0;
}
EXPORT_SYMBOL(ipa_bridge_set_perf_profile);

int ipa_bridge_disconnect(u32 hdl)
{
	int ret;

	ret = odu_bridge_disconnect();
	if (ret)
		return ret;

	if (ipa_pm_is_used())
		ret = ipa_pm_deactivate_sync(odu_bridge_ctx->pm_hdl);
	else
		ret = ipa_br_release_prod();
	if (ret)
		return ret;

	return 0;
}
EXPORT_SYMBOL(ipa_bridge_disconnect);

int ipa_bridge_suspend(u32 hdl)
{
	int ret;

	if (!odu_bridge_ctx) {
		ODU_BRIDGE_ERR("Not initialized\n");
		return -EFAULT;
	}

	if (!odu_bridge_ctx->is_connected) {
		ODU_BRIDGE_ERR("bridge is  disconnected\n");
		return -EFAULT;
	}

	if (odu_bridge_ctx->is_suspended) {
		ODU_BRIDGE_ERR("bridge is already suspended\n");
		return -EFAULT;
	}

	/* stop cons channel to prevent downlink data during suspend */
	ret = ipa_stop_gsi_channel(odu_bridge_ctx->odu_emb_cons_hdl);
	if (ret) {
		ODU_BRIDGE_ERR("failed to stop CONS channel %d\n", ret);
		return ret;
	}

	if (ipa_pm_is_used())
		ret = ipa_pm_deactivate_sync(odu_bridge_ctx->pm_hdl);
	else
		ret = ipa_br_release_prod();
	if (ret) {
		ODU_BRIDGE_ERR("failed to release prod %d\n", ret);
		ipa_start_gsi_channel(odu_bridge_ctx->odu_emb_cons_hdl);
		return ret;
	}
	odu_bridge_ctx->is_suspended = true;

	return 0;
}
EXPORT_SYMBOL(ipa_bridge_suspend);

int ipa_bridge_resume(u32 hdl)
{
	int ret;

	if (!odu_bridge_ctx) {
		ODU_BRIDGE_ERR("Not initialized\n");
		return -EFAULT;
	}

	if (!odu_bridge_ctx->is_connected) {
		ODU_BRIDGE_ERR("bridge is  disconnected\n");
		return -EFAULT;
	}

	if (!odu_bridge_ctx->is_suspended) {
		ODU_BRIDGE_ERR("bridge is not suspended\n");
		return -EFAULT;
	}

	if (ipa_pm_is_used())
		ret = ipa_pm_activate_sync(odu_bridge_ctx->pm_hdl);
	else
		ret = ipa_br_request_prod();
	if (ret)
		return ret;

	ret = ipa_start_gsi_channel(odu_bridge_ctx->odu_emb_cons_hdl);
	if (ret) {
		ODU_BRIDGE_ERR("failed to start CONS channel %d\n", ret);
		return ret;
	}
	odu_bridge_ctx->is_suspended = false;

	return 0;
}
EXPORT_SYMBOL(ipa_bridge_resume);

int ipa_bridge_tx_dp(u32 hdl, struct sk_buff *skb,
	struct ipa_tx_meta *metadata)
{
	return odu_bridge_tx_dp(skb, metadata);
}
EXPORT_SYMBOL(ipa_bridge_tx_dp);

static void ipa_br_delete_rm_resources(void)
{
	ipa_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
		IPA_RM_RESOURCE_APPS_CONS);
	ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD);
	ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_CONS);
}

static void ipa_br_deregister_pm(void)
{
	ipa_pm_deactivate_sync(odu_bridge_ctx->pm_hdl);
	ipa_pm_deregister(odu_bridge_ctx->pm_hdl);
	odu_bridge_ctx->pm_hdl = ~0;
}

int ipa_bridge_cleanup(u32 hdl)
{
	if (ipa_pm_is_used())
		ipa_br_deregister_pm();
	else
		ipa_br_delete_rm_resources();
	return odu_bridge_cleanup();
}
EXPORT_SYMBOL(ipa_bridge_cleanup);

#endif /* CONFIG_IPA3 */

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("ODU bridge driver");
+14 −3
Original line number Diff line number Diff line
@@ -3039,7 +3039,6 @@ static int ipa3_assign_policy(struct ipa_sys_connect_params *in,
			INIT_DELAYED_WORK(&sys->replenish_rx_work,
				ipa3_replenish_rx_work_func);
			atomic_set(&sys->curr_polling_state, 0);
			sys->rx_buff_sz = IPA_ODU_RX_BUFF_SZ;
			sys->rx_pool_sz = in->desc_fifo_sz /
				IPA_FIFO_ELEMENT_SIZE - 1;
			if (sys->rx_pool_sz > IPA_ODU_RX_POOL_SZ)
@@ -3047,8 +3046,20 @@ static int ipa3_assign_policy(struct ipa_sys_connect_params *in,
			sys->pyld_hdlr = ipa3_odu_rx_pyld_hdlr;
			sys->get_skb = ipa3_get_skb_ipa_rx;
			sys->free_skb = ipa3_free_skb_rx;
			sys->free_rx_wrapper = ipa3_free_rx_wrapper;
			/* recycle skb for GSB use case */
			if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) {
				sys->free_rx_wrapper =
					ipa3_recycle_rx_wrapper;
				sys->repl_hdlr =
					ipa3_replenish_rx_cache_recycle;
				sys->rx_buff_sz = IPA_GENERIC_RX_BUFF_SZ(
					IPA_GENERIC_RX_BUFF_BASE_SZ);
			} else {
				sys->free_rx_wrapper =
					ipa3_free_rx_wrapper;
				sys->repl_hdlr = ipa3_replenish_rx_cache;
				sys->rx_buff_sz = IPA_ODU_RX_BUFF_SZ;
			}
		} else if (in->client ==
				IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS) {
			IPADBG("assigning policy to client:%d",