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

Commit 6979c15b 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: add support for WDI 3.0"

parents cefbc175 083341f3
Loading
Loading
Loading
Loading
+51 −0
Original line number Diff line number Diff line
@@ -2823,6 +2823,57 @@ void ipa_ntn_uc_dereg_rdyCB(void)
}
EXPORT_SYMBOL(ipa_ntn_uc_dereg_rdyCB);

/**
 * ipa_conn_wdi3_pipes() - connect wdi3 pipes
 */
int ipa_conn_wdi3_pipes(struct ipa_wdi3_conn_in_params *in,
	struct ipa_wdi3_conn_out_params *out)
{
	int ret;

	IPA_API_DISPATCH_RETURN(ipa_conn_wdi3_pipes, in, out);

	return ret;
}

/**
 * ipa_disconn_wdi3_pipes() - disconnect wdi3 pipes
 */
int ipa_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
{
	int ret;

	IPA_API_DISPATCH_RETURN(ipa_disconn_wdi3_pipes, ipa_ep_idx_tx,
		ipa_ep_idx_rx);

	return ret;
}

/**
 * ipa_enable_wdi3_pipes() - enable wdi3 pipes
 */
int ipa_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
{
	int ret;

	IPA_API_DISPATCH_RETURN(ipa_enable_wdi3_pipes, ipa_ep_idx_tx,
		ipa_ep_idx_rx);

	return ret;
}

/**
 * ipa_disable_wdi3_pipes() - disable wdi3 pipes
 */
int ipa_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
{
	int ret;

	IPA_API_DISPATCH_RETURN(ipa_disable_wdi3_pipes, ipa_ep_idx_tx,
		ipa_ep_idx_rx);

	return ret;
}

static const struct dev_pm_ops ipa_pm_ops = {
	.suspend_noirq = ipa_ap_suspend,
+13 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@

#include <linux/ipa_mhi.h>
#include <linux/ipa_uc_offload.h>
#include <linux/ipa_wdi3.h>
#include "ipa_common_i.h"

#ifndef _IPA_API_H_
@@ -378,6 +379,18 @@ struct ipa_api_controller {
		void *user_data);

	void (*ipa_ntn_uc_dereg_rdyCB)(void);

	int (*ipa_conn_wdi3_pipes)(struct ipa_wdi3_conn_in_params *in,
		struct ipa_wdi3_conn_out_params *out);

	int (*ipa_disconn_wdi3_pipes)(int ipa_ep_idx_tx,
		int ipa_ep_idx_rx);

	int (*ipa_enable_wdi3_pipes)(int ipa_ep_idx_tx,
		int ipa_ep_idx_rx);

	int (*ipa_disable_wdi3_pipes)(int ipa_ep_idx_tx,
		int ipa_ep_idx_rx);
};

#ifdef CONFIG_IPA
+2 −2
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
obj-$(CONFIG_IPA) += odu_bridge.o ipa_mhi_client.o ipa_uc_offload.o
obj-$(CONFIG_IPA3) += ipa_usb.o odu_bridge.o ipa_mhi_client.o ipa_uc_offload.o ipa_wdi3.o
obj-$(CONFIG_IPA) += odu_bridge.o ipa_mhi_client.o ipa_uc_offload.o ipa_wdi3.o
+526 −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.
 */

#include <linux/ipa_wdi3.h>
#include <linux/msm_ipa.h>
#include <linux/string.h>
#include "../ipa_common_i.h"

