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

Commit 9184a537 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: Fixed Netmgr, A7/Q6 synchronization issue"

parents fc23fa34 0f138b56
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -233,6 +233,7 @@ static int ipa_a5_svc_req_cb(struct qmi_handle *handle, void *conn_h,
		break;
	case QMI_IPA_INSTALL_FILTER_RULE_REQ_V01:
		rc = handle_install_filter_rule_req(req_h, req);
		rc = wwan_update_mux_channel_prop();
		break;
	case QMI_IPA_FILTER_INSTALLED_NOTIF_REQ_V01:
		rc = handle_filter_installed_notify_req(req_h, req);
+11 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <mach/ipa.h>
#include <linux/ipa_qmi_service_v01.h>
#include <mach/msm_qmi_interface.h>
#include <uapi/linux/msm_rmnet.h>
#include "ipa_i.h"

/**
@@ -31,6 +32,14 @@
#define IPAWANERR(fmt, args...) \
	pr_err(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)

struct rmnet_mux_val {
	uint32_t  mux_id;
	int8_t    vchannel_name[IFNAMSIZ];
	bool mux_channel_set;
	bool ul_flt_reg;
	bool mux_hdr_set;
};

int ipa_qmi_service_init(void);
void ipa_qmi_service_exit(void);

@@ -43,6 +52,8 @@ int qmi_filter_notify_send(struct ipa_fltr_installed_notif_req_msg_v01 *req);
int copy_ul_filter_rule_to_ipa(struct ipa_install_fltr_rule_req_msg_v01
		*rule_req, uint32_t *rule_hdl);

int wwan_update_mux_channel_prop(void);

int wan_ioctl_init(void);

extern struct elem_info ipa_init_modem_driver_req_msg_data_v01_ei[];
+204 −29
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <uapi/linux/msm_rmnet.h>
#include <linux/if_arp.h>
#include <net/pkt_sched.h>
#include <linux/workqueue.h>
@@ -34,6 +33,7 @@
#define WWAN_DATA_LEN 2000
#define HEADROOM_FOR_QMAP   8 /* for mux header */
#define TAILROOM            0 /* for padding by mux layer */
#define MAX_NUM_OF_MUX_CHANNEL  10 /* max mux channels */
#define UL_FILTER_RULE_HANDLE_START 69

#define IPA_WWAN_DEV_NAME "rmnet_ipa%d"
@@ -42,10 +42,15 @@ static struct net_device *ipa_netdevs[IPA_WWAN_DEVICE_COUNT];
static struct ipa_sys_connect_params apps_to_ipa_ep_cfg, ipa_to_apps_ep_cfg;
static u32 qmap_hdr_hdl, dflt_wan_rt_hdl;
static struct ipa_ioc_ext_intf_prop q6_ul_filter_rule[MAX_NUM_Q6_RULE];
static int num_q6_rule;
static u32 q6_ul_filter_rule_hdl[MAX_NUM_Q6_RULE];
static struct rmnet_mux_val mux_channel[MAX_NUM_OF_MUX_CHANNEL];
static int num_q6_rule, old_num_q6_rule;
static int rmnet_index;
static bool egress_set, a7_ul_flt_set;

u32 apps_to_ipa_hdl, ipa_to_apps_hdl; /* get handler from ipa */
static int wwan_add_ul_flt_rule_to_ipa(void);
static int wwan_del_ul_flt_rule_to_ipa(void);

enum wwan_device_status {
	WWAN_DEVICE_INACTIVE = 0,
@@ -140,7 +145,7 @@ static int ipa_add_qmap_hdr(uint32_t mux_id)

	snprintf(hdr_name, IPA_RESOURCE_NAME_MAX, "%s%d",
		 A2_MUX_HDR_NAME_V4_PREF,
		 rmnet_index);
		 mux_id);
	 strlcpy(hdr_entry->name, hdr_name,
				IPA_RESOURCE_NAME_MAX);

@@ -400,7 +405,7 @@ static int wwan_add_ul_flt_rule_to_ipa(void)
	for (i = 0; i < num_q6_rule; i++) {
		param->ip = q6_ul_filter_rule[i].ip;
		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
		flt_rule_entry.at_rear = false;
		flt_rule_entry.at_rear = true;
		flt_rule_entry.rule.action = q6_ul_filter_rule[i].action;
		flt_rule_entry.rule.rt_tbl_idx
		= q6_ul_filter_rule[i].rt_tbl_idx;
@@ -418,6 +423,9 @@ static int wwan_add_ul_flt_rule_to_ipa(void)
		if (ipa_add_flt_rule((struct ipa_ioc_add_flt_rule *)param)) {
			retval = -EFAULT;
			IPAWANERR("add A7 UL filter rule(%d) failed\n", i);
		} else {
			/* store the rule handler */
			q6_ul_filter_rule_hdl[i] = param->rules[0].flt_rule_hdl;
		}
	}

@@ -436,11 +444,67 @@ static int wwan_add_ul_flt_rule_to_ipa(void)
		IPAWANDBG("add filter rule index on A7-RX failed\n");
		retval = -EFAULT;
	}
	old_num_q6_rule = num_q6_rule;
	IPAWANDBG("add (%d) filter rule index on A7-RX\n",
			old_num_q6_rule);
	kfree(param);
	return retval;
}

