Merge "neigh: Better handling of transition to NUD_PROBE state"
diff --git a/drivers/bif/qpnp-bsi.c b/drivers/bif/qpnp-bsi.c
index e3f7d2f..33ccb82 100644
--- a/drivers/bif/qpnp-bsi.c
+++ b/drivers/bif/qpnp-bsi.c
@@ -1560,7 +1560,7 @@
 	int rc;
 
 	rc = devm_request_irq(dev, chip->irq[QPNP_BSI_IRQ_ERR],
-			qpnp_bsi_isr, IRQF_TRIGGER_RISING, "bsi-err", chip);
+			qpnp_bsi_isr, IRQF_TRIGGER_HIGH, "bsi-err", chip);
 	if (rc < 0) {
 		dev_err(dev, "%s: request for bsi-err irq %d failed, rc=%d\n",
 			__func__, chip->irq[QPNP_BSI_IRQ_ERR], rc);
@@ -1575,7 +1575,7 @@
 	}
 
 	rc = devm_request_irq(dev, chip->irq[QPNP_BSI_IRQ_RX],
-			qpnp_bsi_isr, IRQF_TRIGGER_RISING, "bsi-rx", chip);
+			qpnp_bsi_isr, IRQF_TRIGGER_HIGH, "bsi-rx", chip);
 	if (rc < 0) {
 		dev_err(dev, "%s: request for bsi-rx irq %d failed, rc=%d\n",
 			__func__, chip->irq[QPNP_BSI_IRQ_RX], rc);
@@ -1590,7 +1590,7 @@
 	}
 
 	rc = devm_request_irq(dev, chip->irq[QPNP_BSI_IRQ_TX],
-			qpnp_bsi_isr, IRQF_TRIGGER_RISING, "bsi-tx", chip);
+			qpnp_bsi_isr, IRQF_TRIGGER_HIGH, "bsi-tx", chip);
 	if (rc < 0) {
 		dev_err(dev, "%s: request for bsi-tx irq %d failed, rc=%d\n",
 			__func__, chip->irq[QPNP_BSI_IRQ_TX], rc);
diff --git a/fs/mount.h b/fs/mount.h
index 4ef36d9..9a5edb5 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -4,8 +4,11 @@
 
 struct mnt_namespace {
 	atomic_t		count;
+	unsigned int            proc_inum;
 	struct mount *	root;
 	struct list_head	list;
+	 struct user_namespace   *user_ns;
+	u64			seq;	/* Sequence number to prevent loops */
 	wait_queue_head_t poll;
 	int event;
 };
diff --git a/fs/namespace.c b/fs/namespace.c
index e608199..34d97ca 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -12,6 +12,7 @@
 #include <linux/export.h>
 #include <linux/capability.h>
 #include <linux/mnt_namespace.h>
+#include <linux/user_namespace.h>
 #include <linux/namei.h>
 #include <linux/security.h>
 #include <linux/idr.h>
@@ -20,6 +21,7 @@
 #include <linux/fs_struct.h>	/* get_fs_root et.al. */
 #include <linux/fsnotify.h>	/* fsnotify_vfsmount_delete */
 #include <linux/uaccess.h>
+#include <linux/proc_fs.h>
 #include "pnode.h"
 #include "internal.h"
 
@@ -728,7 +730,7 @@
 	struct mount *mnt = alloc_vfsmnt(old->mnt_devname);
 
 	if (mnt) {
-		if (flag & (CL_SLAVE | CL_PRIVATE))
+		 if (flag & (CL_SLAVE | CL_PRIVATE | CL_SHARED_TO_SLAVE))
 			mnt->mnt_group_id = 0; /* not a peer of original */
 		else
 			mnt->mnt_group_id = old->mnt_group_id;
@@ -749,7 +751,8 @@
 		list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
 		br_write_unlock(vfsmount_lock);
 
-		if (flag & CL_SLAVE) {
+		if ((flag & CL_SLAVE) ||
+		    ((flag & CL_SHARED_TO_SLAVE) && IS_MNT_SHARED(old))) {
 			list_add(&mnt->mnt_slave, &old->mnt_slave_list);
 			mnt->mnt_master = old;
 			CLEAR_MNT_SHARED(mnt);
@@ -1209,7 +1212,7 @@
 		goto dput_and_out;
 
 	retval = -EPERM;
-	if (!capable(CAP_SYS_ADMIN))
+	if (!ns_capable(mnt->mnt_ns->user_ns, CAP_SYS_ADMIN))
 		goto dput_and_out;
 
 	retval = do_umount(mnt, flags);
@@ -1235,7 +1238,7 @@
 
 static int mount_is_safe(struct path *path)
 {
-	if (capable(CAP_SYS_ADMIN))
+	if (ns_capable(real_mount(path->mnt)->mnt_ns->user_ns, CAP_SYS_ADMIN))
 		return 0;
 	return -EPERM;
 #ifdef notyet
@@ -1251,6 +1254,26 @@
 #endif
 }
 
+static bool mnt_ns_loop(struct path *path)
+{
+	/* Could bind mounting the mount namespace inode cause a
+	 * mount namespace loop?
+	 */
+	struct inode *inode = path->dentry->d_inode;
+	struct proc_inode *ei;
+	struct mnt_namespace *mnt_ns;
+
+	if (!proc_ns_inode(inode))
+		return false;
+
+	ei = PROC_I(inode);
+	if (ei->ns_ops != &mntns_operations)
+		return false;
+
+	mnt_ns = ei->ns;
+	return current->nsproxy->mnt_ns->seq >= mnt_ns->seq;
+}
+
 struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
 					int flag)
 {
@@ -1548,7 +1571,7 @@
 	int type;
 	int err = 0;
 
-	if (!capable(CAP_SYS_ADMIN))
+	if (!ns_capable(mnt->mnt_ns->user_ns, CAP_SYS_ADMIN))
 		return -EPERM;
 
 	if (path->dentry != path->mnt->mnt_root)
@@ -1593,6 +1616,10 @@
 	if (err)
 		return err;
 
+	err = -EINVAL;
+	if (mnt_ns_loop(&old_path))
+		goto out; 
+
 	err = lock_mount(path);
 	if (err)
 		goto out;
@@ -1707,7 +1734,7 @@
 	struct mount *p;
 	struct mount *old;
 	int err = 0;
-	if (!capable(CAP_SYS_ADMIN))
+	if (!ns_capable(real_mount(path->mnt)->mnt_ns->user_ns, CAP_SYS_ADMIN))
 		return -EPERM;
 	if (!old_name || !*old_name)
 		return -EINVAL;
@@ -1794,21 +1821,6 @@
 	return ERR_PTR(err);
 }
 
-static struct vfsmount *
-do_kern_mount(const char *fstype, int flags, const char *name, void *data)
-{
-	struct file_system_type *type = get_fs_type(fstype);
-	struct vfsmount *mnt;
-	if (!type)
-		return ERR_PTR(-ENODEV);
-	mnt = vfs_kern_mount(type, flags, name, data);
-	if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
-	    !mnt->mnt_sb->s_subtype)
-		mnt = fs_set_subtype(mnt, fstype);
-	put_filesystem(type);
-	return mnt;
-}
-
 /*
  * add a mount into a namespace's mount tree
  */
@@ -1848,20 +1860,46 @@
  * create a new mount for userspace and request it to be added into the
  * namespace's tree
  */
-static int do_new_mount(struct path *path, char *type, int flags,
+static int do_new_mount(struct path *path, const char *fstype, int flags,
 			int mnt_flags, char *name, void *data)
 {
+	struct file_system_type *type;
+	struct user_namespace *user_ns;
 	struct vfsmount *mnt;
 	int err;
 
-	if (!type)
+	if (!fstype)
 		return -EINVAL;
 
 	/* we need capabilities... */
-	if (!capable(CAP_SYS_ADMIN))
+	user_ns = real_mount(path->mnt)->mnt_ns->user_ns;
+	if (!ns_capable(user_ns, CAP_SYS_ADMIN))
 		return -EPERM;
 
-	mnt = do_kern_mount(type, flags, name, data);
+	type = get_fs_type(fstype);
+	if (!type)
+		return -ENODEV;
+
+	if (user_ns != &init_user_ns) {
+		if (!(type->fs_flags & FS_USERNS_MOUNT)) {
+			put_filesystem(type);
+			return -EPERM;
+		}
+		/* Only in special cases allow devices from mounts
+		 * created outside the initial user namespace.
+		 */
+		if (!(type->fs_flags & FS_USERNS_DEV_MOUNT)) {
+			flags |= MS_NODEV;
+			mnt_flags |= MNT_NODEV;
+		}
+	}
+
+	mnt = vfs_kern_mount(type, flags, name, data);
+	if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
+	    !mnt->mnt_sb->s_subtype)
+		mnt = fs_set_subtype(mnt, fstype);
+
+	put_filesystem(type);
 	if (IS_ERR(mnt))
 		return PTR_ERR(mnt);
 
@@ -2192,18 +2230,43 @@
 	return retval;
 }
 
-static struct mnt_namespace *alloc_mnt_ns(void)
+
+static void free_mnt_ns(struct mnt_namespace *ns)
+{
+	proc_free_inum(ns->proc_inum);
+	put_user_ns(ns->user_ns);
+	kfree(ns);
+}
+
+/*
+ * Assign a sequence number so we can detect when we attempt to bind
+ * mount a reference to an older mount namespace into the current
+ * mount namespace, preventing reference counting loops.  A 64bit
+ * number incrementing at 10Ghz will take 12,427 years to wrap which
+ * is effectively never, so we can ignore the possibility.
+ */
+static atomic64_t mnt_ns_seq = ATOMIC64_INIT(1);
+
+static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
 {
 	struct mnt_namespace *new_ns;
+	int ret;
 
 	new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
 	if (!new_ns)
 		return ERR_PTR(-ENOMEM);
+	ret = proc_alloc_inum(&new_ns->proc_inum);
+	if (ret) {
+		kfree(new_ns);
+		return ERR_PTR(ret);
+	}
+	new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
 	atomic_set(&new_ns->count, 1);
 	new_ns->root = NULL;
 	INIT_LIST_HEAD(&new_ns->list);
 	init_waitqueue_head(&new_ns->poll);
 	new_ns->event = 0;
+	new_ns->user_ns = get_user_ns(user_ns);
 	return new_ns;
 }
 
@@ -2229,24 +2292,28 @@
  * copied from the namespace of the passed in task structure.
  */
 static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
-		struct fs_struct *fs)
+		struct user_namespace *user_ns, struct fs_struct *fs)
 {
 	struct mnt_namespace *new_ns;
 	struct vfsmount *rootmnt = NULL, *pwdmnt = NULL;
 	struct mount *p, *q;
 	struct mount *old = mnt_ns->root;
 	struct mount *new;
+	int copy_flags;
 
-	new_ns = alloc_mnt_ns();
+	new_ns = alloc_mnt_ns(user_ns);
 	if (IS_ERR(new_ns))
 		return new_ns;
 
 	down_write(&namespace_sem);
 	/* First pass: copy the tree topology */
-	new = copy_tree(old, old->mnt.mnt_root, CL_COPY_ALL | CL_EXPIRE);
+	copy_flags = CL_COPY_ALL | CL_EXPIRE;
+	if (user_ns != mnt_ns->user_ns)
+		copy_flags |= CL_SHARED_TO_SLAVE;
+	new = copy_tree(old, old->mnt.mnt_root, copy_flags);
 	if (!new) {
 		up_write(&namespace_sem);
-		kfree(new_ns);
+		free_mnt_ns(new_ns);
 		return ERR_PTR(-ENOMEM);
 	}
 	new_ns->root = new;
@@ -2292,7 +2359,7 @@
 }
 
 struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
-		struct fs_struct *new_fs)
+		 struct user_namespace *user_ns, struct fs_struct *new_fs)
 {
 	struct mnt_namespace *new_ns;
 
@@ -2302,7 +2369,7 @@
 	if (!(flags & CLONE_NEWNS))
 		return ns;
 
-	new_ns = dup_mnt_ns(ns, new_fs);
+	new_ns = dup_mnt_ns(ns, user_ns, new_fs);
 
 	put_mnt_ns(ns);
 	return new_ns;
@@ -2314,7 +2381,7 @@
  */
 static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
 {
-	struct mnt_namespace *new_ns = alloc_mnt_ns();
+	struct mnt_namespace *new_ns = alloc_mnt_ns(&init_user_ns);
 	if (!IS_ERR(new_ns)) {
 		struct mount *mnt = real_mount(m);
 		mnt->mnt_ns = new_ns;
@@ -2455,7 +2522,7 @@
 	struct mount *new_mnt, *root_mnt;
 	int error;
 
-	if (!capable(CAP_SYS_ADMIN))
+	if (!ns_capable(current->nsproxy->mnt_ns->user_ns, CAP_SYS_ADMIN))
 		return -EPERM;
 
 	error = user_path_dir(new_root, &new);
@@ -2537,8 +2604,13 @@
 	struct vfsmount *mnt;
 	struct mnt_namespace *ns;
 	struct path root;
+	struct file_system_type *type;
 
-	mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
+	type = get_fs_type("rootfs");
+	if (!type)
+		panic("Can't find rootfs type");
+	mnt = vfs_kern_mount(type, 0, "rootfs", NULL);
+	put_filesystem(type);
 	if (IS_ERR(mnt))
 		panic("Can't create rootfs");
 
@@ -2601,7 +2673,7 @@
 	br_write_unlock(vfsmount_lock);
 	up_write(&namespace_sem);
 	release_mounts(&umount_list);
-	kfree(ns);
+	free_mnt_ns(ns);
 }
 
 struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
@@ -2633,3 +2705,71 @@
 {
 	return check_mnt(real_mount(mnt));
 }
+
+static void *mntns_get(struct task_struct *task)
+{
+	struct mnt_namespace *ns = NULL;
+	struct nsproxy *nsproxy;
+
+	rcu_read_lock();
+	nsproxy = task_nsproxy(task);
+	if (nsproxy) {
+		ns = nsproxy->mnt_ns;
+		get_mnt_ns(ns);
+	}
+	rcu_read_unlock();
+
+	return ns;
+}
+
+static void mntns_put(void *ns)
+{
+	put_mnt_ns(ns);
+}
+
+static int mntns_install(struct nsproxy *nsproxy, void *ns)
+{
+	struct fs_struct *fs = current->fs;
+	struct mnt_namespace *mnt_ns = ns;
+	struct path root;
+
+	if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) ||
+		!nsown_capable(CAP_SYS_CHROOT))
+		return -EINVAL;
+
+	if (fs->users != 1)
+		return -EINVAL;
+
+	get_mnt_ns(mnt_ns);
+	put_mnt_ns(nsproxy->mnt_ns);
+	nsproxy->mnt_ns = mnt_ns;
+
+	/* Find the root */
+	root.mnt    = &mnt_ns->root->mnt;
+	root.dentry = mnt_ns->root->mnt.mnt_root;
+	path_get(&root);
+	while(d_mountpoint(root.dentry) && follow_down_one(&root))
+		;
+
+	/* Update the pwd and root */
+	set_fs_pwd(fs, &root);
+	set_fs_root(fs, &root);
+
+	path_put(&root);
+	return 0;
+}
+
+static unsigned int mntns_inum(void *ns)
+{
+	struct mnt_namespace *mnt_ns = ns;
+	return mnt_ns->proc_inum;
+}
+
+const struct proc_ns_operations mntns_operations = {
+	.name		= "mnt",
+	.type		= CLONE_NEWNS,
+	.get		= mntns_get,
+	.put		= mntns_put,
+	.install	= mntns_install,
+	.inum		= mntns_inum,
+};
diff --git a/fs/pnode.h b/fs/pnode.h
index 65c6097..3471ddf 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -22,6 +22,7 @@
 #define CL_COPY_ALL 		0x04
 #define CL_MAKE_SHARED 		0x08
 #define CL_PRIVATE 		0x10