#define OFFLOAD_DRV_NAME "ipa_wdi3"
#define IPA_WDI3_DBG(fmt, args...) \
	do { \
		pr_debug(OFFLOAD_DRV_NAME " %s:%d " fmt, \
			__func__, __LINE__, ## args); \
		IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
			OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
		IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
			OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
	} while (0)

#define IPA_WDI3_LOW(fmt, args...) \
	do { \
		pr_debug(OFFLOAD_DRV_NAME " %s:%d " fmt, \
			__func__, __LINE__, ## args); \
		IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
			OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
	} while (0)

#define IPA_WDI3_ERR(fmt, args...) \
	do { \
		pr_err(OFFLOAD_DRV_NAME " %s:%d " fmt, \
			__func__, __LINE__, ## args); \
		IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
			OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
		IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
			OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
	} while (0)

struct ipa_wdi3_intf_info {
	char netdev_name[IPA_RESOURCE_NAME_MAX];
	u8 hdr_len;
	u32 partial_hdr_hdl[IPA_IP_MAX];
	struct list_head link;
};

struct ipa_wdi3_context {
	struct list_head head_intf_list;
	ipa_notify_cb notify;
	void *priv;
	struct completion wdi3_completion;
	struct mutex lock;
};

static struct ipa_wdi3_context *ipa_wdi3_ctx;

static int ipa_wdi3_commit_partial_hdr(
	struct ipa_ioc_add_hdr *hdr,
	const char *netdev_name,
	struct ipa_wdi3_hdr_info *hdr_info)
{
	int i;

	if (!hdr || !hdr_info || !netdev_name) {
		IPA_WDI3_ERR("Invalid input\n");
		return -EINVAL;
	}

	hdr->commit = 1;
	hdr->num_hdrs = 2;

	snprintf(hdr->hdr[0].name, sizeof(hdr->hdr[0].name),
			 "%s_ipv4", netdev_name);
	snprintf(hdr->hdr[1].name, sizeof(hdr->hdr[1].name),
			 "%s_ipv6", netdev_name);
	for (i = IPA_IP_v4; i < IPA_IP_MAX; i++) {
		hdr->hdr[i].hdr_len = hdr_info[i].hdr_len;
		memcpy(hdr->hdr[i].hdr, hdr_info[i].hdr, hdr->hdr[i].hdr_len);
		hdr->hdr[i].type = hdr_info[i].hdr_type;
		hdr->hdr[i].is_partial = 1;
		hdr->hdr[i].is_eth2_ofst_valid = 1;
		hdr->hdr[i].eth2_ofst = hdr_info[i].dst_mac_addr_offset;
	}

	if (ipa_add_hdr(hdr)) {
		IPA_WDI3_ERR("fail to add partial headers\n");
		return -EFAULT;
	}

	return 0;
}

int ipa_wdi3_reg_intf(struct ipa_wdi3_reg_intf_in_params *in)
{
	struct ipa_ioc_add_hdr *hdr;
	struct ipa_wdi3_intf_info *new_intf;
	struct ipa_wdi3_intf_info *entry;
	struct ipa_tx_intf tx;
	struct ipa_rx_intf rx;
	struct ipa_ioc_tx_intf_prop tx_prop[2];
	struct ipa_ioc_rx_intf_prop rx_prop[2];
	u32 len;
	int ret = 0;

	if (in == NULL) {
		IPA_WDI3_ERR("invalid params in=%pK\n", in);
		return -EINVAL;
	}

	if (!ipa_wdi3_ctx) {
		ipa_wdi3_ctx = kzalloc(sizeof(*ipa_wdi3_ctx), GFP_KERNEL);
		if (ipa_wdi3_ctx == NULL) {
			IPA_WDI3_ERR("fail to alloc wdi3 ctx\n");
			return -EFAULT;
		}
		mutex_init(&ipa_wdi3_ctx->lock);
		INIT_LIST_HEAD(&ipa_wdi3_ctx->head_intf_list);
	}

	IPA_WDI3_DBG("register interface for netdev %s\n",
		in->netdev_name);

	mutex_lock(&ipa_wdi3_ctx->lock);
	list_for_each_entry(entry, &ipa_wdi3_ctx->head_intf_list, link)
		if (strcmp(entry->netdev_name, in->netdev_name) == 0) {
			IPA_WDI3_DBG("intf was added before.\n");
			mutex_unlock(&ipa_wdi3_ctx->lock);
			return 0;
		}

	IPA_WDI3_DBG("intf was not added before, proceed.\n");
	new_intf = kzalloc(sizeof(*new_intf), GFP_KERNEL);
	if (new_intf == NULL) {
		IPA_WDI3_ERR("fail to alloc new intf\n");
		mutex_unlock(&ipa_wdi3_ctx->lock);
		return -EFAULT;
	}

	INIT_LIST_HEAD(&new_intf->link);
	strlcpy(new_intf->netdev_name, in->netdev_name,
		sizeof(new_intf->netdev_name));
	new_intf->hdr_len = in->hdr_info[0].hdr_len;

	/* add partial header */
	len = sizeof(struct ipa_ioc_add_hdr) + 2 * sizeof(struct ipa_hdr_add);
	hdr = kzalloc(len, GFP_KERNEL);
	if (hdr == NULL) {
		IPA_WDI3_ERR("fail to alloc %d bytes\n", len);
		ret = -EFAULT;
		goto fail_alloc_hdr;
	}

	if (ipa_wdi3_commit_partial_hdr(hdr, in->netdev_name, in->hdr_info)) {
		IPA_WDI3_ERR("fail to commit partial headers\n");
		ret = -EFAULT;
		goto fail_commit_hdr;
	}

	new_intf->partial_hdr_hdl[IPA_IP_v4] = hdr->hdr[IPA_IP_v4].hdr_hdl;
	new_intf->partial_hdr_hdl[IPA_IP_v6] = hdr->hdr[IPA_IP_v6].hdr_hdl;
	IPA_WDI3_DBG("IPv4 hdr hdl: %d IPv6 hdr hdl: %d\n",
		hdr->hdr[IPA_IP_v4].hdr_hdl, hdr->hdr[IPA_IP_v6].hdr_hdl);

	/* populate tx prop */
	tx.num_props = 2;
	tx.prop = tx_prop;

	memset(tx_prop, 0, sizeof(tx_prop));
	tx_prop[0].ip = IPA_IP_v4;
	tx_prop[0].dst_pipe = IPA_CLIENT_WLAN1_CONS;
	tx_prop[0].hdr_l2_type = in->hdr_info[0].hdr_type;
	strlcpy(tx_prop[0].hdr_name, hdr->hdr[IPA_IP_v4].name,
		sizeof(tx_prop[0].hdr_name));

	tx_prop[1].ip = IPA_IP_v6;
	tx_prop[1].dst_pipe = IPA_CLIENT_WLAN1_CONS;
	tx_prop[1].hdr_l2_type = in->hdr_info[1].hdr_type;
	strlcpy(tx_prop[1].hdr_name, hdr->hdr[IPA_IP_v6].name,
		sizeof(tx_prop[1].hdr_name));

	/* populate rx prop */
	rx.num_props = 2;
	rx.prop = rx_prop;

	memset(rx_prop, 0, sizeof(rx_prop));
	rx_prop[0].ip = IPA_IP_v4;
	rx_prop[0].src_pipe = IPA_CLIENT_WLAN1_PROD;
	rx_prop[0].hdr_l2_type = in->hdr_info[0].hdr_type;
	if (in->is_meta_data_valid) {
		rx_prop[0].attrib.attrib_mask |= IPA_FLT_META_DATA;
		rx_prop[0].attrib.meta_data = in->meta_data;
		rx_prop[0].attrib.meta_data_mask = in->meta_data_mask;
	}

	rx_prop[1].ip = IPA_IP_v6;
	rx_prop[1].src_pipe = IPA_CLIENT_WLAN1_PROD;
	rx_prop[1].hdr_l2_type = in->hdr_info[1].hdr_type;
	if (in->is_meta_data_valid) {
		rx_prop[1].attrib.attrib_mask |= IPA_FLT_META_DATA;
		rx_prop[1].attrib.meta_data = in->meta_data;
		rx_prop[1].attrib.meta_data_mask = in->meta_data_mask;
	}

	if (ipa_register_intf(in->netdev_name, &tx, &rx)) {
		IPA_WDI3_ERR("fail to add interface prop\n");
		ret = -EFAULT;
		goto fail_commit_hdr;
	}

	list_add(&new_intf->link, &ipa_wdi3_ctx->head_intf_list);
	init_completion(&ipa_wdi3_ctx->wdi3_completion);

	kfree(hdr);
	mutex_unlock(&ipa_wdi3_ctx->lock);
	return 0;

fail_commit_hdr:
	kfree(hdr);
fail_alloc_hdr:
	kfree(new_intf);
	mutex_unlock(&ipa_wdi3_ctx->lock);
	return ret;
}
EXPORT_SYMBOL(ipa_wdi3_reg_intf);

int ipa_wdi3_dereg_intf(const char *netdev_name)
{
	int len, ret = 0;
	struct ipa_ioc_del_hdr *hdr = NULL;
	struct ipa_wdi3_intf_info *entry;
	struct ipa_wdi3_intf_info *next;

	if (!netdev_name) {
		IPA_WDI3_ERR("no netdev name.\n");
		return -EINVAL;
	}

	if (!ipa_wdi3_ctx) {
		IPA_WDI3_ERR("wdi3 ctx is not initialized.\n");
		return -EPERM;
	}

	mutex_lock(&ipa_wdi3_ctx->lock);
	list_for_each_entry_safe(entry, next, &ipa_wdi3_ctx->head_intf_list,
		link)
		if (strcmp(entry->netdev_name, netdev_name) == 0) {
			len = sizeof(struct ipa_ioc_del_hdr) +
				2 * sizeof(struct ipa_hdr_del);
			hdr = kzalloc(len, GFP_KERNEL);
			if (hdr == NULL) {
				IPA_WDI3_ERR("fail to alloc %d bytes\n", len);
				mutex_unlock(&ipa_wdi3_ctx->lock);
				return -ENOMEM;
			}

			hdr->commit = 1;
			hdr->num_hdls = 2;
			hdr->hdl[0].hdl = entry->partial_hdr_hdl[0];
			hdr->hdl[1].hdl = entry->partial_hdr_hdl[1];
			IPA_WDI3_DBG("IPv4 hdr hdl: %d IPv6 hdr hdl: %d\n",
				hdr->hdl[0].hdl, hdr->hdl[1].hdl);

			if (ipa_del_hdr(hdr)) {
				IPA_WDI3_ERR("fail to delete partial header\n");
				ret = -EFAULT;
				goto fail;
			}

			if (ipa_deregister_intf(entry->netdev_name)) {
				IPA_WDI3_ERR("fail to del interface props\n");
				ret = -EFAULT;
				goto fail;
			}
			list_del(&entry->link);
			kfree(entry);

			break;
		}

fail:
	kfree(hdr);
	mutex_unlock(&ipa_wdi3_ctx->lock);
	return ret;
}
EXPORT_SYMBOL(ipa_wdi3_dereg_intf);

static void ipa_wdi3_rm_notify(void *user_data, enum ipa_rm_event event,
		unsigned long data)
{
	if (!ipa_wdi3_ctx) {
		IPA_WDI3_ERR("Invalid context\n");
		return;
	}

	switch (event) {
	case IPA_RM_RESOURCE_GRANTED:
		complete_all(&ipa_wdi3_ctx->wdi3_completion);
		break;

	case IPA_RM_RESOURCE_RELEASED:
		break;

	default:
		IPA_WDI3_ERR("Invalid RM Evt: %d", event);
		break;
	}
}

static int ipa_wdi3_cons_release(void)
{
	return 0;
}

static int ipa_wdi3_cons_request(void)
{
	int ret = 0;

	if (!ipa_wdi3_ctx) {
		IPA_WDI3_ERR("wdi3 ctx is not initialized\n");
		ret = -EFAULT;
	}

	return ret;
}

int ipa_wdi3_conn_pipes(struct ipa_wdi3_conn_in_params *in,
			struct ipa_wdi3_conn_out_params *out)
{
	int ret = 0;
	struct ipa_rm_create_params param;

	if (!(in && out)) {
		IPA_WDI3_ERR("empty parameters. in=%pK out=%pK\n", in, out);
		return -EINVAL;
	}

	if (!ipa_wdi3_ctx) {
		ipa_wdi3_ctx = kzalloc(sizeof(*ipa_wdi3_ctx), GFP_KERNEL);
		if (ipa_wdi3_ctx == NULL) {
			IPA_WDI3_ERR("fail to alloc wdi3 ctx\n");
			return -EFAULT;
		}
		mutex_init(&ipa_wdi3_ctx->lock);
		INIT_LIST_HEAD(&ipa_wdi3_ctx->head_intf_list);
	}
	ipa_wdi3_ctx->notify = in->notify;
	ipa_wdi3_ctx->priv = in->priv;

	memset(&param, 0, sizeof(param));
	param.name = IPA_RM_RESOURCE_WLAN_PROD;
	param.reg_params.user_data = ipa_wdi3_ctx;
	param.reg_params.notify_cb = ipa_wdi3_rm_notify;
	param.floor_voltage = IPA_VOLTAGE_SVS;
	ret = ipa_rm_create_resource(&param);
	if (ret) {
		IPA_WDI3_ERR("fail to create WLAN_PROD resource\n");
		return -EFAULT;
	}

	memset(&param, 0, sizeof(param));
	param.name = IPA_RM_RESOURCE_WLAN_CONS;
	param.request_resource = ipa_wdi3_cons_request;
	param.release_resource = ipa_wdi3_cons_release;
	ret = ipa_rm_create_resource(&param);
	if (ret) {
		IPA_WDI3_ERR("fail to create WLAN_CONS resource\n");
		goto fail_create_rm_cons;
	}

	if (ipa_rm_add_dependency(IPA_RM_RESOURCE_WLAN_PROD,
		IPA_RM_RESOURCE_APPS_CONS)) {
		IPA_WDI3_ERR("fail to add rm dependency\n");
		ret = -EFAULT;
		goto fail;
	}

	if (ipa_conn_wdi3_pipes(in, out)) {
		IPA_WDI3_ERR("fail to setup wdi3 pipes\n");
		ret = -EFAULT;
		goto fail;
	}

	return 0;

fail:
	ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS);
fail_create_rm_cons:
	ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD);

	return ret;
}
EXPORT_SYMBOL(ipa_wdi3_conn_pipes);

int ipa_wdi3_disconn_pipes(void)
{
	int ipa_ep_idx_rx, ipa_ep_idx_tx;

	if (!ipa_wdi3_ctx) {
		IPA_WDI3_ERR("wdi3 ctx is not initialized\n");
		return -EPERM;
	}

	ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_PROD);
	ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
	if (ipa_disconn_wdi3_pipes(ipa_ep_idx_rx, ipa_ep_idx_tx)) {
		IPA_WDI3_ERR("fail to tear down wdi3 pipes\n");
		return -EFAULT;
	}

	if (ipa_rm_delete_dependency(IPA_RM_RESOURCE_WLAN_PROD,
				IPA_RM_RESOURCE_APPS_CONS)) {
		IPA_WDI3_ERR("fail to delete rm dependency\n");
		return -EFAULT;
	}

	if (ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD)) {
		IPA_WDI3_ERR("fail to delete WLAN_PROD resource\n");
		return -EFAULT;
	}

	if (ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS)) {
		IPA_WDI3_ERR("fail to delete WLAN_CONS resource\n");
		return -EFAULT;
	}

	return 0;
}
EXPORT_SYMBOL(ipa_wdi3_disconn_pipes);