static int wwan_register_to_ipa(const char *dev_name, uint32_t mux_id)

static int wwan_del_ul_flt_rule_to_ipa(void)
{
	u32 pyld_sz;
	int i, retval = 0;
	struct ipa_ioc_del_flt_rule *param;
	struct ipa_flt_rule_del flt_rule_entry;

	pyld_sz = sizeof(struct ipa_ioc_del_flt_rule) +
	   sizeof(struct ipa_flt_rule_del);
	param = kzalloc(pyld_sz, GFP_KERNEL);
	if (!param) {
		IPAWANERR("kzalloc failed\n");
		return -ENOMEM;
	}

	param->commit = 1;
	param->num_hdls = (uint8_t) 1;

	for (i = 0; i < old_num_q6_rule; i++) {
		param->ip = q6_ul_filter_rule[i].ip;
		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_del));
		flt_rule_entry.hdl = q6_ul_filter_rule_hdl[i];
		/* debug rt-hdl*/
		IPAWANDBG("delete-IPA rule index(%d)\n", i);
		memcpy(&(param->hdl[0]), &flt_rule_entry,
			sizeof(struct ipa_flt_rule_del));
		if (ipa_del_flt_rule((struct ipa_ioc_del_flt_rule *)param)) {
			IPAWANERR("del A7 UL filter rule(%d) failed\n", i);
			return -EFAULT;
		}
	}

	/* set UL filter-rule add-indication */
	a7_ul_flt_set = false;
	old_num_q6_rule = 0;

	kfree(param);
	return retval;
}

static int find_mux_channel_index(uint32_t mux_id)
{
	int i;

	for (i = 0; i < MAX_NUM_OF_MUX_CHANNEL; i++) {
		if (mux_id == mux_channel[i].mux_id)
			return i;
	}
	return MAX_NUM_OF_MUX_CHANNEL;
}


static int wwan_register_to_ipa(int index)
{
	struct ipa_tx_intf tx_properties = {0};
	struct ipa_ioc_tx_intf_prop tx_ioc_properties[2] = { {0}, {0} };
@@ -455,22 +519,30 @@ static int wwan_register_to_ipa(const char *dev_name, uint32_t mux_id)
	u32 pyld_sz;
	int ret = 0, i;

	IPAWANDBG("device[%s]:\n", dev_name);
	ipa_add_qmap_hdr(mux_id);
	IPAWANDBG("index(%d) device[%s]:\n", index,
		mux_channel[index].vchannel_name);
	if (!mux_channel[index].mux_hdr_set) {
		ret = ipa_add_qmap_hdr(mux_channel[index].mux_id);
		if (ret) {
			IPAWANERR("ipa_add_mux_hdr failed (%d)\n", index);
			return ret;
		}
		mux_channel[index].mux_hdr_set = true;
	}
	tx_properties.prop = tx_ioc_properties;
	tx_ipv4_property = &tx_properties.prop[0];
	tx_ipv4_property->ip = IPA_IP_v4;
	tx_ipv4_property->dst_pipe = IPA_CLIENT_APPS_WAN_CONS;
	snprintf(tx_ipv4_property->hdr_name, IPA_RESOURCE_NAME_MAX, "%s%d",
		 A2_MUX_HDR_NAME_V4_PREF,
		 rmnet_index);
		 mux_channel[index].mux_id);
	tx_ipv6_property = &tx_properties.prop[1];
	tx_ipv6_property->ip = IPA_IP_v6;
	tx_ipv6_property->dst_pipe = IPA_CLIENT_APPS_WAN_CONS;
	/* no need use A2_MUX_HDR_NAME_V6_PREF, same header */
	snprintf(tx_ipv6_property->hdr_name, IPA_RESOURCE_NAME_MAX, "%s%d",
		 A2_MUX_HDR_NAME_V4_PREF,
		 rmnet_index);
		 mux_channel[index].mux_id);
	tx_properties.num_props = 2;

	rx_properties.prop = rx_ioc_properties;