+#define CL_SHARED_TO_SLAVE      0x20
 
 static inline void set_mnt_shared(struct mount *mnt)
 {
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 2edf34f..a1487e5 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -350,37 +350,39 @@
  * Return an inode number between PROC_DYNAMIC_FIRST and
  * 0xffffffff, or zero on failure.
  */
-static unsigned int get_inode_number(void)
+int proc_alloc_inum(unsigned int *inum)
 {
 	unsigned int i;
 	int error;
 
 retry:
-	if (ida_pre_get(&proc_inum_ida, GFP_KERNEL) == 0)
-		return 0;
+	if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL))
+		return -ENOMEM;
 
-	spin_lock(&proc_inum_lock);
+	spin_lock_irq(&proc_inum_lock);
 	error = ida_get_new(&proc_inum_ida, &i);
-	spin_unlock(&proc_inum_lock);
+	spin_unlock_irq(&proc_inum_lock);
 	if (error == -EAGAIN)
 		goto retry;
 	else if (error)
-		return 0;
+		return error;
 
 	if (i > UINT_MAX - PROC_DYNAMIC_FIRST) {
-		spin_lock(&proc_inum_lock);
+		spin_lock_irq(&proc_inum_lock);
 		ida_remove(&proc_inum_ida, i);
-		spin_unlock(&proc_inum_lock);
-		return 0;
+		spin_unlock_irq(&proc_inum_lock);
+		return -ENOSPC;
 	}
-	return PROC_DYNAMIC_FIRST + i;
+	*inum = PROC_DYNAMIC_FIRST + i;
+	return 0;
 }
 
-static void release_inode_number(unsigned int inum)
+void proc_free_inum(unsigned int inum)
 {
-	spin_lock(&proc_inum_lock);
+	unsigned long flags;
+	spin_lock_irqsave(&proc_inum_lock, flags);
 	ida_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST);
-	spin_unlock(&proc_inum_lock);
+	spin_unlock_irqrestore(&proc_inum_lock, flags);
 }
 
 static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)