int ipa_wdi3_enable_pipes(void)
{
	int ret;
	int ipa_ep_idx_tx, ipa_ep_idx_rx;

	if (!ipa_wdi3_ctx) {
		IPA_WDI3_ERR("wdi3 ctx is not initialized.\n");
		return -EPERM;
	}

	ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_PROD);
	ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
	if (ipa_enable_wdi3_pipes(ipa_ep_idx_tx, ipa_ep_idx_rx)) {
		IPA_WDI3_ERR("fail to enable wdi3 pipes\n");
		return -EFAULT;
	}

	ret = ipa_rm_request_resource(IPA_RM_RESOURCE_WLAN_PROD);
	if (ret == -EINPROGRESS) {
		if (wait_for_completion_timeout(&ipa_wdi3_ctx->wdi3_completion,
			10*HZ) == 0) {
			IPA_WDI3_ERR("WLAN_PROD resource req time out\n");
			return -EFAULT;
		}
	} else if (ret != 0) {
		IPA_WDI3_ERR("fail to request resource\n");
		return -EFAULT;
	}

	return 0;
}
EXPORT_SYMBOL(ipa_wdi3_enable_pipes);

int ipa_wdi3_disable_pipes(void)
{
	int ret;
	int ipa_ep_idx_tx, ipa_ep_idx_rx;

	if (!ipa_wdi3_ctx) {
		IPA_WDI3_ERR("wdi3 ctx is not initialized.\n");
		return -EPERM;
	}

	ret = ipa_rm_release_resource(IPA_RM_RESOURCE_WLAN_PROD);
	if (ret != 0) {
		IPA_WDI3_ERR("fail to release resource\n");
		return -EFAULT;
	}

	ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_PROD);
	ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
	if (ipa_disable_wdi3_pipes(ipa_ep_idx_tx, ipa_ep_idx_rx)) {
		IPA_WDI3_ERR("fail to disable wdi3 pipes\n");
		return -EFAULT;
	}

	return 0;
}
EXPORT_SYMBOL(ipa_wdi3_disable_pipes);

