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