@@ -554,13 +556,12 @@
 
 static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
 {
-	unsigned int i;
 	struct proc_dir_entry *tmp;
+	int ret;
 	
-	i = get_inode_number();
-	if (i == 0)
-		return -EAGAIN;
-	dp->low_ino = i;
+	ret = proc_alloc_inum(&dp->low_ino);
+	if (ret)
+		return ret;
 
 	if (S_ISDIR(dp->mode)) {
 		if (dp->proc_iops == NULL) {
@@ -765,7 +766,7 @@
 
 static void free_proc_entry(struct proc_dir_entry *de)
 {
-	release_inode_number(de->low_ino);
+	proc_free_inum(de->low_ino);
 
 	if (S_ISLNK(de->mode))
 		kfree(de->data);
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 205c922..b1f55ae 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -31,6 +31,7 @@
 	struct proc_dir_entry *de;
 	struct ctl_table_header *head;
 	const struct proc_ns_operations *ns_ops;
+	void *ns;
 
 	truncate_inode_pages(&inode->i_data, 0);
 	end_writeback(inode);
@@ -49,8 +50,9 @@
 	}
 	/* Release any associated namespace */
 	ns_ops = PROC_I(inode)->ns_ops;
-	if (ns_ops && ns_ops->put)
-		ns_ops->put(PROC_I(inode)->ns);
+	ns = PROC_I(inode)->ns;
+	if (ns_ops && ns)
+		ns_ops->put(ns);
 }
 
 static struct kmem_cache * proc_inode_cachep;
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index 0d9e23a..08dfd6a 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -24,12 +24,165 @@
 #ifdef CONFIG_IPC_NS
 	&ipcns_operations,
 #endif
+#ifdef CONFIG_PID_NS
+	&pidns_operations,
+#endif
+	&mntns_operations,
 };
 
 static const struct file_operations ns_file_operations = {
 	.llseek		= no_llseek,
 };
 
+static const struct inode_operations ns_inode_operations = {
+	.setattr	= proc_setattr,
+};
+
+static int ns_delete_dentry(const struct dentry *dentry)
+{
+	/* Don't cache namespace inodes when not in use */
+	return 1;
+}
+
+static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
+{
+	struct inode *inode = dentry->d_inode;
+	const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
+
+	return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
+		ns_ops->name, inode->i_ino);
+}
+
+const struct dentry_operations ns_dentry_operations =
+{
+	.d_delete	= ns_delete_dentry,
+	.d_dname	= ns_dname,
+};
+
+static struct dentry *proc_ns_get_dentry(struct super_block *sb,
+	struct task_struct *task, const struct proc_ns_operations *ns_ops)
+{
+	struct dentry *dentry, *result;
+	struct inode *inode;
+	struct proc_inode *ei;
+	struct qstr qname = { .name = "", };
+	void *ns;
+
+	ns = ns_ops->get(task);
+	if (!ns)
+		return ERR_PTR(-ENOENT);
+
+	dentry = d_alloc_pseudo(sb, &qname);
+	if (!dentry) {
+		ns_ops->put(ns);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	inode = iget_locked(sb, ns_ops->inum(ns));
+	if (!inode) {
+		dput(dentry);
+		ns_ops->put(ns);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	ei = PROC_I(inode);
+	if (inode->i_state & I_NEW) {
+		inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+		inode->i_op = &ns_inode_operations;
+		inode->i_mode = S_IFREG | S_IRUGO;
+		inode->i_fop = &ns_file_operations;
+		ei->ns_ops = ns_ops;
+		ei->ns = ns;
+		unlock_new_inode(inode);
+	} else {
+		ns_ops->put(ns);
+	}
+
+	d_set_d_op(dentry, &ns_dentry_operations);
+	result = d_instantiate_unique(dentry, inode);
+	if (result) {
+		dput(dentry);
+		dentry = result;
+	}
+
+	return dentry;
+}
+
+static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+	struct inode *inode = dentry->d_inode;
+	struct super_block *sb = inode->i_sb;
+	struct proc_inode *ei = PROC_I(inode);
+	struct task_struct *task;
+	struct dentry *ns_dentry;
+	void *error = ERR_PTR(-EACCES);
+
+	task = get_proc_task(inode);
+	if (!task)
+		goto out;
+
+	if (!ptrace_may_access(task, PTRACE_MODE_READ))
+		goto out_put_task;
+
+	ns_dentry = proc_ns_get_dentry(sb, task, ei->ns_ops);
+	if (IS_ERR(ns_dentry)) {
+		error = ERR_CAST(ns_dentry);
+		goto out_put_task;
+	}
+
+	dput(nd->path.dentry);
+	nd->path.dentry = ns_dentry;
+	error = NULL;
+
+out_put_task:
+	put_task_struct(task);
+out:
+	return error;
+}
+
+static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen)
+{
+	struct inode *inode = dentry->d_inode;
+	struct proc_inode *ei = PROC_I(inode);
+	const struct proc_ns_operations *ns_ops = ei->ns_ops;
+	struct task_struct *task;
+	void *ns;
+	char name[50];
+	int len = -EACCES;
+
+	task = get_proc_task(inode);
+	if (!task)
+		goto out;
+
+	if (!ptrace_may_access(task, PTRACE_MODE_READ))
+		goto out_put_task;
+
+	len = -ENOENT;
+	ns = ns_ops->get(task);
+	if (!ns)
+		goto out_put_task;
+
+	snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns_ops->inum(ns));
+	len = strlen(name);
+
+	if (len > buflen)
+		len = buflen;
+	if (copy_to_user(buffer, name, len))
+		len = -EFAULT;
+
+	ns_ops->put(ns);
+out_put_task:
+	put_task_struct(task);
+out:
+	return len;
+}
+
+static const struct inode_operations proc_ns_link_inode_operations = {
+	.readlink	= proc_ns_readlink,
+	.follow_link	= proc_ns_follow_link,
+	.setattr	= proc_setattr,
+};
+
 static struct dentry *proc_ns_instantiate(struct inode *dir,
 	struct dentry *dentry, struct task_struct *task, const void *ptr)
 {
@@ -37,21 +190,15 @@
 	struct inode *inode;
 	struct proc_inode *ei;
 	struct dentry *error = ERR_PTR(-ENOENT);
-	void *ns;
 
 	inode = proc_pid_make_inode(dir->i_sb, task);
 	if (!inode)
 		goto out;
 
-	ns = ns_ops->get(task);
-	if (!ns)
-		goto out_iput;
-
 	ei = PROC_I(inode);
-	inode->i_mode = S_IFREG|S_IRUSR;
-	inode->i_fop  = &ns_file_operations;
-	ei->ns_ops    = ns_ops;
-	ei->ns	      = ns;
+	inode->i_mode = S_IFLNK|S_IRWXUGO;
+	inode->i_op = &proc_ns_link_inode_operations;
+	ei->ns_ops = ns_ops;
 
 	d_set_d_op(dentry, &pid_dentry_operations);
 	d_add(dentry, inode);
@@ -60,9 +207,6 @@
 		error = NULL;
 out:
 	return error;
-out_iput:
-	iput(inode);
-	goto out;
 }
 
 static int proc_ns_fill_cache(struct file *filp, void *dirent,
@@ -89,10 +233,6 @@
 	if (!task)
 		goto out_no_task;
 
-	ret = -EPERM;
-	if (!ptrace_may_access(task, PTRACE_MODE_READ))
-		goto out;
-
 	ret = 0;
 	i = filp->f_pos;
 	switch (i) {
@@ -152,10 +292,6 @@
 	if (!task)
 		goto out_no_task;
 
-	error = ERR_PTR(-EPERM);
-	if (!ptrace_may_access(task, PTRACE_MODE_READ))
-		goto out;
-
 	last = &ns_entries[ARRAY_SIZE(ns_entries)];
 	for (entry = ns_entries; entry < last; entry++) {
 		if (strlen((*entry)->name) != len)
@@ -163,7 +299,6 @@
 		if (!memcmp(dentry->d_name.name, (*entry)->name, len))
 			break;
 	}
-	error = ERR_PTR(-ENOENT);
 	if (entry == last)
 		goto out;
 
@@ -198,3 +333,7 @@
 	return ERR_PTR(-EINVAL);
 }
 
+bool proc_ns_inode(struct inode *inode)
+{
+	return inode->i_fop == &ns_file_operations;
+}
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 7396e15..be929a1 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -212,6 +212,7 @@
 header-y += ip.h
 header-y += ip6_tunnel.h
 header-y += ip_vs.h
+header-y += ipa_qmi_service_v01.h
 header-y += ipc.h
 header-y += ipmi.h
 header-y += ipmi_msgdefs.h
@@ -337,6 +338,7 @@
 header-y += reiserfs_xattr.h
 header-y += resource.h
 header-y += rfkill.h
+header-y += rmnet_ipa_fd_ioctl.h
 header-y += romfs_fs.h
 header-y += rose.h
 header-y += route.h
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 6181c69..71dbe3d 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1836,6 +1836,13 @@
 struct file_system_type {
 	const char *name;
 	int fs_flags;
+#define FS_REQUIRES_DEV                1
+#define FS_BINARY_MOUNTDATA    2
+#define FS_HAS_SUBTYPE         4
+#define FS_USERNS_MOUNT                8       /* Can be mounted by userns root */
+#define FS_USERNS_DEV_MOUNT    16 /* A userns mount does not imply MNT_NODEV */
+#define FS_REVAL_DOT           16384   /* Check the paths ".", ".." for staleness */
+#define FS_RENAME_DOES_D_MOVE  32768   /* FS will handle d_move() during rename() internally. */
 	struct dentry *(*mount) (struct file_system_type *, int,
 		       const char *, void *);
 	void (*kill_sb) (struct super_block *);
diff --git a/include/linux/ipa_qmi_service_v01.h b/include/linux/ipa_qmi_service_v01.h
new file mode 100755
index 0000000..b93e61d
--- /dev/null
+++ b/include/linux/ipa_qmi_service_v01.h
@@ -0,0 +1,1392 @@
+/*
+ * This header file defines the types and structures that were defined in
+ * ipa. It contains the constant values defined, enums, structures,
+ * messages, and service message IDs (in that order) Structures that were
+ * defined in the IDL as messages contain mandatory elements, optional
+ * elements, a combination of mandatory and optional elements (mandatory
+ * always come before optionals in the structure), or nothing (null message)
+
+ * An optional element in a message is preceded by a uint8_t value that must be
+ * set to true if the element is going to be included. When decoding a received
+ * message, the uint8_t values will be set to true or false by the decode
+ * routine, and should be checked before accessing the values that they
+ * correspond to.
+
+ * Variable sized arrays are defined as static sized arrays with an unsigned
+ * integer (32 bit) preceding it that must be set to the number of elements
+ * in the array that are valid. For Example:
+
+ * uint32_t test_opaque_len;
+ * uint8_t test_opaque[16];
+
+ * If only 4 elements are added to test_opaque[] then test_opaque_len must be
+ * set to 4 before sending the message.  When decoding, the _len value is set
+ * by the decode routine and should be checked so that the correct number of
+ * elements in the array will be accessed.
+ */
+#ifndef IPA_QMI_SERVICE_V01_H
+#define IPA_QMI_SERVICE_V01_H
+
+#define QMI_IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS_V01 2
+#define QMI_IPA_IPFLTR_NUM_MEQ_32_EQNS_V01 2
+#define QMI_IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS_V01 2
+#define QMI_IPA_IPFLTR_NUM_MEQ_128_EQNS_V01 2
+#define QMI_IPA_MAX_FILTERS_V01 64
+#define QMI_IPA_MAX_PIPES_V01 20
+#define QMI_IPA_MAX_APN_V01 8
+
+#define IPA_INT_MAX	((int)(~0U>>1))
+#define IPA_INT_MIN	(-IPA_INT_MAX - 1)
+
+/* IPA definition as msm_qmi_interface.h */
+
+enum ipa_qmi_result_type_v01 {
+	/* To force a 32 bit signed enum. Do not change or use*/
+	IPA_QMI_RESULT_TYPE_MIN_ENUM_VAL_V01 = IPA_INT_MIN,
+	IPA_QMI_RESULT_SUCCESS_V01 = 0,
+	IPA_QMI_RESULT_FAILURE_V01 = 1,
+	IPA_QMI_RESULT_TYPE_MAX_ENUM_VAL_V01 = IPA_INT_MAX,
+};
+
+enum ipa_qmi_error_type_v01 {
+	/* To force a 32 bit signed enum. Do not change or use*/
+	IPA_QMI_ERROR_TYPE_MIN_ENUM_VAL_V01 = IPA_INT_MIN,
+	IPA_QMI_ERR_NONE_V01 = 0x0000,
+	IPA_QMI_ERR_MALFORMED_MSG_V01 = 0x0001,
+	IPA_QMI_ERR_NO_MEMORY_V01 = 0x0002,
+	IPA_QMI_ERR_INTERNAL_V01 = 0x0003,
+	IPA_QMI_ERR_CLIENT_IDS_EXHAUSTED_V01 = 0x0005,
+	IPA_QMI_ERR_INVALID_ID_V01 = 0x0029,
+	IPA_QMI_ERR_ENCODING_V01 = 0x003A,
+	IPA_QMI_ERR_INCOMPATIBLE_STATE_V01 = 0x005A,
+	IPA_QMI_ERR_NOT_SUPPORTED_V01 = 0x005E,
+	IPA_QMI_ERROR_TYPE_MAX_ENUM_VAL_V01 = IPA_INT_MAX,
+};
+
+struct ipa_qmi_response_type_v01 {
+	enum ipa_qmi_result_type_v01 result;
+	enum ipa_qmi_error_type_v01 error;
+};
+
+enum ipa_platform_type_enum_v01 {
+	IPA_PLATFORM_TYPE_ENUM_MIN_ENUM_VAL_V01 =
+	-2147483647, /* To force a 32 bit signed enum.  Do not change or use */
+	QMI_IPA_PLATFORM_TYPE_INVALID_V01 = 0,
+	/*  Invalid platform identifier */
+	QMI_IPA_PLATFORM_TYPE_TN_V01 = 1,
+	/*  Platform identifier -	Data card device */
+	QMI_IPA_PLATFORM_TYPE_LE_V01 = 2,
+	/*  Platform identifier -	Data router device */
+	QMI_IPA_PLATFORM_TYPE_MSM_ANDROID_V01 = 3,
+	/*  Platform identifier -	MSM device with Android HLOS */
+	QMI_IPA_PLATFORM_TYPE_MSM_WINDOWS_V01 = 4,
+	/*  Platform identifier -	MSM device with Windows HLOS */
+	QMI_IPA_PLATFORM_TYPE_MSM_QNX_V01 = 5,
+	/*  Platform identifier -	MSM device with QNX HLOS */
+	IPA_PLATFORM_TYPE_ENUM_MAX_ENUM_VAL_V01 = 2147483647
+	/* To force a 32 bit signed enum.  Do not change or use */
+};
+
+struct ipa_hdr_tbl_info_type_v01 {
+	uint32_t modem_offset_start;
+	/*	Offset from the start of IPA Shared memory from which
+	 *	modem driver may insert header table entries.
+	 */
+	uint32_t modem_offset_end;
+	/*	Offset from the start of IPA shared mem beyond which modem
+	 *	driver shall not insert header table entries. The space
+	 *	available for the modem driver shall include the
+	 *	modem_offset_start and modem_offset_end.
+	 */
+};  /* Type */
+
+struct ipa_route_tbl_info_type_v01 {
+	uint32_t route_tbl_start_addr;
+	/*	Identifies the start of the routing table. Denotes the offset
+	 *	from the start of the IPA Shared Mem
+	 */
+
+	uint32_t num_indices;
+	/*	Number of indices (starting from 0) that is being allocated to
+	 *	the modem. The number indicated here is also included in the
+	 *	allocation. The value of num_indices shall not exceed 31
+	 *	(5 bits used to specify the routing table index), unless there
+	 *	is a change in the hardware.
+	 */
+};  /* Type */
+
+struct ipa_modem_mem_info_type_v01 {
+
+	uint32_t block_start_addr;
+	/*	Identifies the start of the memory block allocated for the
+	 *	modem. Denotes the offset from the start of the IPA Shared Mem
+	 */
+
+	uint32_t size;
+	/*	Size of the block allocated for the modem driver */
+};  /* Type */
+
+struct ipa_hdr_proc_ctx_tbl_info_type_v01 {
+
+	uint32_t modem_offset_start;
+	/*  Offset from the start of IPA shared memory from which the modem
+	 *	driver may insert header processing context table entries.
+	 */
+
+	uint32_t modem_offset_end;
+	/*  Offset from the start of IPA shared memory beyond which the modem
+	 *	driver may not insert header proc table entries. The space
+	 *	available for the modem driver includes modem_offset_start and
+	 *	modem_offset_end.
+	 */
+};  /* Type */
+
+struct ipa_zip_tbl_info_type_v01 {
+
+	uint32_t modem_offset_start;
+	/*  Offset from the start of IPA shared memory from which the modem
+	 *	driver may insert compression/decompression command entries.
+	 */
+
+	uint32_t modem_offset_end;
+	/*  Offset from the start of IPA shared memory beyond which the modem
+	 *	driver may not insert compression/decompression command entries.
+	 *	The space available for the modem driver includes
+	 *  modem_offset_start and modem_offset_end.
+	 */
+};  /* Type */
+
+/** Request Message; Requests the modem IPA driver to perform initializtion */
+struct ipa_init_modem_driver_req_msg_v01 {
+
+	/* Optional */
+	/*  Platform info */
+	uint8_t platform_type_valid;  /**< Must be set to true if platform_type
+	is being passed */
+	enum ipa_platform_type_enum_v01 platform_type;
+	/*   Provides information about the platform (ex. TN/MN/LE/MSM,etc) */
+
+	/* Optional */
+	/*  Header table info */
+	uint8_t hdr_tbl_info_valid;
+	/* Must be set to true if hdr_tbl_info is being passed */
+	struct ipa_hdr_tbl_info_type_v01 hdr_tbl_info;
+	/*	Provides information about the header table */
+
+	/* Optional */
+	/*  IPV4 Routing table info */
+	uint8_t v4_route_tbl_info_valid;
+	/* Must be set to true if v4_route_tbl_info is being passed */
+	struct ipa_route_tbl_info_type_v01 v4_route_tbl_info;
+	/*	Provides information about the IPV4 routing table */
+
+	/* Optional */
+	/*  IPV6 Routing table info */
+	uint8_t v6_route_tbl_info_valid;  /**< Must be set to true if
+	v6_route_tbl_info is being passed */
+	struct ipa_route_tbl_info_type_v01 v6_route_tbl_info;
+	/*	Provides information about the IPV6 routing table */
+
+	/* Optional */
+	/*  IPV4 Filter table start address */
+	uint8_t v4_filter_tbl_start_addr_valid;  /**< Must be set to true
+	if v4_filter_tbl_start_addr is being passed */
+	uint32_t v4_filter_tbl_start_addr;
+	/*	Provides information about the starting address of IPV4 filter
+	 *	tableDenotes the offset from the start of the IPA Shared Mem
+	 */
+
+	/* Optional */
+	/* IPV6 Filter table start address */
+	uint8_t v6_filter_tbl_start_addr_valid;
+	/* Must be set to true if v6_filter_tbl_start_addr is being passed */
+	uint32_t v6_filter_tbl_start_addr;
+	/*	Provides information about the starting address of IPV6 filter
+	 *	table Denotes the offset from the start of the IPA Shared Mem
+	 */
+
+	/* Optional */
+	/*  Modem memory block */
+	uint8_t modem_mem_info_valid;
+	/* Must be set to true if modem_mem_info is being passed */
+	struct ipa_modem_mem_info_type_v01 modem_mem_info;
+	/*  Provides information about the start address and the size of
+	 *	the memory block that is being allocated to the modem driver.
+	 *	Denotes the physical address
+	 */
+
+	/* Optional */
+	/*  Destination end point for control commands from modem */
+	uint8_t ctrl_comm_dest_end_pt_valid;  /**< Must be set to true if
+	ctrl_comm_dest_end_pt is being passed */
+	uint32_t ctrl_comm_dest_end_pt;
+	/*  Provides information about the destination end point on the
+	 *	application processor to which the modem driver can send
+	 *	control commands. The value of this parameter cannot exceed
+	 *	19 since IPA only supports 20 end points.
+	 */
+
+	/* Optional */
+	/*  Modem Bootup Information */
+	uint8_t is_ssr_bootup_valid;  /**< Must be set to true if
+	is_ssr_bootup is being passed */
+	uint8_t is_ssr_bootup;
+	/*	Specifies whether the modem is booting up after a modem only
+	 *	sub-system restart or not. This will let the modem driver
+	 *	know that it doesn't have to reinitialize some of the HW
+	 *	blocks because IPA has not been reset since the previous
+	 *	initialization.
+	 */
+
+	/* Optional */
+	/*  Header Processing Context Table Information */
+	uint8_t hdr_proc_ctx_tbl_info_valid;
+	/* Must be set to true if hdr_proc_ctx_tbl_info is being passed */
+	struct ipa_hdr_proc_ctx_tbl_info_type_v01 hdr_proc_ctx_tbl_info;
+	/* Provides information about the header processing context table.
+	*/
+
+	/* Optional */
+	/*  Compression Decompression Table Information */
+	uint8_t zip_tbl_info_valid;
+	/* Must be set to true if zip_tbl_info is being passed */
+	struct ipa_zip_tbl_info_type_v01 zip_tbl_info;
+	/* Provides information about the header processing context table.
+	*/
+};  /* Message */
+
+/* Response Message; Requests the modem IPA driver about initializtion */
+struct ipa_init_modem_driver_resp_msg_v01 {
+	/* Mandatory */
+	/*  Result Code */
+	struct ipa_qmi_response_type_v01 resp;
+	/* Standard response type.*/
+
+	/* Optional */
+	/* Destination end point for control commands from master driver */
+	uint8_t ctrl_comm_dest_end_pt_valid;
+	/* Must be set to true if ctrl_comm_dest_ep is being passed */
+	uint32_t ctrl_comm_dest_end_pt;
+	/*	Provides information about the destination end point on the
+	 *	modem processor to which the master driver can send control
+	 *	commands. The value of this parameter cannot exceed 19 since
+	 *	IPA only supports 20 end points. This field is looked at only
+	 *	if the result in TLV RESULT_CODE is	QMI_RESULT_SUCCESS
+	 */
+
+	/* Optional */
+	/*  Default end point */
+	uint8_t default_end_pt_valid;
+	/* Must be set to true if default_end_pt is being passed */
+	uint32_t default_end_pt;
+	/*  Provides information about the default end point. The master
+	 *	driver may or may not set the register in the hardware with
+	 *	this value. The value of this parameter cannot exceed 19
+	 *	since IPA only supports 20 end points. This field is looked
+	 *	at only if the result in TLV RESULT_CODE is QMI_RESULT_SUCCESS
+	 */
+};  /* Message */
+
+
+/*	Request Message; This is the message that is exchanged between the
+ *	control point and the service in order to register for indications.
+ */
+struct ipa_indication_reg_req_msg_v01 {
+	/* Optional */
+	/*  Master driver initialization completion */
+	uint8_t master_driver_init_complete_valid;
+	/* Must be set to true if master_driver_init_complete is being passed */
+	uint8_t master_driver_init_complete;
+	/*  If set to TRUE, this field indicates that the client is
+	 *	interested in getting indications about the completion
+	 *	of the initialization sequence of the master driver.
+	 *	Setting this field in the request message makes sense
+	 *	only when the QMI_IPA_INDICATION_REGISTER_REQ is being
+	 *	originated from the modem driver
+	 */
+
+	/* Optional */
+	/*  Data Usage Quota Reached */
+	uint8_t data_usage_quota_reached_valid;
+	/*  Must be set to true if data_usage_quota_reached is being passed */
+	uint8_t data_usage_quota_reached;
+	/*  If set to TRUE, this field indicates that the client wants to
+	 *  receive indications about reaching the data usage quota that
+	 *  previously set via QMI_IPA_SET_DATA_USAGE_QUOTA. Setting this field
+	 *  in the request message makes sense only when the
+	 *  QMI_IPA_INDICATION_REGISTER_REQ is being originated from the Master
+	 *  driver
+	 */
+};  /* Message */
+
+
+/* Response Message; This is the message that is exchanged between the
+ *	control point and the service in order to register for indications.
+ */
+struct ipa_indication_reg_resp_msg_v01 {
+	/* Mandatory */
+	/*  Result Code */
+	struct ipa_qmi_response_type_v01 resp;
+	/**<   Standard response type.*/
+};  /* Message */
+
+
+/*	Indication Message; Indication sent to the Modem IPA driver from
+ *	master IPA driver about initialization being complete.
+ */
+struct ipa_master_driver_init_complt_ind_msg_v01 {
+	/* Mandatory */
+	/*  Master driver initialization completion status */
+	struct ipa_qmi_response_type_v01 master_driver_init_status;
+	/*	Indicates the status of initialization. If everything went
+	 *	as expected, this field is set to SUCCESS. ERROR is set
+	 *	otherwise. Extended error info may be used to convey
+	 *	additional information about the error
+	 */
+};  /* Message */
+
+struct ipa_ipfltr_range_eq_16_type_v01 {
+	uint8_t offset;
+	/*	Specifies the offset from the IHL (Internet Header length) */
+
+	uint16_t range_low;
+	/*	Specifies the lower bound of the range */
+
+	uint16_t range_high;
+	/*	Specifies the upper bound of the range */
+};  /* Type */
+
+struct ipa_ipfltr_mask_eq_32_type_v01 {
+	uint8_t offset;
+	/*	Specifies the offset either from IHL or from the start of
+	 *	the IP packet. This depends on the equation that this structure
+	 *	is used in.
+	 */
+
+	uint32_t mask;
+	/*	Specifies the mask that has to be used in the comparison.
+	 *	The field is ANDed with the mask and compared against the value.
+	 */
+
+	uint32_t value;
+	/*	Specifies the 32 bit value that used in the comparison. */
+};  /* Type */
+
+struct ipa_ipfltr_eq_16_type_v01 {
+	uint8_t offset;
+	/*  Specifies the offset into the packet */
+
+	uint16_t value;
+	/* Specifies the 16 bit value that should be used in the comparison. */
+};  /* Type */
+
+struct ipa_ipfltr_eq_32_type_v01 {
+	uint8_t offset;
+	/* Specifies the offset into the packet */
+
+	uint32_t value;
+	/* Specifies the 32 bit value that should be used in the comparison. */
+};  /* Type */
+
+struct ipa_ipfltr_mask_eq_128_type_v01 {
+	uint8_t offset;
+	/* Specifies the offset into the packet */
+
+	uint8_t mask[16];
+	/*  Specifies the mask that has to be used in the comparison.
+	 *	The field is ANDed with the mask and compared against the value.
+	 */
+
+	uint8_t value[16];
+	/* Specifies the 128 bit value that should be used in the comparison. */
+};  /* Type */
+
+
+struct ipa_filter_rule_type_v01 {
+	uint16_t rule_eq_bitmap;
+	/* 16-bit Bitmask to indicate how many eqs are valid in this rule */
+
+	uint8_t tos_eq_present;
+	/* Specifies if a type of service check rule is present */
+
+	uint8_t tos_eq;
+	/* The value to check against the type of service (ipv4) field */
+
+	uint8_t protocol_eq_present;
+	/* Specifies if a protocol check rule is present */
+
+	uint8_t protocol_eq;
+	/* The value to check against the protocol field */
+
+	uint8_t num_ihl_offset_range_16;
+	/*  The number of 16 bit range check rules at the location
+	 *	determined by IP header length plus a given offset offset
+	 *	in this rule. See the definition of the ipa_filter_range_eq_16
+	 *	for better understanding. The value of this field cannot exceed
+	 *	IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS which is set as 2
+	 */
+
+	struct ipa_ipfltr_range_eq_16_type_v01
+		ihl_offset_range_16[QMI_IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS_V01];
+	/*	Array of the registered IP header length offset 16 bit range
+	 *	check rules.
+	 */
+
+	uint8_t num_offset_meq_32;
+	/*  The number of 32 bit masked comparison rules present
+	 *  in this rule
+	 */
+
+	struct ipa_ipfltr_mask_eq_32_type_v01
+		offset_meq_32[QMI_IPA_IPFLTR_NUM_MEQ_32_EQNS_V01];
+	/*  An array of all the possible 32bit masked comparison rules
+	 *	in this rule
+	 */
+
+	uint8_t tc_eq_present;
+	/*  Specifies if the traffic class rule is present in this rule */
+
+	uint8_t tc_eq;
+	/* The value against which the IPV4 traffic class field has to
+		be checked */
+
+	uint8_t flow_eq_present;
+	/* Specifies if the "flow equals" rule is present in this rule */
+
+	uint32_t flow_eq;
+	/* The value against which the IPV6 flow field has to be checked */
+
+	uint8_t ihl_offset_eq_16_present;
+	/*	Specifies if there is a 16 bit comparison required at the
+	 *	location in	the packet determined by "Intenet Header length
+	 *	+ specified offset"
+	 */
+
+	struct ipa_ipfltr_eq_16_type_v01 ihl_offset_eq_16;
+	/* The 16 bit comparison equation */
+
+	uint8_t ihl_offset_eq_32_present;
+	/*	Specifies if there is a 32 bit comparison required at the
+	 *	location in the packet determined by "Intenet Header length
+	 *	+ specified offset"
+	 */
+
+	struct ipa_ipfltr_eq_32_type_v01 ihl_offset_eq_32;
+	/*	The 32 bit comparison equation */
+
+	uint8_t num_ihl_offset_meq_32;
+	/*	The number of 32 bit masked comparison equations in this
+	 *	rule. The location of the packet to be compared is
+	 *	determined by the IP Header length + the give offset
+	 */
+
+	struct ipa_ipfltr_mask_eq_32_type_v01
+		ihl_offset_meq_32[QMI_IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS_V01];
+	/*	Array of 32 bit masked comparison equations.
+	*/
+
+	uint8_t num_offset_meq_128;
+	/*	The number of 128 bit comparison equations in this rule */
+
+	struct ipa_ipfltr_mask_eq_128_type_v01
+		offset_meq_128[QMI_IPA_IPFLTR_NUM_MEQ_128_EQNS_V01];
+	/*	Array of 128 bit comparison equations. The location in the
+	 *	packet is determined by the specified offset
+	 */
+
+	uint8_t metadata_meq32_present;
+	/*  Boolean indicating if the 32 bit masked comparison equation
+	 *	is present or not. Comparison is done against the metadata
+	 *	in IPA. Metadata can either be extracted from the packet
+	 *	header or from the "metadata" register.
+	 */
+
+	struct ipa_ipfltr_mask_eq_32_type_v01
+			metadata_meq32;
+	/* The metadata  32 bit masked comparison equation */
+
+	uint8_t ipv4_frag_eq_present;
+	/* Specifies if the IPv4 Fragment equation is present in this rule */
+};  /* Type */
+
+
+enum ipa_ip_type_enum_v01 {
+	IPA_IP_TYPE_ENUM_MIN_ENUM_VAL_V01 = -2147483647,
+	/* To force a 32 bit signed enum.  Do not change or use*/
+	QMI_IPA_IP_TYPE_INVALID_V01 = 0,
+	/*  Invalid IP type identifier */
+	QMI_IPA_IP_TYPE_V4_V01 = 1,
+	/*  IP V4 type */
+	QMI_IPA_IP_TYPE_V6_V01 = 2,
+	/*  IP V6 type */
+	QMI_IPA_IP_TYPE_V4V6_V01 = 3,
+	/*  Applies to both IP types */
+	IPA_IP_TYPE_ENUM_MAX_ENUM_VAL_V01 = 2147483647
+	/* To force a 32 bit signed enum.  Do not change or use*/
+};
+
+
+enum ipa_filter_action_enum_v01 {
+	IPA_FILTER_ACTION_ENUM_MIN_ENUM_VAL_V01 = -2147483647,
+	/* To force a 32 bit signed enum. Do not change or use */
+	QMI_IPA_FILTER_ACTION_INVALID_V01 = 0,
+	/*  Invalid action on filter hit */
+	QMI_IPA_FILTER_ACTION_SRC_NAT_V01 = 1,
+	/*  Pass packet to NAT block for Source NAT */
+	QMI_IPA_FILTER_ACTION_DST_NAT_V01 = 2,
+	/*  Pass packet to NAT block for Destination NAT */
+	QMI_IPA_FILTER_ACTION_ROUTING_V01 = 3,
+	/*  Pass packet to Routing block */
+	QMI_IPA_FILTER_ACTION_EXCEPTION_V01 = 4,
+	/*  Treat packet as exception and send to exception pipe */
+	IPA_FILTER_ACTION_ENUM_MAX_ENUM_VAL_V01 = 2147483647
+	/* To force a 32 bit signed enum.  Do not change or use*/
+};
+
+struct ipa_filter_spec_type_v01 {
+	uint32_t filter_spec_identifier;
+	/*	This field is used to identify a filter spec in the list
+	 *	of filter specs being sent from the client. This field
+	 *	is applicable only in the filter install request and response.
+	 */
+
+	enum ipa_ip_type_enum_v01 ip_type;
+	/*	This field identifies the IP type for which this rule is
+	 *	applicable. The driver needs to identify the filter table
+	 *	(V6 or V4) and this field is essential for that
+	 */
+
+	struct ipa_filter_rule_type_v01 filter_rule;
+	/*	This field specifies the rules in the filter spec. These rules
+	 *	are the ones that are matched against fields in the packet.
+	 */
+
+	enum ipa_filter_action_enum_v01 filter_action;
+	/*	This field specifies the action to be taken when a filter match
+	 *	occurs. The remote side should install this information into the
+	 *	hardware along with the filter equations.
+	 */
+
+	uint8_t is_routing_table_index_valid;
+	/*	Specifies whether the routing table index is present or not.
+	 *	If the action is "QMI_IPA_FILTER_ACTION_EXCEPTION", this
+	 *	parameter need not be provided.
+	 */
+
+	uint32_t route_table_index;
+	/*	This is the index in the routing table that should be used
+	 *	to route the packets if the filter rule is hit
+	 */
+
+	uint8_t is_mux_id_valid;
+	/*	Specifies whether the mux_id is valid */
+
+	uint32_t mux_id;
+	/*	This field identifies the QMAP MUX ID. As a part of QMAP
+	 *	protocol, several data calls may be multiplexed over the
+	 *	same physical transport channel. This identifier is used to
+	 *	identify one such data call. The maximum value for this
+	 *	identifier is 255.
+	 */
+};  /* Type */
+
+
+/*  Request Message; This is the message that is exchanged between the
+ *	control point and the service in order to request the installation
+ *	of filtering rules in the hardware block by the remote side.
+ */
+struct ipa_install_fltr_rule_req_msg_v01 {
+	/* Optional */
+	/*  IP type that this rule applies to
+	Filter specification to be installed in the hardware */
+	uint8_t filter_spec_list_valid;
+	/* Must be set to true if filter_spec_list is being passed */
+	uint32_t filter_spec_list_len;
+	/* Must be set to # of elements in filter_spec_list */
+	struct ipa_filter_spec_type_v01
+		filter_spec_list[QMI_IPA_MAX_FILTERS_V01];
+	/*	This structure defines the list of filters that have
+	 *		to be installed in the hardware. The driver installing
+	 *		these rules shall do so in the same order as specified
+	 *		in this list.
+	 */
+
+	/* Optional */
+	/*  Pipe index to intall rule */
+	uint8_t source_pipe_index_valid;
+	/* Must be set to true if source_pipe_index is being passed */
+	uint32_t source_pipe_index;
+	/*	This is the source pipe on which the filter rule is to be
+	 *	installed. The requestor may always not know the pipe
+	 *	indices. If not specified, the receiver shall install
+	 *	this rule on all the pipes that it controls through
+	 *	which data may be fed into IPA.
+	 */
+
+	/* Optional */
+	/*  Total number of IPv4 filters in the filter spec list */
+	uint8_t num_ipv4_filters_valid;
+	/* Must be set to true if num_ipv4_filters is being passed */
+	uint32_t num_ipv4_filters;
+	/*   Number of IPv4 rules included in filter spec list */
+
+	/* Optional */
+	/*  Total number of IPv6 filters in the filter spec list */
+	uint8_t num_ipv6_filters_valid;
+	/* Must be set to true if num_ipv6_filters is being passed */
+	uint32_t num_ipv6_filters;
+	/* Number of IPv6 rules included in filter spec list */
+
+	/* Optional */
+	/*  List of XLAT filter indices in the filter spec list */
+	uint8_t xlat_filter_indices_list_valid;
+	/* Must be set to true if xlat_filter_indices_list
+	 * is being passed
+	 */
+	uint32_t xlat_filter_indices_list_len;
+	/* Must be set to # of elements in xlat_filter_indices_list */
+	uint32_t xlat_filter_indices_list[QMI_IPA_MAX_FILTERS_V01];
+	/* List of XLAT filter indices. Filter rules at specified indices
+	 * will need to be modified by the receiver if the PDN is XLAT
+	 * before installing them on the associated IPA consumer pipe.
+	 */
+};  /* Message */
+
+struct ipa_filter_rule_identifier_to_handle_map_v01 {
+	uint32_t filter_spec_identifier;
+	/*	This field is used to identify a filter spec in the list of
+	 *	filter specs being sent from the client. This field is
+	 *	applicable only in the filter install request and response.
+	 */
+	uint32_t filter_handle;
+	/*  This field is used to identify a rule in any subsequent message.
+	 *	This is a value that is provided by the server to the control
+	 *	point
+	 */
+};  /* Type */
+
+/* Response Message; This is the message that is exchanged between the
+ * control point and the service in order to request the
+ * installation of filtering rules in the hardware block by
+ * the remote side.
+ */
+struct ipa_install_fltr_rule_resp_msg_v01 {
+	/* Mandatory */
+	/*  Result Code */
+	struct ipa_qmi_response_type_v01 resp;
+	/*	Standard response type.
+	 *	Standard response type. Contains the following data members:
+	 *	- qmi_result_type -- QMI_RESULT_SUCCESS or QMI_RESULT_FAILURE
+	 *	- qmi_error_type  -- Error code. Possible error code values are
+	 *	described in the error codes section of each message definition.
+	 */
+
+	/* Optional */
+	/*  Filter Handle list */
+	uint8_t filter_handle_list_valid;
+	/**< Must be set to true if filter_handle_list is being passed */
+	uint32_t filter_handle_list_len;
+	/* Must be set to # of elements in filter_handle_list */
+	struct ipa_filter_rule_identifier_to_handle_map_v01
+		filter_handle_list[QMI_IPA_MAX_FILTERS_V01];
+	/*  This is a list of handles returned to the control point.
+	 *	Each handle is mapped to the rule identifier that was
+	 *	specified in the request message. Any further reference
+	 *	to the rule is done using the filter handle
+	 */
+};  /* Message */
+
+struct ipa_filter_handle_to_index_map_v01 {
+	uint32_t filter_handle;
+	/*	This is a handle that was given to the remote client that
+	 *	requested the rule addition.
+	 */
+	uint32_t filter_index;
+	/*	This index denotes the location in a filter table, where the
+	 *	filter rule has been installed. The maximum value of this
+	 *	field is 64.
+	 */
+};  /* Type */
+
+/* Request Message; This is the message that is exchanged between the
+ * control point and the service in order to notify the remote driver
+ * about the installation of the filter rule supplied earlier by
+ * the remote driver
+ */
+struct ipa_fltr_installed_notif_req_msg_v01 {
+	/*	Mandatory	*/
+	/*  Pipe index	*/
+	uint32_t source_pipe_index;
+	/*	This is the source pipe on which the filter rule has been
+	 *	installed or was attempted to be installed
+	 */
+
+	/* Mandatory */
+	/*  Installation Status */
+	enum ipa_qmi_result_type_v01 install_status;
+	/*	This is the status of installation. If this indicates
+	 *	SUCCESS, other optional fields carry additional
+	 *	information
+	 */
+
+	/* Mandatory */
+	/*  List of filter indices */
+	uint32_t filter_index_list_len;
+	/* Must be set to # of elements in filter_index_list */
+	struct ipa_filter_handle_to_index_map_v01
+		filter_index_list[QMI_IPA_MAX_FILTERS_V01];
+	/*	This field provides the list of filter indices and the
+	 *	corresponding filter handle. If the installation_status
+	 *	indicates failure, then the filter indices shall be set
+	 *	to a reserve index (255)
+	 */
+
+	/* Optional */
+	/*  Embedded pipe index */
+	uint8_t embedded_pipe_index_valid;
+	/* Must be set to true if embedded_pipe_index is being passed */
+	uint32_t embedded_pipe_index;
+	/*	This index denotes the embedded pipe number on which a call to
+	 *	the same PDN has been made. If this field is set, it denotes
+	 *	that this is a use case where PDN sharing is happening. The
+	 *	embedded pipe is used to send data from the embedded client
+	 *	in the device
+	 */
+
+	/* Optional */
+	/*  Retain Header Configuration */
+	uint8_t retain_header_valid;
+	/* Must be set to true if retain_header is being passed */
+	uint8_t retain_header;
+	/*	This field indicates if the driver installing the rule has
+	 *	turned on the "retain header" bit. If this is true, the
+	 *	header that is removed by IPA is reinserted after the
+	 *	packet processing is completed.
+	 */
+
+	/* Optional */
+	/*  Embedded call Mux Id */
+	uint8_t embedded_call_mux_id_valid;
+	/**< Must be set to true if embedded_call_mux_id is being passed */
+	uint32_t embedded_call_mux_id;
+	/*	This identifies one of the many calls that have been originated
+	 *	on the embedded pipe. This is how we identify the PDN gateway
+	 *	to which traffic from the source pipe has to flow.
+	 */
+
+	/* Optional */
+	/*  Total number of IPv4 filters in the filter index list */
+	uint8_t num_ipv4_filters_valid;
+	/* Must be set to true if num_ipv4_filters is being passed */
+	uint32_t num_ipv4_filters;
+	/* Number of IPv4 rules included in filter index list */
+
+	/* Optional */
+	/*  Total number of IPv6 filters in the filter index list */
+	uint8_t num_ipv6_filters_valid;
+	/* Must be set to true if num_ipv6_filters is being passed */
+	uint32_t num_ipv6_filters;
+	/* Number of IPv6 rules included in filter index list */
+
+	/* Optional */
+	/*  Start index on IPv4 filters installed on source pipe */
+	uint8_t start_ipv4_filter_idx_valid;
+	/* Must be set to true if start_ipv4_filter_idx is being passed */
+	uint32_t start_ipv4_filter_idx;
+	/* Start index of IPv4 rules in filter index list */
+
+	/* Optional */
+	/*  Start index on IPv6 filters installed on source pipe */
+	uint8_t start_ipv6_filter_idx_valid;
+	/* Must be set to true if start_ipv6_filter_idx is being passed */
+	uint32_t start_ipv6_filter_idx;
+	/* Start index of IPv6 rules in filter index list */
+};  /* Message */
+
+/* Response Message; This is the message that is exchanged between the control
+ *	point and the service in order to notify the remote driver about the
+ *	installation of the filter rule supplied earlier by the remote driver
+ */
+struct ipa_fltr_installed_notif_resp_msg_v01 {
+	/* Mandatory */
+	/*  Result Code */
+	struct ipa_qmi_response_type_v01 resp;
+	/*	Standard response type */
+};  /* Message */
+
+/* Request Message; Notifies the remote driver of the need to clear the data
+ * path to prevent the IPA from being blocked at the head of the processing
+ * pipeline
+ */
+struct ipa_enable_force_clear_datapath_req_msg_v01 {
+	/* Mandatory */
+	/*  Pipe Mask */
+	uint32_t source_pipe_bitmask;
+	/* Set of consumer (source) pipes that must be clear of
+	 * active data transfers.
+	 */
+
+	/* Mandatory */
+	/* Request ID */
+	uint32_t request_id;
+	/* Identifies the ID of the request that is sent to the server
+	 * The same request ID is used in the message to remove the force_clear
+	 * request. The server is expected to keep track of the request ID and
+	 * the source_pipe_bitmask so that it can revert as needed
+	 */
+
+	/* Optional */
+	/*  Source Throttle State */
+	uint8_t throttle_source_valid;
+	/* Must be set to true if throttle_source is being passed */
+	uint8_t throttle_source;
+	/*  Specifies whether the server is to throttle the data from
+	 *	these consumer (source) pipes after clearing the exisiting
+	 *	data present in the IPA that were pulled from these pipes
+	 *	The server is expected to put all the source pipes in the
+	 *	source_pipe_bitmask in the same state
+	 */
+};  /* Message */
+
+/* Response Message; Notifies the remote driver of the need to clear the
+ * data path to prevent the IPA from being blocked at the head of the
+ * processing pipeline
+ */
+struct ipa_enable_force_clear_datapath_resp_msg_v01 {
+	/* Mandatory */
+	/*  Result Code */
+	struct ipa_qmi_response_type_v01 resp;
+	/* Standard response type */
+};  /* Message */
+
+/* Request Message; Notifies the remote driver that the forceful clearing
+ * of the data path can be lifted
+ */
+struct ipa_disable_force_clear_datapath_req_msg_v01 {
+	/* Mandatory */
+	/* Request ID */
+	uint32_t request_id;
+	/* Identifies the request that was sent to the server to
+	 * forcibly clear the data path. This request simply undoes
+	 * the operation done in that request
+	 */
+};  /* Message */
+
+/* Response Message; Notifies the remote driver that the forceful clearing
+ * of the data path can be lifted
+ */
+struct ipa_disable_force_clear_datapath_resp_msg_v01 {
+	/* Mandatory */
+	/*  Result Code */
+	struct ipa_qmi_response_type_v01 resp;
+	/* Standard response type */
+};  /* Message */
+
+enum ipa_peripheral_speed_enum_v01 {
+	IPA_PERIPHERAL_SPEED_ENUM_MIN_ENUM_VAL_V01 = -2147483647,
+	/* To force a 32 bit signed enum.  Do not change or use */
+	QMI_IPA_PER_USB_FS_V01 = 1,
+	/*  Full-speed USB connection */
+	QMI_IPA_PER_USB_HS_V01 = 2,
+	/*  High-speed USB connection */
+	QMI_IPA_PER_USB_SS_V01 = 3,
+	/*  Super-speed USB connection */
+	QMI_IPA_PER_WLAN_V01 = 4,
+	/*  WLAN connection */
+	IPA_PERIPHERAL_SPEED_ENUM_MAX_ENUM_VAL_V01 = 2147483647
+	/* To force a 32 bit signed enum.  Do not change or use*/
+};
+
+enum ipa_pipe_mode_enum_v01 {
+	IPA_PIPE_MODE_ENUM_MIN_ENUM_VAL_V01 = -2147483647,
+	/* To force a 32 bit signed enum.  Do not change or use */
+	QMI_IPA_PIPE_MODE_HW_V01 = 1,
+	/*  Pipe is connected with a hardware block */
+	QMI_IPA_PIPE_MODE_SW_V01 = 2,
+	/*  Pipe is controlled by the software */
+	IPA_PIPE_MODE_ENUM_MAX_ENUM_VAL_V01 = 2147483647
+	/* To force a 32 bit signed enum.  Do not change or use */
+};
+
+enum ipa_peripheral_type_enum_v01 {
+	IPA_PERIPHERAL_TYPE_ENUM_MIN_ENUM_VAL_V01 = -2147483647,
+	/* To force a 32 bit signed enum.  Do not change or use */
+	QMI_IPA_PERIPHERAL_USB_V01 = 1,
+	/*  Specifies a USB peripheral */
+	QMI_IPA_PERIPHERAL_HSIC_V01 = 2,
+	/*  Specifies an HSIC peripheral */
+	QMI_IPA_PERIPHERAL_PCIE_V01 = 3,
+	/*  Specifies a PCIe	peripheral */
+	IPA_PERIPHERAL_TYPE_ENUM_MAX_ENUM_VAL_V01 = 2147483647
+	/* To force a 32 bit signed enum.  Do not change or use */
+};
+
+struct ipa_config_req_msg_v01 {
+	/* Optional */
+	/*  Peripheral Type */
+	uint8_t peripheral_type_valid;
+	/* Must be set to true if peripheral_type is being passed */
+	enum ipa_peripheral_type_enum_v01 peripheral_type;
+	/* Informs the remote driver about the perhipheral for
+	 * which this configuration information is relevant. Values:
+	 *	- QMI_IPA_PERIPHERAL_USB (1) -- Specifies a USB peripheral
+	 *	- QMI_IPA_PERIPHERAL_HSIC(2) -- Specifies an HSIC peripheral
+	 *	- QMI_IPA_PERIPHERAL_PCIE(3) -- Specifies a PCIe peripheral
+	 */
+
+	/* Optional */
+	/*  HW Deaggregation Support */
+	uint8_t hw_deaggr_supported_valid;
+	/* Must be set to true if hw_deaggr_supported is being passed */
+	uint8_t hw_deaggr_supported;
+	/* Informs the remote driver whether the local IPA driver
+	 * allows de-aggregation to be performed in the hardware
+	 */
+
+	/* Optional */
+	/*  Maximum Aggregation Frame Size */
+	uint8_t max_aggr_frame_size_valid;
+	/* Must be set to true if max_aggr_frame_size is being passed */
+	uint32_t max_aggr_frame_size;
+	/* Specifies the maximum size of the aggregated frame that
+	 * the remote driver can expect from this execution environment
+	 *	- Valid range: 128 bytes to 32768 bytes
+	 */
+
+	/* Optional */
+	/*  IPA Ingress Pipe Mode */
+	uint8_t ipa_ingress_pipe_mode_valid;
+	/* Must be set to true if ipa_ingress_pipe_mode is being passed */
+
+	enum ipa_pipe_mode_enum_v01 ipa_ingress_pipe_mode;
+	/* Indicates to the remote driver if the ingress pipe into the
+	 *	IPA is in direct connection with another hardware block or
+	 *	if the producer of data to this ingress pipe is a software
+	 *  module. Values:
+	 *	-QMI_IPA_PIPE_MODE_HW(1) --Pipe is connected with hardware block
+	 *	-QMI_IPA_PIPE_MODE_SW(2) --Pipe is controlled by the software
+	 */
+
+	/* Optional */
+	/*  Peripheral Speed Info */
+	uint8_t peripheral_speed_info_valid;
+	/* Must be set to true if peripheral_speed_info is being passed */
+
+	enum ipa_peripheral_speed_enum_v01 peripheral_speed_info;
+	/* Indicates the speed that the peripheral connected to the IPA supports
+	 * Values:
+	 *	- QMI_IPA_PER_USB_FS (1) --  Full-speed USB connection
+	 *	- QMI_IPA_PER_USB_HS (2) --  High-speed USB connection
+	 *	- QMI_IPA_PER_USB_SS (3) --  Super-speed USB connection
+	 *  - QMI_IPA_PER_WLAN   (4) --  WLAN connection
+	 */
+
+	/* Optional */
+	/*  Downlink Accumulation Time limit */
+	uint8_t dl_accumulation_time_limit_valid;
+	/* Must be set to true if dl_accumulation_time_limit is being passed */
+	uint32_t dl_accumulation_time_limit;
+	/* Informs the remote driver about the time for which data
+	 * is accumulated in the downlink direction before it is pushed into the
+	 * IPA (downlink is with respect to the WWAN air interface)
+	 * - Units: milliseconds
+	 * - Maximum value: 255
+	 */
+
+	/* Optional */
+	/*  Downlink Accumulation Packet limit */
+	uint8_t dl_accumulation_pkt_limit_valid;
+	/* Must be set to true if dl_accumulation_pkt_limit is being passed */
+	uint32_t dl_accumulation_pkt_limit;
+	/* Informs the remote driver about the number of packets
+	 * that are to be accumulated in the downlink direction before it is
+	 * pushed into the IPA - Maximum value: 1023
+	 */
+
+	/* Optional */
+	/*  Downlink Accumulation Byte Limit */
+	uint8_t dl_accumulation_byte_limit_valid;
+	/* Must be set to true if dl_accumulation_byte_limit is being passed */
+	uint32_t dl_accumulation_byte_limit;
+	/* Inform the remote driver about the number of bytes
+	 * that are to be accumulated in the downlink direction before it
+	 * is pushed into the IPA - Maximum value: TBD
+	 */
+
+	/* Optional */
+	/*  Uplink Accumulation Time Limit */
+	uint8_t ul_accumulation_time_limit_valid;
+	/* Must be set to true if ul_accumulation_time_limit is being passed */
+	uint32_t ul_accumulation_time_limit;
+	/* Inform thes remote driver about the time for which data
+	 * is to be accumulated in the uplink direction before it is pushed into
+	 * the IPA (downlink is with respect to the WWAN air interface).
+	 * - Units: milliseconds
+	 * - Maximum value: 255
+	 */
+
+	/* Optional */
+	/*  HW Control Flags */
+	uint8_t hw_control_flags_valid;
+	/* Must be set to true if hw_control_flags is being passed */
+	uint32_t hw_control_flags;
+	/* Informs the remote driver about the hardware control flags:
+	 *	- Bit 0: IPA_HW_FLAG_HALT_SYSTEM_ON_NON_TERMINAL_FAILURE --
+	 *	Indicates to the hardware that it must not continue with
+	 *	any subsequent operation even if the failure is not terminal
+	 *	- Bit 1: IPA_HW_FLAG_NO_REPORT_MHI_CHANNEL_ERORR --
+	 *	Indicates to the hardware that it is not required to report
+	 *	channel errors to the host.
+	 *	- Bit 2: IPA_HW_FLAG_NO_REPORT_MHI_CHANNEL_WAKE_UP --
+	 *	Indicates to the hardware that it is not required to generate
+	 *	wake-up events to the host.
+	 *	- Bit 4: IPA_HW_FLAG_WORK_OVER_DDR --
+	 *	Indicates to the hardware that it is accessing addresses in
+	 *  the DDR and not over PCIe
+	 *	- Bit 5: IPA_HW_FLAG_INTERRUPT_MODE_CTRL_FLAG --
+	 *	Indicates whether the device must
+	 *	raise an event to let the host know that it is going into an
+	 *	interrupt mode (no longer polling for data/buffer availability)
+	 */
+
+	/* Optional */
+	/*  Uplink MSI Event Threshold */
+	uint8_t ul_msi_event_threshold_valid;
+	/* Must be set to true if ul_msi_event_threshold is being passed */
+	uint32_t ul_msi_event_threshold;
+	/* Informs the remote driver about the threshold that will
+	 * cause an interrupt (MSI) to be fired to the host. This ensures
+	 * that the remote driver does not accumulate an excesive number of
+	 * events before firing an interrupt.
+	 * This threshold is applicable for data moved in the UL direction.
+	 * - Maximum value: 65535
+	 */
+
+	/* Optional */
+	/*  Downlink MSI Event Threshold */
+	uint8_t dl_msi_event_threshold_valid;
+	/* Must be set to true if dl_msi_event_threshold is being passed */
+	uint32_t dl_msi_event_threshold;
+	/* Informs the remote driver about the threshold that will
+	 * cause an interrupt (MSI) to be fired to the host. This ensures
+	 * that the remote driver does not accumulate an excesive number of
+	 * events before firing an interrupt
+	 * This threshold is applicable for data that is moved in the
+	 * DL direction - Maximum value: 65535
+	 */
+};  /* Message */
+
+/* Response Message; Notifies the remote driver of the configuration
+ * information
+ */
+struct ipa_config_resp_msg_v01 {
+	/* Mandatory */
+	/*  Result Code */
+	struct ipa_qmi_response_type_v01 resp;
+	/**<   Standard response type.*/
+}; /* Message */
+
+enum ipa_stats_type_enum_v01 {
+	IPA_STATS_TYPE_ENUM_MIN_ENUM_VAL_V01 = -2147483647,
+	/* To force a 32 bit signed enum.  Do not change or use */
+	QMI_IPA_STATS_TYPE_INVALID_V01 = 0,
+	/* Invalid stats type identifier */
+	QMI_IPA_STATS_TYPE_PIPE_V01 = 1,
+	/* Pipe stats type */
+	QMI_IPA_STATS_TYPE_FILTER_RULES_V01 = 2,
+	/* Filter rule stats type */
+	IPA_STATS_TYPE_ENUM_MAX_ENUM_VAL_V01 = 2147483647
+	/* To force a 32 bit signed enum.  Do not change or use */
+};
+
+struct ipa_pipe_stats_info_type_v01 {
+	uint32_t pipe_index;
+	/* Pipe index for statistics to be retrieved. */
+
+	uint64_t num_ipv4_packets;
+	/* Accumulated number of IPv4 packets over this pipe. */
+
+	uint64_t num_ipv4_bytes;
+	/* Accumulated number of IPv4 bytes over this pipe. */
+
+	uint64_t num_ipv6_packets;
+	/* Accumulated number of IPv6 packets over this pipe. */
+
+	uint64_t num_ipv6_bytes;
+	/* Accumulated number of IPv6 bytes over this pipe. */
+};
+
+struct ipa_stats_type_filter_rule_v01 {
+	uint32_t filter_rule_index;
+	/* Filter rule index for statistics to be retrieved. */
+
+	uint64_t num_packets;
+	/* Accumulated number of packets over this filter rule. */
+};
+
+/* Request Message; Retrieve the data statistics collected on modem
+ * IPA driver.
+ */
+struct ipa_get_data_stats_req_msg_v01 {
+	/* Mandatory */
+	/*  Stats Type  */
+	enum ipa_stats_type_enum_v01 ipa_stats_type;
+	/* Indicates the type of statistics to be retrieved. */
+
+	/* Optional */
+	/* Reset Statistics */
+	uint8_t reset_stats_valid;
+	/* Must be set to true if reset_stats is being passed */
+	uint8_t reset_stats;
+	/* Option to reset the specific type of data statistics
+	 * currently collected.
+	 */
+};  /* Message */
+
+/* Response Message; Retrieve the data statistics collected
+ * on modem IPA driver.
+ */
+struct ipa_get_data_stats_resp_msg_v01 {
+	/* Mandatory */
+	/*  Result Code */
+	struct ipa_qmi_response_type_v01 resp;
+	/* Standard response type. */
+
+	/* Optional */
+	/*  Stats Type  */
+	uint8_t ipa_stats_type_valid;
+	/* Must be set to true if ipa_stats_type is passed */
+	enum ipa_stats_type_enum_v01 ipa_stats_type;
+	/* Indicates the type of statistics that are retrieved. */
+
+	/* Optional */
+	/*  Uplink Source Pipe Statistics List */
+	uint8_t ul_src_pipe_stats_list_valid;
+	/* Must be set to true if ul_src_pipe_stats_list is being passed */
+	uint32_t ul_src_pipe_stats_list_len;
+	/* Must be set to # of elements in ul_src_pipe_stats_list */
+	struct ipa_pipe_stats_info_type_v01
+		ul_src_pipe_stats_list[QMI_IPA_MAX_PIPES_V01];
+	/* List of all Uplink pipe statistics that are retrieved. */
+
+	/* Optional */
+	/*  Downlink Destination Pipe Statistics List */
+	uint8_t dl_dst_pipe_stats_list_valid;
+	/* Must be set to true if dl_dst_pipe_stats_list is being passed */
+	uint32_t dl_dst_pipe_stats_list_len;
+	/* Must be set to # of elements in dl_dst_pipe_stats_list */
+	struct ipa_pipe_stats_info_type_v01
+		dl_dst_pipe_stats_list[QMI_IPA_MAX_PIPES_V01];
+	/* List of all Downlink pipe statistics that are retrieved. */
+
+	/* Optional */
+	/*  Downlink Filter Rule Stats List */
+	uint8_t dl_filter_rule_stats_list_valid;
+	/* Must be set to true if dl_filter_rule_stats_list is being passed */
+	uint32_t dl_filter_rule_stats_list_len;
+	/* Must be set to # of elements in dl_filter_rule_stats_list */
+	struct ipa_stats_type_filter_rule_v01
+		dl_filter_rule_stats_list[QMI_IPA_MAX_FILTERS_V01];
+	/* List of all Downlink filter rule statistics retrieved. */
+};  /* Message */
+
+struct ipa_apn_data_stats_info_type_v01 {
+	uint32_t mux_id;
+	/* Indicates the MUX ID associated with the APN for which the data
+	 * usage statistics is queried
+	 */
+
+	uint64_t num_ul_packets;
+	/* Accumulated number of uplink packets corresponding to
+	 * this Mux ID
+	 */
+
+	uint64_t num_ul_bytes;
+	/* Accumulated number of uplink bytes corresponding to
+	 * this Mux ID
+	 */
+
+	uint64_t num_dl_packets;
+	/* Accumulated number of downlink packets corresponding
+	 * to this Mux ID
+	 */
+
+	uint64_t num_dl_bytes;
+	/* Accumulated number of downlink bytes corresponding to
+	 * this Mux ID
+	 */
+};  /* Type */
+
+/* Request Message; Retrieve the APN data statistics collected from modem */
+struct ipa_get_apn_data_stats_req_msg_v01 {
+	/* Optional */
+	/*  Mux ID List */
+	uint8_t mux_id_list_valid;
+	/* Must be set to true if mux_id_list is being passed */
+	uint32_t mux_id_list_len;
+	/* Must be set to # of elements in mux_id_list */
+	uint32_t mux_id_list[QMI_IPA_MAX_APN_V01];
+	/* The list of MUX IDs associated with APNs for which the data usage
+	 * statistics is being retrieved
+	 */
+};  /* Message */
+
+/* Response Message; Retrieve the APN data statistics collected from modem */
+struct ipa_get_apn_data_stats_resp_msg_v01 {
+	/* Mandatory */
+	/*  Result Code */
+	struct ipa_qmi_response_type_v01 resp;
+	/* Standard response type.*/
+
+	/* Optional */
+	/* APN Data Statistics List */
+	uint8_t apn_data_stats_list_valid;
+	/* Must be set to true if apn_data_stats_list is being passed */
+	uint32_t apn_data_stats_list_len;
+	/* Must be set to # of elements in apn_data_stats_list */
+	struct ipa_apn_data_stats_info_type_v01
+		apn_data_stats_list[QMI_IPA_MAX_APN_V01];
+	/* List of APN data retrieved as per request on mux_id.
+	* For now, only one APN monitoring is supported on modem driver.
+	* Making this as list for expandability to support more APNs in future.
+	*/
+};  /* Message */
+
+struct ipa_data_usage_quota_info_type_v01 {
+	uint32_t mux_id;
+	/* Indicates the MUX ID associated with the APN for which the data usage
+	 * quota needs to be set
+	 */
+
+	uint64_t num_Mbytes;
+	/* Number of Mega-bytes of quota value to be set on this APN associated
+	 * with this Mux ID.
+	 */
+};  /* Type */
+
+/* Request Message; Master driver sets a data usage quota value on
+ * modem driver
+ */
+struct ipa_set_data_usage_quota_req_msg_v01 {
+	/* Optional */
+	/* APN Quota List */
+	uint8_t apn_quota_list_valid;
+	/* Must be set to true if apn_quota_list is being passed */
+	uint32_t apn_quota_list_len;
+	/* Must be set to # of elements in apn_quota_list */
+	struct ipa_data_usage_quota_info_type_v01
+		apn_quota_list[QMI_IPA_MAX_APN_V01];
+	/* The list of APNs on which a data usage quota to be set on modem
+	 * driver. For now, only one APN monitoring is supported on modem
+	 * driver. Making this as list for expandability to support more
+	 * APNs in future.
+	 */
+};  /* Message */
+
+/* Response Message; Master driver sets a data usage on modem driver. */
+struct ipa_set_data_usage_quota_resp_msg_v01 {
+	/* Mandatory */
+	/* Result Code */
+	struct ipa_qmi_response_type_v01 resp;
+	/* Standard response type.*/
+};  /* Message */
+
+/* Indication Message; Modem driver sends this indication to master
+ * driver when the data usage quota is reached
+ */
+struct ipa_data_usage_quota_reached_ind_msg_v01 {
+	/* Mandatory */
+	/*  APN Quota List */
+	struct ipa_data_usage_quota_info_type_v01 apn;
+	/* This message indicates which APN has the previously set quota
+	 * reached. For now, only one APN monitoring is supported on modem
+	 * driver.
+	 */
+};  /* Message */
+
+/* Request Message; Master driver request modem driver to terminate
+ * the current data usage quota monitoring session.
+ */
+struct ipa_stop_data_usage_quota_req_msg_v01 {
+	/* This element is a placeholder to prevent the declaration of
+     *  an empty struct.  DO NOT USE THIS FIELD UNDER ANY CIRCUMSTANCE
+	 */
+	char __placeholder;
+};  /* Message */
+
+/* Response Message; Master driver request modem driver to terminate
+ * the current quota monitoring session.
+ */
+struct ipa_stop_data_usage_quota_resp_msg_v01 {
+	/* Mandatory */
+	/*  Result Code */
+	struct ipa_qmi_response_type_v01 resp;
+	/**<   Standard response type.*/
+};  /* Message */
+
+/*Service Message Definition*/
+#define QMI_IPA_INDICATION_REGISTER_REQ_V01 0x0020
+#define QMI_IPA_INDICATION_REGISTER_RESP_V01 0x0020
+#define QMI_IPA_INIT_MODEM_DRIVER_REQ_V01 0x0021
+#define QMI_IPA_INIT_MODEM_DRIVER_RESP_V01 0x0021
+#define QMI_IPA_MASTER_DRIVER_INIT_COMPLETE_IND_V01 0x0022
+#define QMI_IPA_INSTALL_FILTER_RULE_REQ_V01 0x0023
+#define QMI_IPA_INSTALL_FILTER_RULE_RESP_V01 0x0023
+#define QMI_IPA_FILTER_INSTALLED_NOTIF_REQ_V01 0x0024
+#define QMI_IPA_FILTER_INSTALLED_NOTIF_RESP_V01 0x0024
+#define QMI_IPA_ENABLE_FORCE_CLEAR_DATAPATH_REQ_V01 0x0025
+#define QMI_IPA_ENABLE_FORCE_CLEAR_DATAPATH_RESP_V01 0x0025
+#define QMI_IPA_DISABLE_FORCE_CLEAR_DATAPATH_REQ_V01 0x0026
+#define QMI_IPA_DISABLE_FORCE_CLEAR_DATAPATH_RESP_V01 0x0026
+#define QMI_IPA_CONFIG_REQ_V01 0x0027
+#define QMI_IPA_CONFIG_RESP_V01 0x0027
+#define QMI_IPA_DISABLE_LINK_LOW_PWR_STATE_REQ_V01 0x0028
+#define QMI_IPA_DISABLE_LINK_LOW_PWR_STATE_RESP_V01 0x0028
+#define QMI_IPA_ENABLE_LINK_LOW_PWR_STATE_REQ_V01 0x0029
+#define QMI_IPA_ENABLE_LINK_LOW_PWR_STATE_RESP_V01 0x0029
+#define QMI_IPA_GET_DATA_STATS_REQ_V01 0x0030
+#define QMI_IPA_GET_DATA_STATS_RESP_V01 0x0030
+#define QMI_IPA_GET_APN_DATA_STATS_REQ_V01 0x0031
+#define QMI_IPA_GET_APN_DATA_STATS_RESP_V01 0x0031
+#define QMI_IPA_SET_DATA_USAGE_QUOTA_REQ_V01 0x0032
+#define QMI_IPA_SET_DATA_USAGE_QUOTA_RESP_V01 0x0032
+#define QMI_IPA_DATA_USAGE_QUOTA_REACHED_IND_V01 0x0033
+#define QMI_IPA_STOP_DATA_USAGE_QUOTA_REQ_V01 0x0034
+#define QMI_IPA_STOP_DATA_USAGE_QUOTA_RESP_V01 0x0034
+/* add for max length*/
+#define QMI_IPA_INIT_MODEM_DRIVER_REQ_MAX_MSG_LEN_V01 98
+#define QMI_IPA_INIT_MODEM_DRIVER_RESP_MAX_MSG_LEN_V01 21
+#define QMI_IPA_INDICATION_REGISTER_REQ_MAX_MSG_LEN_V01 8
+#define QMI_IPA_INDICATION_REGISTER_RESP_MAX_MSG_LEN_V01 7
+#define QMI_IPA_INSTALL_FILTER_RULE_REQ_MAX_MSG_LEN_V01 11293
+#define QMI_IPA_INSTALL_FILTER_RULE_RESP_MAX_MSG_LEN_V01 523
+#define QMI_IPA_FILTER_INSTALLED_NOTIF_REQ_MAX_MSG_LEN_V01 574
+#define QMI_IPA_FILTER_INSTALLED_NOTIF_RESP_MAX_MSG_LEN_V01 7
+#define QMI_IPA_MASTER_DRIVER_INIT_COMPLETE_IND_MAX_MSG_LEN_V01 7
+#define QMI_IPA_DATA_USAGE_QUOTA_REACHED_IND_MAX_MSG_LEN_V01 15
+
+
+#define QMI_IPA_ENABLE_FORCE_CLEAR_DATAPATH_REQ_MAX_MSG_LEN_V01 18
+#define QMI_IPA_DISABLE_FORCE_CLEAR_DATAPATH_REQ_MAX_MSG_LEN_V01 7
+#define QMI_IPA_ENABLE_FORCE_CLEAR_DATAPATH_RESP_MAX_MSG_LEN_V01 7
+#define QMI_IPA_DISABLE_FORCE_CLEAR_DATAPATH_RESP_MAX_MSG_LEN_V01 7
+
+
+#define QMI_IPA_CONFIG_REQ_MAX_MSG_LEN_V01 81
+#define QMI_IPA_CONFIG_RESP_MAX_MSG_LEN_V01 7
+#define QMI_IPA_DISABLE_LINK_LOW_PWR_STATE_REQ_MAX_MSG_LEN_V01 18
+#define QMI_IPA_DISABLE_LINK_LOW_PWR_STATE_RESP_MAX_MSG_LEN_V01 7
+#define QMI_IPA_ENABLE_LINK_LOW_PWR_STATE_REQ_MAX_MSG_LEN_V01 7
+#define QMI_IPA_ENABLE_LINK_LOW_PWR_STATE_RESP_MAX_MSG_LEN_V01 7
+#define QMI_IPA_GET_DATA_STATS_REQ_MAX_MSG_LEN_V01 11
+#define QMI_IPA_GET_DATA_STATS_RESP_MAX_MSG_LEN_V01 2234
+#define QMI_IPA_GET_APN_DATA_STATS_REQ_MAX_MSG_LEN_V01 36
+#define QMI_IPA_GET_APN_DATA_STATS_RESP_MAX_MSG_LEN_V01 299
+#define QMI_IPA_SET_DATA_USAGE_QUOTA_REQ_MAX_MSG_LEN_V01 100
+#define QMI_IPA_SET_DATA_USAGE_QUOTA_RESP_MAX_MSG_LEN_V01 7
+#define QMI_IPA_STOP_DATA_USAGE_QUOTA_REQ_MAX_MSG_LEN_V01 0
+#define QMI_IPA_STOP_DATA_USAGE_QUOTA_RESP_MAX_MSG_LEN_V01 7
+
+/* Service Object Accessor */
+
+#endif/* IPA_QMI_SERVICE_V01_H */
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index 8a297a5..0bd5a4e 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -65,6 +65,8 @@
 
 	/* user_ns which owns the ipc ns */
 	struct user_namespace *user_ns;
+
+	unsigned int	proc_inum;
 };
 
 extern struct ipc_namespace init_ipc_ns;
diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
index 5a8e390..2e9d475 100644
--- a/include/linux/mnt_namespace.h
+++ b/include/linux/mnt_namespace.h
@@ -4,9 +4,10 @@
 
 struct mnt_namespace;
 struct fs_struct;
+struct user_namespace;
 
 extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
-		struct fs_struct *);
+		 struct user_namespace *, struct fs_struct *);
 extern void put_mnt_ns(struct mnt_namespace *ns);
 
 extern const struct file_operations proc_mounts_operations;