int ipa_wdi3_set_perf_profile(struct ipa_wdi3_perf_profile *profile)
{
	struct ipa_rm_perf_profile rm_profile;
	enum ipa_rm_resource_name resource_name;

	if (profile == NULL) {
		IPA_WDI3_ERR("Invalid input\n");
		return -EINVAL;
	}

	rm_profile.max_supported_bandwidth_mbps =
		profile->max_supported_bw_mbps;

	if (profile->client == IPA_CLIENT_WLAN1_PROD) {
		resource_name = IPA_RM_RESOURCE_WLAN_PROD;
	} else if (profile->client == IPA_CLIENT_WLAN1_CONS) {
		resource_name = IPA_RM_RESOURCE_WLAN_CONS;
	} else {
		IPA_WDI3_ERR("not supported\n");
		return -EINVAL;
	}

	if (ipa_rm_set_perf_profile(resource_name, &rm_profile)) {
		IPA_WDI3_ERR("fail to setup rm perf profile\n");
		return -EFAULT;
	}

	return 0;
}
EXPORT_SYMBOL(ipa_wdi3_set_perf_profile);
+11 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/ipc_logging.h>
#include <linux/ipa.h>
#include <linux/ipa_uc_offload.h>
#include <linux/ipa_wdi3.h>

#define __FILENAME__ \
	(strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
@@ -375,6 +376,16 @@ int ipa_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl);
int ipa_ntn_uc_reg_rdyCB(void (*ipauc_ready_cb)(void *user_data),
			      void *user_data);
void ipa_ntn_uc_dereg_rdyCB(void);

int ipa_conn_wdi3_pipes(struct ipa_wdi3_conn_in_params *in,
	struct ipa_wdi3_conn_out_params *out);

int ipa_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);

int ipa_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);

int ipa_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);

const char *ipa_get_version_string(enum ipa_hw_type ver);
int ipa_start_gsi_channel(u32 clnt_hdl);

Loading