@@ -478,13 +550,14 @@ static int wwan_register_to_ipa(const char *dev_name, uint32_t mux_id)
	rx_ipv4_property->ip = IPA_IP_v4;
	rx_ipv4_property->attrib.attrib_mask |= IPA_FLT_META_DATA;
	rx_ipv4_property->attrib.meta_data =
		mux_id << WWAN_METADATA_SHFT;
		mux_channel[index].mux_id << WWAN_METADATA_SHFT;
	rx_ipv4_property->attrib.meta_data_mask = WWAN_METADATA_MASK;
	rx_ipv4_property->src_pipe = IPA_CLIENT_APPS_LAN_WAN_PROD;
	rx_ipv6_property = &rx_properties.prop[1];
	rx_ipv6_property->ip = IPA_IP_v6;
	rx_ipv6_property->attrib.attrib_mask |= IPA_FLT_META_DATA;
	rx_ipv6_property->attrib.meta_data = mux_id << WWAN_METADATA_SHFT;
	rx_ipv6_property->attrib.meta_data =
		mux_channel[index].mux_id << WWAN_METADATA_SHFT;
	rx_ipv6_property->attrib.meta_data_mask = WWAN_METADATA_MASK;
	rx_ipv6_property->src_pipe = IPA_CLIENT_APPS_LAN_WAN_PROD;
	rx_properties.num_props = 2;
@@ -503,26 +576,85 @@ static int wwan_register_to_ipa(const char *dev_name, uint32_t mux_id)
		memcpy(&(ext_properties.prop[i]),
				 &(q6_ul_filter_rule[i]),
				sizeof(struct ipa_ioc_ext_intf_prop));
	ext_properties.prop[i].mux_id = mux_id;
	IPAWANDBG("ip: %d rt-tbl:%d\n",
	ext_properties.prop[i].mux_id = mux_channel[index].mux_id;
	IPAWANDBG("index %d ip: %d rt-tbl:%d\n", i,
		ext_properties.prop[i].ip,
		ext_properties.prop[i].rt_tbl_idx);
	IPAWANDBG("action: %d mux:%d\n",
		ext_properties.prop[i].action,
		ext_properties.prop[i].mux_id);
	}
	ret = ipa_register_intf_ext(dev_name, &tx_properties,
	ret = ipa_register_intf_ext(mux_channel[index].
		vchannel_name, &tx_properties,
		&rx_properties, &ext_properties);
	if (ret) {
		IPAWANERR("[%s]:ipa_register_intf failed %d\n", dev_name, ret);
		IPAWANERR("[%s]:ipa_register_intf failed %d\n",
			mux_channel[index].vchannel_name, ret);
	goto fail;
	}
	rmnet_index++;
	mux_channel[index].ul_flt_reg = true;
fail:
	kfree(ext_ioc_properties);
	return ret;
}

int wwan_update_mux_channel_prop(void)
{
	int ret = 0, i;
	/* install UL filter rules */
	if (egress_set) {
		IPAWANDBG("setup UL filter rules\n");
		if (a7_ul_flt_set) {
			IPAWANDBG("del previous UL filter rules\n");
			/* delete rule hdlers */
			ret = wwan_del_ul_flt_rule_to_ipa();
			if (ret) {
				IPAWANERR("failed to del old UL rules\n");
				return -EINVAL;
			} else {
				IPAWANDBG("success to del old UL rules\n");
			}
		}
		ret = wwan_add_ul_flt_rule_to_ipa();
		if (ret)
			IPAWANERR("failed to install UL rules\n");
		else
			a7_ul_flt_set = true;
	}
	/* update Tx/Rx/Ext property */
	IPAWANDBG("update Tx/Rx/Ext property in IPA\n");
	if (rmnet_index == 0) {
		IPAWANDBG("no Tx/Rx/Ext property registered in IPA\n");
		return ret;
	}

	for (i = 0; i < rmnet_index; i++) {
		if (mux_channel[i].ul_flt_reg) {
			ret = ipa_deregister_intf(mux_channel[i].vchannel_name);
			if (ret < 0) {
				IPAWANERR("de-register device %s(%d) failed\n",
					mux_channel[i].vchannel_name,
					i);
				return -ENODEV;
			} else {
				IPAWANDBG("de-register device %s(%d) success\n",
					mux_channel[i].vchannel_name,
					i);
			}
		}
		ret = wwan_register_to_ipa(i);
		if (ret < 0) {
			IPAWANERR("failed to re-regist %s, mux %d, index %d\n",
				mux_channel[i].vchannel_name,
				mux_channel[i].mux_id,
				i);
			return -ENODEV;
		}
		mux_channel[i].ul_flt_reg = true;
	}
	return ret;
}