diff --git a/include/linux/msm_ipa.h b/include/linux/msm_ipa.h
index 8b45fcc..7347631 100644
--- a/include/linux/msm_ipa.h
+++ b/include/linux/msm_ipa.h
@@ -940,6 +940,12 @@
 	struct teth_aggr_params_link prot_caps[0];
 };
 
+enum ipacm_client_enum {
+     IPACM_CLIENT_USB = 1,
+     IPACM_CLIENT_WLAN,
+     IPACM_CLIENT_MAX
+};
+
 
 #define TETH_BRIDGE_IOC_SET_BRIDGE_MODE _IOW(TETH_BRIDGE_IOC_MAGIC, \
 				TETH_BRIDGE_IOCTL_SET_BRIDGE_MODE, \
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
index b067bd8..375527b 100644
--- a/include/linux/pid_namespace.h
+++ b/include/linux/pid_namespace.h
@@ -34,6 +34,7 @@
 	gid_t pid_gid;
 	int hide_pid;
 	int reboot;	/* group exit code if this pidns was rebooted */
+	unsigned int proc_inum;
 };
 
 extern struct pid_namespace init_pid_ns;
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 85c5073..6c89017 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -28,7 +28,11 @@
  */
 
 enum {
-	PROC_ROOT_INO = 1,
+	PROC_ROOT_INO		= 1,
+	PROC_IPC_INIT_INO	= 0xEFFFFFFFU,
+	PROC_UTS_INIT_INO	= 0xEFFFFFFEU,
+	PROC_USER_INIT_INO	= 0xEFFFFFFDU,
+	PROC_PID_INIT_INO	= 0xEFFFFFFCU,
 };
 
 /*
@@ -174,7 +178,10 @@
 	struct proc_dir_entry *parent);
 
 extern struct file *proc_ns_fget(int fd);
+extern bool proc_ns_inode(struct inode *inode);
 
+extern int proc_alloc_inum(unsigned int *pino);
+extern void proc_free_inum(unsigned int inum);
 #else
 
 #define proc_net_fops_create(net, name, mode, fops)  ({ (void)(mode), NULL; })
@@ -229,6 +236,19 @@
 	return ERR_PTR(-EINVAL);
 }
 
+static inline bool proc_ns_inode(struct inode *inode)
+{
+	return false;
+}
+
+static inline int proc_alloc_inum(unsigned int *inum)
+{
+	*inum = 1;
+	return 0;
+}
+static inline void proc_free_inum(unsigned int inum)
+{
+}
 #endif /* CONFIG_PROC_FS */
 
 #if !defined(CONFIG_PROC_KCORE)
@@ -247,10 +267,13 @@
 	void *(*get)(struct task_struct *task);
 	void (*put)(void *ns);
 	int (*install)(struct nsproxy *nsproxy, void *ns);
+	unsigned int (*inum)(void *ns);
 };
 extern const struct proc_ns_operations netns_operations;
 extern const struct proc_ns_operations utsns_operations;
 extern const struct proc_ns_operations ipcns_operations;
+extern const struct proc_ns_operations pidns_operations;
+extern const struct proc_ns_operations mntns_operations;
 
 union proc_op {
 	int (*proc_get_link)(struct dentry *, struct path *);
diff --git a/include/linux/rmnet_data.h b/include/linux/rmnet_data.h
index e0ca511..92c04b3 100644
--- a/include/linux/rmnet_data.h
+++ b/include/linux/rmnet_data.h
@@ -9,6 +9,7 @@
 #define RMNET_EGRESS_FORMAT_AGGREGATION         (1<<2)
 #define RMNET_EGRESS_FORMAT_MUXING              (1<<3)
 #define RMNET_EGRESS_FORMAT_MAP_CKSUMV3         (1<<4)
+#define RMNET_EGRESS_FORMAT_MAP_CKSUMV4         (1<<5)
 
 #define RMNET_INGRESS_FIX_ETHERNET              (1<<0)
 #define RMNET_INGRESS_FORMAT_MAP                (1<<1)
@@ -16,6 +17,7 @@
 #define RMNET_INGRESS_FORMAT_DEMUXING           (1<<3)
 #define RMNET_INGRESS_FORMAT_MAP_COMMANDS       (1<<4)
 #define RMNET_INGRESS_FORMAT_MAP_CKSUMV3        (1<<5)
+#define RMNET_INGRESS_FORMAT_MAP_CKSUMV4        (1<<6)
 
 /* ***************** Netlink API ******************************************** */
 #define RMNET_NETLINK_PROTO 31
diff --git a/include/linux/rmnet_ipa_fd_ioctl.h b/include/linux/rmnet_ipa_fd_ioctl.h
new file mode 100755
index 0000000..e49bfc6
--- /dev/null
+++ b/include/linux/rmnet_ipa_fd_ioctl.h
@@ -0,0 +1,126 @@
+#ifndef _RMNET_IPA_FD_IOCTL_H
+#define _RMNET_IPA_FD_IOCTL_H
+
+#include <linux/ioctl.h>
+#include <linux/ipa_qmi_service_v01.h>
+#include <linux/msm_ipa.h>
+
+/**
+ * unique magic number of the IPA_WAN device
+ */
+#define WAN_IOC_MAGIC 0x69
+
+#define WAN_IOCTL_ADD_FLT_RULE		0
+#define WAN_IOCTL_ADD_FLT_INDEX		1
+#define WAN_IOCTL_VOTE_FOR_BW_MBPS	2
+#define WAN_IOCTL_POLL_TETHERING_STATS  3
+#define WAN_IOCTL_SET_DATA_QUOTA        4
+#define WAN_IOCTL_SET_TETHER_CLIENT_PIPE 5
+#define WAN_IOCTL_QUERY_TETHER_STATS     6
+#define WAN_IOCTL_RESET_TETHER_STATS     7
+#define WAN_IOCTL_QUERY_DL_FILTER_STATS  8
+
+/* User space may not have this defined. */
+#ifndef IFNAMSIZ
+#define IFNAMSIZ 16
+#endif
+
+struct wan_ioctl_poll_tethering_stats {
+	/* Polling interval in seconds */
+	uint64_t polling_interval_secs;
+
+	/* Indicate whether to reset the stats (use 1) or not */
+	uint8_t reset_stats;
+};
+
+struct wan_ioctl_set_data_quota {
+	/* Name of the interface on which to set the quota */
+	char interface_name[IFNAMSIZ];
+
+	/* Quota (in Mbytes) for the above interface */
+	uint64_t quota_mbytes;
+
+	/* Indicate whether to set the quota (use 1) or unset the quota */
+	uint8_t set_quota;
+};
+
+struct wan_ioctl_set_tether_client_pipe {
+	/* enum of tether interface */
+	enum ipacm_client_enum ipa_client;
+	uint8_t reset_client;
+	uint32_t ul_src_pipe_len;
+	uint32_t ul_src_pipe_list[QMI_IPA_MAX_PIPES_V01];
+	uint32_t dl_dst_pipe_len;
+	uint32_t dl_dst_pipe_list[QMI_IPA_MAX_PIPES_V01];
+};
+
+struct wan_ioctl_query_tether_stats {
+	/* Name of the upstream interface */
+	char upstreamIface[IFNAMSIZ];
+	/* Name of the tethered interface */
+	char tetherIface[IFNAMSIZ];
+	/* enum of tether interface */
+	enum ipacm_client_enum ipa_client;
+	uint64_t ipv4_tx_packets;
+	uint64_t ipv4_tx_bytes;
+	uint64_t ipv4_rx_packets;
+	uint64_t ipv4_rx_bytes;
+	uint64_t ipv6_tx_packets;
+	uint64_t ipv6_tx_bytes;
+	uint64_t ipv6_rx_packets;
+	uint64_t ipv6_rx_bytes;
+};
+
+struct wan_ioctl_reset_tether_stats {
+	/* Name of the upstream interface, not support now */
+	char upstreamIface[IFNAMSIZ];
+	/* Indicate whether to reset the stats (use 1) or not */
+	uint8_t reset_stats;
+};
+
+struct wan_ioctl_query_dl_filter_stats {
+	/* Indicate whether to reset the filter stats (use 1) or not*/
+	uint8_t reset_stats;
+	/* Modem response QMI */
+	struct ipa_get_data_stats_resp_msg_v01 stats_resp;
+	/* provide right index to 1st firewall rule */
+	uint32_t index;
+};
+
+#define WAN_IOC_ADD_FLT_RULE _IOWR(WAN_IOC_MAGIC, \
+		WAN_IOCTL_ADD_FLT_RULE, \
+		struct ipa_install_fltr_rule_req_msg_v01 *)
+
+#define WAN_IOC_ADD_FLT_RULE_INDEX _IOWR(WAN_IOC_MAGIC, \
+		WAN_IOCTL_ADD_FLT_INDEX, \
+		struct ipa_fltr_installed_notif_req_msg_v01 *)
+
+#define WAN_IOC_VOTE_FOR_BW_MBPS _IOWR(WAN_IOC_MAGIC, \
+		WAN_IOCTL_VOTE_FOR_BW_MBPS, \
+		uint32_t *)
+
+#define WAN_IOC_POLL_TETHERING_STATS _IOWR(WAN_IOC_MAGIC, \
+		WAN_IOCTL_POLL_TETHERING_STATS, \
+		struct wan_ioctl_poll_tethering_stats *)
+
+#define WAN_IOC_SET_DATA_QUOTA _IOWR(WAN_IOC_MAGIC, \
+		WAN_IOCTL_SET_DATA_QUOTA, \
+		struct wan_ioctl_set_data_quota *)
+
+#define WAN_IOC_SET_TETHER_CLIENT_PIPE _IOWR(WAN_IOC_MAGIC, \
+		WAN_IOCTL_SET_TETHER_CLIENT_PIPE, \
+		struct wan_ioctl_set_tether_client_pipe *)
+
+#define WAN_IOC_QUERY_TETHER_STATS _IOWR(WAN_IOC_MAGIC, \
+		WAN_IOCTL_QUERY_TETHER_STATS, \
+		struct wan_ioctl_query_tether_stats *)
+
+#define WAN_IOC_RESET_TETHER_STATS _IOWR(WAN_IOC_MAGIC, \
+		WAN_IOCTL_RESET_TETHER_STATS, \
+		struct wan_ioctl_reset_tether_stats *)
+
+#define WAN_IOC_QUERY_DL_FILTER_STATS _IOWR(WAN_IOC_MAGIC, \
+		WAN_IOCTL_QUERY_DL_FILTER_STATS, \
+		struct wan_ioctl_query_dl_filter_stats *)
+
+#endif /* _RMNET_IPA_FD_IOCTL_H */
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index faf4679..5ecc988 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -14,6 +14,7 @@
 	struct hlist_head	uidhash_table[UIDHASH_SZ];
 	struct user_struct	*creator;
 	struct work_struct	destroyer;