static int __ipa_wwan_open(struct net_device *dev)
{
	struct wwan_private *wwan_ptr = netdev_priv(dev);
@@ -742,7 +874,7 @@ static void apps_ipa_packet_receive_notify(void *priv,
static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
	int rc = 0;
	int mru = 1000, epid = 1;
	int mru = 1000, epid = 1, mux_index;
	struct rmnet_ioctl_extended_s extend_ioctl_data;

	IPAWANDBG("rmnet_ipa got ioctl number 0x%08x", cmd);
@@ -876,18 +1008,49 @@ static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
			break;
		/*  Add MUX ID  */
		case RMNET_IOCTL_ADD_MUX_CHANNEL:
			mux_index = find_mux_channel_index(
				extend_ioctl_data.u.rmnet_mux_val.mux_id);
			if (mux_index < MAX_NUM_OF_MUX_CHANNEL) {
				IPAWANDBG("already setup mux(%d)\n",
					extend_ioctl_data.u.
					rmnet_mux_val.mux_id);
				return rc;
			}
			IPAWANDBG("ADD_MUX_CHANNEL(%d, name: %s)\n",
			extend_ioctl_data.u.rmnet_mux_val.mux_id,
			extend_ioctl_data.u.rmnet_mux_val.vchannel_name);
			rc = wwan_register_to_ipa(
			/* cache the mux name and id */
			mux_channel[rmnet_index].mux_id =
				extend_ioctl_data.u.rmnet_mux_val.mux_id;
			memcpy(mux_channel[rmnet_index].vchannel_name,
				extend_ioctl_data.u.rmnet_mux_val.vchannel_name,
				extend_ioctl_data.u.rmnet_mux_val.mux_id);
				sizeof(mux_channel[rmnet_index].vchannel_name));
			IPAWANDBG("cashe device[%s:%d] in IPA_wan[%d]\n",
				mux_channel[rmnet_index].vchannel_name,
				mux_channel[rmnet_index].mux_id,
				rmnet_index);
			/* check if UL filter rules coming*/
			if (num_q6_rule != 0) {
				IPAWANERR("dev(%s) register to IPA\n",
					extend_ioctl_data.u.rmnet_mux_val.
					vchannel_name);
				rc = wwan_register_to_ipa(rmnet_index);
				if (rc < 0) {
				IPAWANERR("(%s) failed to register IPA rc %d\n",
				extend_ioctl_data.u.rmnet_mux_val.vchannel_name,
				rc);
					IPAWANERR("device %s reg IPA failed\n",
						extend_ioctl_data.u.
						rmnet_mux_val.vchannel_name);
					return -ENODEV;
				}
				mux_channel[rmnet_index].mux_channel_set = true;
				mux_channel[rmnet_index].ul_flt_reg = true;
			} else {
				IPAWANERR("dev(%s) not register to IPA\n",
					extend_ioctl_data.u.
					rmnet_mux_val.vchannel_name);
				mux_channel[rmnet_index].mux_channel_set = true;
				mux_channel[rmnet_index].ul_flt_reg = false;
			}
			rmnet_index++;
			break;
		case RMNET_IOCTL_SET_EGRESS_DATA_FORMAT:
			IPAWANDBG("get RMNET_IOCTL_SET_EGRESS_DATA_FORMAT\n");
@@ -924,11 +1087,18 @@ static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
				IPAWANERR("failed to config egress endpoint\n");

			if (num_q6_rule != 0) {
				/* already got Q6 UL filter rules*/
				rc = wwan_add_ul_flt_rule_to_ipa();
				egress_set = true;
				if (rc)
					IPAWANERR("install UL rules failed\n");
				else
					a7_ul_flt_set = true;
			} else {
				IPAWANERR("not get QMI UL rules from Q6\n");
				/* wait Q6 UL filter rules*/
				egress_set = true;
				IPAWANDBG("no UL-rules, egress_set(%d)\n",
					egress_set);
			}
			break;
		case RMNET_IOCTL_SET_INGRESS_DATA_FORMAT:/*  Set IDF  */
@@ -1057,7 +1227,7 @@ static void ipa_wwan_setup(struct net_device *dev)
 */
static int __init ipa_wwan_init(void)
{
	int ret;
	int ret, i;
	struct net_device *dev;
	struct wwan_private *wwan_ptr;

@@ -1078,7 +1248,12 @@ static int __init ipa_wwan_init(void)
	/* initialize ex property setup */
	memset(q6_ul_filter_rule, 0, sizeof(q6_ul_filter_rule));
	num_q6_rule = 0;
	old_num_q6_rule = 0;
	rmnet_index = 0;
	egress_set = false;
	a7_ul_flt_set = false;
	for (i = 0; i < MAX_NUM_OF_MUX_CHANNEL; i++)
		memset(&mux_channel[i], 0, sizeof(struct rmnet_mux_val));

	dev = alloc_netdev(sizeof(struct wwan_private),
			   IPA_WWAN_DEV_NAME, ipa_wwan_setup);