+	unsigned int		proc_inum;
 };
 
 extern struct user_namespace init_user_ns;
diff --git a/include/linux/utsname.h b/include/linux/utsname.h
index c714ed7..ae739d7 100644
--- a/include/linux/utsname.h
+++ b/include/linux/utsname.h
@@ -52,6 +52,7 @@
 	struct kref kref;
 	struct new_utsname name;
 	struct user_namespace *user_ns;
+	unsigned int proc_inum;
 };
 extern struct uts_namespace init_uts_ns;
 
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index ee547c1..b1cd8b6 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -52,6 +52,8 @@
 	struct list_head	cleanup_list;	/* namespaces on death row */
 	struct list_head	exit_list;	/* Use only net_mutex */
 
+	unsigned int		proc_inum;
+
 	struct proc_dir_entry 	*proc_net;
 	struct proc_dir_entry 	*proc_net_stat;
 
diff --git a/include/sound/compress_offload.h b/include/sound/compress_offload.h
index 4292802..2ca30b6 100644
--- a/include/sound/compress_offload.h
+++ b/include/sound/compress_offload.h
@@ -192,6 +192,8 @@
 #define SNDRV_COMPRESS_DRAIN		_IO('C', 0x34)
 #define SNDRV_COMPRESS_NEXT_TRACK	_IO('C', 0x35)
 #define SNDRV_COMPRESS_PARTIAL_DRAIN	_IO('C', 0x36)
+#define SNDRV_COMPRESS_SET_NEXT_TRACK_PARAM\
+                                        _IOW('C', 0x37, union snd_codec_options)
 /*
  * TODO
  * 1. add mmap support
diff --git a/init/version.c b/init/version.c
index 86fe0cc..58170f1 100644
--- a/init/version.c
+++ b/init/version.c
@@ -12,6 +12,7 @@
 #include <linux/utsname.h>
 #include <generated/utsrelease.h>
 #include <linux/version.h>
+#include <linux/proc_fs.h>
 
 #ifndef CONFIG_KALLSYMS
 #define version(a) Version_ ## a
@@ -34,6 +35,7 @@
 		.domainname	= UTS_DOMAINNAME,
 	},
 	.user_ns = &init_user_ns,
+	.proc_inum = PROC_UTS_INIT_INO,
 };
 EXPORT_SYMBOL_GPL(init_uts_ns);
 
diff --git a/ipc/msgutil.c b/ipc/msgutil.c
index 26143d3..6471f1b 100644
--- a/ipc/msgutil.c
+++ b/ipc/msgutil.c
@@ -16,6 +16,7 @@
 #include <linux/msg.h>
 #include <linux/ipc_namespace.h>
 #include <linux/utsname.h>
+#include <linux/proc_fs.h>
 #include <asm/uaccess.h>
 
 #include "util.h"
@@ -30,6 +31,7 @@
 struct ipc_namespace init_ipc_ns = {
 	.count		= ATOMIC_INIT(1),
 	.user_ns = &init_user_ns,
+	.proc_inum = PROC_IPC_INIT_INO,
 };
 
 atomic_t nr_ipc_ns = ATOMIC_INIT(1);
diff --git a/ipc/namespace.c b/ipc/namespace.c
index ce0a647..cd7f733 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -26,9 +26,16 @@
 	if (ns == NULL)
 		return ERR_PTR(-ENOMEM);
 
+	err = proc_alloc_inum(&ns->proc_inum);
+	if (err) {
+		kfree(ns);
+		return ERR_PTR(err);
+	}
+
 	atomic_set(&ns->count, 1);
 	err = mq_init_ns(ns);
 	if (err) {
+		proc_free_inum(ns->proc_inum);
 		kfree(ns);
 		return ERR_PTR(err);
 	}
@@ -113,6 +120,7 @@
 	 */
 	ipcns_notify(IPCNS_REMOVED);
 	put_user_ns(ns->user_ns);
+	proc_free_inum(ns->proc_inum);
 	kfree(ns);
 }
 
@@ -170,10 +178,18 @@
 	return 0;
 }
 
+static unsigned int ipcns_inum(void *vp)
+{
+	struct ipc_namespace *ns = vp;
+
+	return ns->proc_inum;
+}
+
 const struct proc_ns_operations ipcns_operations = {
 	.name		= "ipc",
 	.type		= CLONE_NEWIPC,
 	.get		= ipcns_get,
 	.put		= ipcns_put,
 	.install	= ipcns_install,
+	.inum		= ipcns_inum,
 };
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index b576f7f..5b6ce19 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -66,7 +66,7 @@
 	if (!new_nsp)
 		return ERR_PTR(-ENOMEM);
 
-	new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, new_fs);
+	new_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, task_cred_xxx(tsk, user_ns), new_fs);
 	if (IS_ERR(new_nsp->mnt_ns)) {
 		err = PTR_ERR(new_nsp->mnt_ns);
 		goto out_ns;
diff --git a/kernel/pid.c b/kernel/pid.c
index 7acf590..b1e701b 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -78,6 +78,7 @@
 	.last_pid = 0,
 	.level = 0,
 	.child_reaper = &init_task,
+	.proc_inum = PROC_PID_INIT_INO,
 };
 EXPORT_SYMBOL_GPL(init_pid_ns);
 
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index 57bc1fd..4f15bef 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -88,6 +88,10 @@
 	if (ns->pid_cachep == NULL)
 		goto out_free_map;
 
+	err = proc_alloc_inum(&ns->proc_inum);
+	if (err)
+		goto out_free_map;
+
 	kref_init(&ns->kref);
 	ns->level = level;
 	ns->parent = get_pid_ns(parent_pid_ns);
@@ -118,6 +122,7 @@
 {
 	int i;
 
+	proc_free_inum(ns->proc_inum);
 	for (i = 0; i < PIDMAP_ENTRIES; i++)
 		kfree(ns->pidmap[i].page);
 	kmem_cache_free(pid_ns_cachep, ns);
diff --git a/kernel/user.c b/kernel/user.c
index 71dd236..9013a4f 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/export.h>
 #include <linux/user_namespace.h>
+#include <linux/proc_fs.h>
 
 /*
  * userns count is 1 for root user, 1 for init_uts_ns,
@@ -26,6 +27,7 @@
 		.refcount	= ATOMIC_INIT(3),
 	},
 	.creator = &root_user,
+	.proc_inum = PROC_USER_INIT_INO,
 };
 EXPORT_SYMBOL_GPL(init_user_ns);
 
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 3b906e9..c14b7b9 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -27,11 +27,18 @@
 	struct user_namespace *ns;
 	struct user_struct *root_user;
 	int n;
+	int ret;
 
 	ns = kmem_cache_alloc(user_ns_cachep, GFP_KERNEL);
 	if (!ns)
 		return -ENOMEM;
 
+	ret = proc_alloc_inum(&ns->proc_inum);
+	if (ret) {
+		kmem_cache_free(user_ns_cachep, ns);
+		return ret;
+	}
+
 	kref_init(&ns->kref);
 
 	for (n = 0; n < UIDHASH_SZ; ++n)
@@ -73,6 +80,7 @@
 	struct user_namespace *ns =
 		container_of(work, struct user_namespace, destroyer);
 	free_uid(ns->creator);
+	proc_free_inum(ns->proc_inum);
 	kmem_cache_free(user_ns_cachep, ns);
 }
 
diff --git a/kernel/utsname.c b/kernel/utsname.c
index 405caf9..ce3d44b 100644
--- a/kernel/utsname.c
+++ b/kernel/utsname.c
@@ -36,11 +36,18 @@
 					  struct uts_namespace *old_ns)
 {
 	struct uts_namespace *ns;
+	int err;
 
 	ns = create_uts_ns();
 	if (!ns)
 		return ERR_PTR(-ENOMEM);
 
+	err = proc_alloc_inum(&ns->proc_inum);
+	if (err) {
+		kfree(ns);
+		return ERR_PTR(err);
+	}
+
 	down_read(&uts_sem);
 	memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
 	ns->user_ns = get_user_ns(task_cred_xxx(tsk, user)->user_ns);
@@ -78,6 +85,7 @@
 
 	ns = container_of(kref, struct uts_namespace, kref);
 	put_user_ns(ns->user_ns);
+	proc_free_inum(ns->proc_inum);
 	kfree(ns);
 }
 
@@ -110,11 +118,18 @@
 	return 0;
 }
 
+static unsigned int utsns_inum(void *vp)
+{
+	struct uts_namespace *ns = vp;
+
+	return ns->proc_inum;
+}
+
 const struct proc_ns_operations utsns_operations = {
 	.name		= "uts",
 	.type		= CLONE_NEWUTS,
 	.get		= utsns_get,
 	.put		= utsns_put,
 	.install	= utsns_install,
+	.inum		= utsns_inum,
 };
-
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 31a5ae5..335ab88 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -376,6 +376,21 @@
 }
 EXPORT_SYMBOL_GPL(get_net_ns_by_pid);
 
+static __net_init int net_ns_net_init(struct net *net)
+{
+	return proc_alloc_inum(&net->proc_inum);
+}
+
+static __net_exit void net_ns_net_exit(struct net *net)
+{
+	proc_free_inum(net->proc_inum);
+}
+
+static struct pernet_operations __net_initdata net_ns_ops = {
+	.init = net_ns_net_init,
+	.exit = net_ns_net_exit,
+};
+
 static int __init net_ns_init(void)
 {
 	struct net_generic *ng;
@@ -407,6 +422,8 @@
 
 	mutex_unlock(&net_mutex);
 
+	register_pernet_subsys(&net_ns_ops);
+
 	return 0;
 }
 
@@ -630,11 +647,18 @@
 	return 0;
 }
 
+static unsigned int netns_inum(void *ns)
+{
+	struct net *net = ns;
+	return net->proc_inum;
+}
+
 const struct proc_ns_operations netns_operations = {
 	.name		= "net",
 	.type		= CLONE_NEWNET,
 	.get		= netns_get,
 	.put		= netns_put,
 	.install	= netns_install,
+	.inum		= netns_inum,
 };
 #endif