aboutsummaryrefslogtreecommitdiffstats
diff options
-rw-r--r--0001-kdbus-interprocess-message-router.patch1096
-rw-r--r--dev_removal.patch372
-rw-r--r--devnode_gid.patch206
-rw-r--r--series2
4 files changed, 1675 insertions, 1 deletions
diff --git a/0001-kdbus-interprocess-message-router.patch b/0001-kdbus-interprocess-message-router.patch
new file mode 100644
index 00000000000000..e671e082b6ab48
--- /dev/null
+++ b/0001-kdbus-interprocess-message-router.patch
@@ -0,0 +1,1096 @@
+From 8c41f3b1fb98a30664c73d61745b346d4013ced5 Mon Sep 17 00:00:00 2001
+From: Kay Sievers <kay@vrfy.org>
+Date: Sat, 22 Dec 2012 18:36:55 +0100
+Subject: [PATCH] kdbus: interprocess message router
+
+---
+ drivers/Kconfig | 2
+ drivers/Makefile | 1
+ drivers/kdbus/Kconfig | 5
+ drivers/kdbus/Makefile | 2
+ drivers/kdbus/kdbus.c | 916 +++++++++++++++++++++++++++++++++++++++++++++
+ include/uapi/kdbus/kdbus.h | 46 ++
+ include/uapi/linux/major.h | 2
+ kdbus.c | 64 +++
+ 8 files changed, 1038 insertions(+)
+ create mode 100644 drivers/kdbus/Kconfig
+ create mode 100644 drivers/kdbus/Makefile
+ create mode 100644 drivers/kdbus/kdbus.c
+ create mode 100644 include/uapi/kdbus/kdbus.h
+ create mode 100644 kdbus.c
+
+--- a/drivers/Kconfig
++++ b/drivers/Kconfig
+@@ -158,4 +158,6 @@ source "drivers/irqchip/Kconfig"
+
+ source "drivers/ipack/Kconfig"
+
++source "drivers/kdbus/Kconfig"
++
+ endmenu
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -146,3 +146,4 @@ obj-$(CONFIG_MEMORY) += memory/
+ obj-$(CONFIG_IIO) += iio/
+ obj-$(CONFIG_VME_BUS) += vme/
+ obj-$(CONFIG_IPACK_BUS) += ipack/
++obj-$(CONFIG_KDBUS) += kdbus/
+--- /dev/null
++++ b/drivers/kdbus/Kconfig
+@@ -0,0 +1,5 @@
++config KDBUS
++ tristate "kdbus interprocess message router"
++ help
++ kdbus provides efficient kernel-aided message exchange and routing
++ between processes. It is used as the low-level transport of D-Bus.
+--- /dev/null
++++ b/drivers/kdbus/Makefile
+@@ -0,0 +1,2 @@
++obj-$(CONFIG_KDBUS) += kdbus.o
++
+--- /dev/null
++++ b/drivers/kdbus/kdbus.c
+@@ -0,0 +1,916 @@
++/*
++ * kdbus - interprocess message routing
++ *
++ * Copyright (C) 2013
++ *
++ * kdbus is free software; you can redistribute it and/or modify it under
++ * the terms of the GNU Lesser General Public License as published by the
++ * Free Software Foundation; either version 2.1 of the License, or (at
++ * your option) any later version.
++ *
++ */
++
++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
++
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/idr.h>
++#include <linux/fs.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++#include <linux/init.h>
++#include <linux/cred.h>
++#include <linux/security.h>
++#include <asm/uaccess.h>
++#include <uapi/linux/major.h>
++#include <uapi/kdbus/kdbus.h>
++
++/*
++ * TODO:
++ * - set parent for driver-core /sys/devices/kdbus!... devices to virtual/kdbus/,
++ * the bus subsys misses the "no parent" logic the class subsys has
++ *
++ * - switch to a 64bit idr for connection id <--> kdbus_conn
++ */
++
++/*
++ * Example of device nodes in /dev. For any future changes, keep in mind,
++ * that the layout should support a possible /dev/kdbus/ filesystem for the
++ * init namspace and one for each sub-namespace.
++ *
++ * /dev/kdbus/
++ * |-- control
++ * |-- system
++ * | |-- bus
++ * | |-- ep-epiphany
++ * | `-- ep-firefox
++ * |-- 2702-user
++ * | `-- bus
++ * |-- 1000-user
++ * | `-- bus
++ * `-- ns
++ * |-- myfedoracontainer
++ * | |-- control
++ * | |-- system
++ * | | `-- bus
++ * | `-- 1000-user
++ * | `-- bus
++ * `-- mydebiancontainer
++ * |-- control
++ * |-- system
++ * `-- bus
++ */
++
++/*
++ * kdbus namespace
++ * - provides a "control" node
++ * - owns a major number
++ * - owns all created buses
++ * - the initial namespace is unnamed and stays around for forver
++ * - new namespaces are created by opening the control node and
++ * issuing KDBUS_NS_CREATE
++ * - closing the connection destroys the created namespace
++ */
++struct kdbus_ns {
++ unsigned int ref; /* reference count */
++ bool disconnected; /* invalidated data */
++ struct kdbus_ns *parent;/* parent namespace */
++ __u64 id; /* global id of this namespace */
++ const char *devpath; /* /dev base directory path */
++ int major; /* device major number for all nodes */
++ struct idr idr; /* map of endpoint minors to buses */
++ struct device *dev; /* control device node, minor == 0 */
++ struct mutex lock; /* ns data lock */
++ __u64 bus_id_next; /* next bus id sequence number */
++};
++
++/*
++ * kdbus bus
++ * - provides a "bus" endpoint
++ * - owns additional endpoints
++ * - own all bus connections
++ * - new buses are created by opening the control node and
++ * issuing KDBUS_BUS_CREATE
++ * - closing the connection destroys the created bus
++ */
++struct kdbus_bus {
++ unsigned int ref; /* reference count */
++ bool disconnected; /* invalidated data */
++ struct kdbus_ns *ns; /* namespace of this bus */
++ const char *name; /* bus name */
++ __u64 id; /* id of this bus in the namespace */
++ struct mutex lock; /* bus data lock */
++ __u64 ep_id_next; /* next endpoint id sequence number */
++ __u64 conn_id_next; /* next connection id sequence number */
++ __u64 msg_id_next; /* next message id sequence number */
++ struct idr conn_idr; /* map of connection ids */
++ struct kdbus_ep *ep; /* "bus" default endpoint */
++ struct list_head ep_list; /* endpoints assigned to this bus */
++};
++
++/*
++ * kdbus endpoint
++ * - offers access to a bus, the default device node name is "bus"
++ * - additional endpoints can carry a specific policy/filters
++ */
++struct kdbus_ep {
++ unsigned int ref; /* reference count */
++ bool disconnected; /* invalidated data */
++ struct kdbus_bus *bus; /* bus behind this endpoint */
++ const char *name; /* name, prefixed with uid */
++ __u64 id; /* id of this endpoint on the bus */
++ unsigned int minor; /* minor of this endpoint in the namespace major */
++ struct device *dev; /* device node of this endpoint */
++ umode_t mode; /* file mode of this endpoint device node */
++ uid_t uid; /* uid owning this endpoint */
++ gid_t gid; /* gid owning this endpoint */
++};
++
++/*
++ * kdbus connection
++ * - connection to a control node or an endpoint
++ */
++enum kdbus_conn_type {
++ KDBUS_CONN_UNDEFINED,
++ KDBUS_CONN_CONTROL,
++ KDBUS_CONN_NS_OWNER,
++ KDBUS_CONN_BUS_OWNER,
++ KDBUS_CONN_EP,
++};
++
++struct kdbus_conn {
++ enum kdbus_conn_type type;
++ struct kdbus_ns *ns;
++ union {
++ struct kdbus_ns *ns_owner;
++ struct kdbus_bus *bus_owner;
++ struct kdbus_ep *ep;
++ };
++ __u64 id; /* id of the connection on the bus */
++};
++
++/* kdbus message */
++enum kdbus_msg_data_type {
++ KDBUS_MSG_DATA_UNDEFINED,
++ KDBUS_MSG_DATA_MEM,
++};
++
++struct kdbus_msg_data {
++ u64 data;
++ u64 size;
++ u32 type;
++ u32 flags;
++};
++
++struct kdbus_msg {
++ u64 src_id;
++ u64 dst_id;
++ u64 flags;
++ uid_t src_uid;
++ gid_t src_gid;
++ pid_t src_pid;
++ pid_t src_tid;
++ u64 ts_nsec;
++ u64 id;
++ u64 reserved[8];
++ u32 data_count;
++ struct kdbus_msg_data *data;
++};
++
++static void kdbus_release(struct device *dev)
++{
++ kfree(dev);
++}
++
++/* kdbus sysfs subsystem */
++static struct bus_type kdbus_subsys = {
++ .name = "kdbus",
++};
++
++/* control nodes are world accessible */
++static char *kdbus_devnode_control(struct device *dev,
++ umode_t *mode, uid_t *uid, gid_t *gid)
++{
++ if (mode)
++ *mode = 0666;
++ return NULL;
++}
++
++static struct device_type kdbus_devtype_control = {
++ .name = "control",
++ .release = kdbus_release,
++ .devnode = kdbus_devnode_control,
++};
++
++/* endpoints are by default owned by the bus owner */
++static char *kdbus_devnode_ep(struct device *dev,
++ umode_t *mode, uid_t *uid, gid_t *gid)
++{
++ struct kdbus_ep *ep = dev_get_drvdata(dev);
++
++ if (mode)
++ *mode = ep->mode;
++ if (uid)
++ *uid = ep->uid;
++ if (gid)
++ *gid = ep->gid;
++ return NULL;
++}
++
++static struct device_type kdbus_devtype_ep = {
++ .name = "ep",
++ .release = kdbus_release,
++ .devnode = kdbus_devnode_ep,
++};
++
++/* kdbus initial namespace */
++static struct kdbus_ns *kdbus_ns_init;
++
++/* map of majors to namespaces */
++static DEFINE_IDR(kdbus_ns_major_idr);
++
++/* namespace list lock */
++static DEFINE_MUTEX(kdbus_subsys_lock);
++
++/* next namespace id sequence number */
++static __u64 kdbus_ns_id_next;
++
++extern const struct file_operations kdbus_device_ops;
++static void kdbus_ep_disconnect(struct kdbus_ep *ep);
++static struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep);
++static int kdbus_ep_new(struct kdbus_bus *bus, const char *name,
++ umode_t mode, uid_t uid, gid_t gid,
++ struct kdbus_ep **ep);
++static int kdbus_msg_new(struct kdbus_conn *conn, struct kdbus_msg __user *umsg,
++ struct kdbus_msg **msg);
++static int kdbus_msg_send(struct kdbus_conn *conn, struct kdbus_msg *msg);
++
++static struct kdbus_ep *endpoint_find(struct kdbus_bus *bus, const char *name);
++static int endpoint_remove(struct kdbus_ep *ep);
++
++/* kdbus namespace */
++static struct kdbus_ns *kdbus_ns_ref(struct kdbus_ns *ns)
++{
++ if (!ns)
++ return NULL;
++ ns->ref++;
++ return ns;
++}
++
++static void kdbus_ns_disconnect(struct kdbus_ns *ns)
++{
++ if (ns->disconnected)
++ return;
++ ns->disconnected = true;
++
++ if (ns->dev) {
++ device_unregister(ns->dev);
++ ns->dev = NULL;
++ }
++ if (ns->major > 0) {
++ idr_remove(&kdbus_ns_major_idr, ns->major);
++ unregister_chrdev(ns->major, "kdbus");
++ ns->major = 0;
++ }
++ pr_info("closing namespace %s\n", ns->devpath);
++}
++
++static struct kdbus_ns *kdbus_ns_unref(struct kdbus_ns *ns)
++{
++ if (!ns)
++ return NULL;
++ ns->ref--;
++ if (ns->ref > 0)
++ return ns;
++
++ kdbus_ns_disconnect(ns);
++ pr_info("clean up namespace %s\n", ns->devpath);
++ kfree(ns->devpath);
++ kfree(ns);
++ return NULL;
++}
++
++static int kdbus_ns_new(struct kdbus_ns *parent, const char *name,
++ struct kdbus_ns **ns)
++{
++ struct kdbus_ns *n;
++ int i;
++ int err;
++
++ if ((parent && !name) || (!parent && name))
++ return -EINVAL;
++
++ n = kzalloc(sizeof(struct kdbus_ns), GFP_KERNEL);
++ if (!n)
++ return -ENOMEM;
++
++ n->ref = 1;
++ idr_init(&n->idr);
++ mutex_init(&n->lock);
++
++ /* compose name and path of base directory in /dev */
++ if (!parent) {
++ /* initial namespace */
++ n->devpath = kstrdup("kdbus", GFP_KERNEL);
++ if (!n->devpath) {
++ err = -ENOMEM;
++ goto err;
++ }
++
++ /* register static major to support module auto-loading */
++ err = register_chrdev(KDBUS_CHAR_MAJOR, "kdbus", &kdbus_device_ops);
++ if (err)
++ goto err;
++ n->major = KDBUS_CHAR_MAJOR;
++ } else {
++ n->parent = parent;
++ n->devpath = kasprintf(GFP_KERNEL, "kdbus/ns/%s/%s", parent->devpath, name);
++ if (!n->devpath) {
++ err = -ENOMEM;
++ goto err;
++ }
++
++ /* get dynamic major */
++ n->major = register_chrdev(0, "kdbus", &kdbus_device_ops);
++ if (n->major < 0) {
++ err = n->major;
++ goto err;
++ }
++ }
++
++ /* register major in our namespace map */
++ mutex_lock(&kdbus_subsys_lock);
++ if (!idr_pre_get(&kdbus_ns_major_idr, GFP_KERNEL)) {
++ err = -ENOMEM;
++ goto err_unlock;
++ }
++ err = idr_get_new_above(&kdbus_ns_major_idr, n, n->major, &i);
++ if (err >= 0 && n->major != i) {
++ idr_remove(&kdbus_ns_major_idr, i);
++ err = -EEXIST;
++ goto err_unlock;
++ }
++
++ /* get id for this namespace */
++ n->id = kdbus_ns_id_next++;
++
++ /* register control device for this namespace */
++ n->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
++ if (!n->dev)
++ goto err_unlock;
++ dev_set_name(n->dev, "%s/%s", n->devpath, "control");
++ n->dev->bus = &kdbus_subsys;
++ n->dev->type = &kdbus_devtype_control;
++ n->dev->devt = MKDEV(n->major, 0);
++ dev_set_drvdata(n->dev, n);
++ err = device_register(n->dev);
++ if (err < 0) {
++ put_device(n->dev);
++ n->dev = NULL;
++ goto err_unlock;
++ }
++ mutex_unlock(&kdbus_subsys_lock);
++
++ *ns = n;
++ pr_info("created namespace %llu '%s/'\n",
++ (unsigned long long)n->id, n->devpath);
++ return 0;
++
++err_unlock:
++ mutex_unlock(&kdbus_subsys_lock);
++err:
++ kdbus_ns_unref(n);
++ return err;
++}
++
++/* kdbus bus */
++static struct kdbus_bus *kdbus_bus_ref(struct kdbus_bus *bus)
++{
++ if (!bus)
++ return NULL;
++ bus->ref++;
++ return bus;
++}
++
++static void kdbus_bus_disconnect(struct kdbus_bus *bus)
++{
++ if (bus->disconnected)
++ return;
++ bus->disconnected = true;
++
++ /* remove default endpoint */
++ kdbus_ep_disconnect(bus->ep);
++ kdbus_ep_unref(bus->ep);
++
++ pr_info("closing bus %s/%s\n",
++ bus->ns->devpath, bus->name);
++}
++
++static struct kdbus_bus *kdbus_bus_unref(struct kdbus_bus *bus)
++{
++ if (!bus)
++ return NULL;
++ bus->ref--;
++ if (bus->ref > 0)
++ return bus;
++
++ kdbus_bus_disconnect(bus);
++ pr_info("clean up bus %s/%s\n",
++ bus->ns->devpath, bus->name);
++
++ kfree(bus->name);
++ kfree(bus);
++ return NULL;
++}
++
++static int kdbus_bus_new(struct kdbus_ns *ns, const char *name,
++ umode_t mode, uid_t uid, gid_t gid,
++ struct kdbus_bus **bus)
++{
++ struct kdbus_bus *b;
++ int err;
++
++ b = kzalloc(sizeof(struct kdbus_bus), GFP_KERNEL);
++ if (!b)
++ return -ENOMEM;
++
++ b->ref = 1;
++ b->ns = ns;
++ /* connection 0 == kernel/multi-cast */
++ b->conn_id_next = 1;
++ mutex_init(&b->lock);
++ idr_init(&b->conn_idr);
++ INIT_LIST_HEAD(&b->ep_list);
++
++ if (uid > 0)
++ b->name = kasprintf(GFP_KERNEL, "%u-%s", uid, name);
++ else
++ b->name = kstrdup(name, GFP_KERNEL);
++ if (!b->name) {
++ err = -ENOMEM;
++ goto err;
++ }
++
++ err = kdbus_ep_new(b, "bus", mode, uid, gid, &b->ep);
++ if (err < 0)
++ goto err;
++
++ mutex_lock(&ns->lock);
++ b->id = ns->bus_id_next++;
++ mutex_unlock(&ns->lock);
++
++ *bus = b;
++ pr_info("created bus %llu '%s/%s'\n",
++ (unsigned long long)b->id, ns->devpath, b->name);
++ return 0;
++err:
++ kdbus_bus_unref(b);
++ return err;
++}
++
++/* kdbus endpoint */
++static struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep)
++{
++ if (!ep)
++ return NULL;
++ ep->ref++;
++ return ep;
++}
++
++static void kdbus_ep_disconnect(struct kdbus_ep *ep)
++{
++ if (ep->disconnected)
++ return;
++ ep->disconnected = true;
++
++ if (ep->dev) {
++ device_unregister(ep->dev);
++ ep->dev = NULL;
++ }
++ if (ep->minor > 0) {
++ idr_remove(&ep->bus->ns->idr, ep->minor);
++ ep->minor = 0;
++ }
++ pr_info("closing endpoint %s/%s/%s\n",
++ ep->bus->ns->devpath, ep->bus->name, ep->name);
++}
++
++static struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep)
++{
++ if (!ep)
++ return NULL;
++ ep->ref--;
++ if (ep->ref > 0)
++ return ep;
++
++ mutex_lock(&ep->bus->lock);
++ kdbus_ep_disconnect(ep);
++ pr_info("clean up endpoint %s/%s/%s\n",
++ ep->bus->ns->devpath, ep->bus->name, ep->name);
++ kdbus_bus_unref(ep->bus);
++ mutex_unlock(&ep->bus->lock);
++
++ kfree(ep->name);
++ kfree(ep);
++ return NULL;
++}
++
++/* Find the endpoint for a specific bus */
++static struct kdbus_ep *endpoint_find(struct kdbus_bus *bus, const char *name)
++{
++ struct kdbus_ep *ep = NULL;
++
++ mutex_lock(&bus->lock);
++ list_for_each_entry(ep, &bus->ep_list, bus);
++
++ mutex_unlock(&bus->lock);
++
++ return NULL;
++}
++
++static int kdbus_ep_new(struct kdbus_bus *bus, const char *name,
++ umode_t mode, uid_t uid, gid_t gid,
++ struct kdbus_ep **ep)
++{
++ struct kdbus_ep *e;
++ int err;
++ int i;
++
++ e = kzalloc(sizeof(struct kdbus_ep), GFP_KERNEL);
++ if (!e)
++ return -ENOMEM;
++
++ mutex_lock(&bus->ns->lock);
++ e->ref = 1;
++ e->mode = mode;
++ e->uid = uid;
++ e->gid = gid;
++ e->bus = kdbus_bus_ref(bus);
++
++ e->name = kstrdup(name, GFP_KERNEL);
++ if (!e->name) {
++ err = -ENOMEM;
++ goto err;
++ }
++
++ /* register minor in our endpoint map */
++ if (!idr_pre_get(&bus->ns->idr, GFP_KERNEL)) {
++ err = -ENOMEM;
++ goto err_unlock;
++ }
++ err = idr_get_new_above(&bus->ns->idr, e, 1, &i);
++ if (err < 0)
++ goto err_unlock;
++ e->minor = i;
++
++ /* get id for this endpoint from bus */
++ mutex_lock(&bus->lock);
++ e->id = bus->ep_id_next++;
++ mutex_unlock(&bus->lock);
++
++ /* register bus endpoint device */
++ e->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
++ if (!e->dev)
++ goto err;
++ dev_set_name(e->dev, "%s/%s/%s", bus->ns->devpath, bus->name, name);
++ e->dev->bus = &kdbus_subsys;
++ e->dev->type = &kdbus_devtype_ep;
++ e->dev->devt = MKDEV(bus->ns->major, e->minor);
++ dev_set_drvdata(e->dev, e);
++ err = device_register(e->dev);
++ if (err < 0) {
++ put_device(e->dev);
++ e->dev = NULL;
++ }
++ mutex_unlock(&bus->ns->lock);
++
++ if (ep)
++ *ep = e;
++ pr_info("created endpoint %llu for bus '%s/%s/%s'\n",
++ (unsigned long long)e->id, bus->ns->devpath, bus->name, name);
++ return 0;
++
++err_unlock:
++ mutex_unlock(&bus->ns->lock);
++err:
++ kdbus_ep_unref(e);
++ return err;
++}
++
++static int endpoint_remove(struct kdbus_ep *ep)
++{
++ return 0;
++}
++
++/* kdbus file operations */
++static int kdbus_conn_open(struct inode *inode, struct file *file)
++{
++ struct kdbus_conn *conn;
++ struct kdbus_ns *ns;
++ struct kdbus_ep *ep;
++ int i;
++ int err;
++
++ conn = kzalloc(sizeof(struct kdbus_conn), GFP_KERNEL);
++ if (!conn)
++ return -ENOMEM;
++
++ /* find and reference namespace */
++ mutex_lock(&kdbus_subsys_lock);
++ ns = idr_find(&kdbus_ns_major_idr, MAJOR(inode->i_rdev));
++ if (!ns || ns->disconnected) {
++ kfree(conn);
++ mutex_unlock(&kdbus_subsys_lock);
++ return -ENOENT;
++ }
++ conn->ns = kdbus_ns_ref(ns);
++ file->private_data = conn;
++ mutex_unlock(&kdbus_subsys_lock);
++
++ /* control device node */
++ if (MINOR(inode->i_rdev) == 0) {
++ conn->type = KDBUS_CONN_CONTROL;
++ file->private_data = conn;
++ pr_info("opened control device '%s/control'\n",
++ conn->ns->devpath);
++ return 0;
++ }
++
++ /* find endpoint for device node */
++ mutex_lock(&conn->ns->lock);
++ ep = idr_find(&conn->ns->idr, MINOR(inode->i_rdev));
++ if (!ep || ep->disconnected) {
++ err = -ENOENT;
++ goto err_unlock;
++ }
++
++ /* create endpoint connection */
++ conn->type = KDBUS_CONN_EP;
++ conn->ep = kdbus_ep_ref(ep);
++
++ /* get and register new id for this connection */
++ conn->id = conn->ep->bus->conn_id_next++;
++ if (!idr_pre_get(&conn->ep->bus->conn_idr, GFP_KERNEL)) {
++ err = -ENOMEM;
++ goto err_unlock;
++ }
++ /* FIXME: get 64 bit working, this will fail for the 2^31th connection */
++ err = idr_get_new_above(&conn->ep->bus->conn_idr, conn, conn->id, &i);
++ if (err >= 0 && conn->id != i) {
++ idr_remove(&conn->ep->bus->conn_idr, i);
++ err = -EEXIST;
++ goto err_unlock;
++ }
++
++ file->private_data = conn;
++ mutex_unlock(&conn->ns->lock);
++
++ pr_info("created endpoint bus connection %llu '%s/%s'\n",
++ (unsigned long long)conn->id, conn->ns->devpath,
++ conn->ep->bus->name);
++ return 0;
++
++err_unlock:
++ mutex_unlock(&conn->ns->lock);
++ kfree(conn);
++ return err;
++}
++
++static int kdbus_conn_release(struct inode *inode, struct file *file)
++{
++ struct kdbus_conn *conn = file->private_data;
++
++ switch (conn->type) {
++ case KDBUS_CONN_NS_OWNER:
++ break;
++
++ case KDBUS_CONN_BUS_OWNER:
++ kdbus_bus_disconnect(conn->bus_owner);
++ kdbus_bus_unref(conn->bus_owner);
++ break;
++
++ case KDBUS_CONN_EP:
++ kdbus_ep_unref(conn->ep);
++ break;
++
++ default:
++ break;
++ }
++
++ mutex_lock(&conn->ns->lock);
++ kdbus_ns_unref(conn->ns);
++ mutex_unlock(&conn->ns->lock);
++ kfree(conn);
++ return 0;
++}
++
++/* kdbus control device commands */
++static long kdbus_conn_ioctl_control(struct file *file,
++ unsigned int cmd, void __user *argp)
++{
++ struct kdbus_conn *conn = file->private_data;
++ struct kdbus_cmd_name name;
++ int err;
++
++ switch (cmd) {
++ case KDBUS_CMD_BUS_CREATE: {
++ struct kdbus_bus *bus = NULL;
++
++ if (copy_from_user(&name, argp, sizeof(struct kdbus_cmd_name)))
++ return -EFAULT;
++
++ err = kdbus_bus_new(conn->ns, name.name,
++ 0660, current_fsuid(), current_fsgid(),
++ &bus);
++ if (err < 0)
++ return err;
++
++ /* turn the control fd into a new bus owner device */
++ conn->type = KDBUS_CONN_BUS_OWNER;
++ conn->bus_owner = bus;
++ return 0;
++ }
++
++ case KDBUS_CMD_NS_CREATE:
++ return -ENOSYS;
++
++ default:
++ return -ENOTTY;
++ }
++}
++
++/* kdbus bus endpoint commands */
++static long kdbus_conn_ioctl_ep(struct file *file, unsigned int cmd,
++ void __user *argp)
++{
++ struct kdbus_conn *conn = file->private_data;
++ struct kdbus_cmd_name name;
++ struct kdbus_msg *msg;
++ struct kdbus_ep *ep;
++ long err;
++
++ /* We need a connection before we can do anything with an ioctl */
++ if (!conn)
++ return -EINVAL;
++
++ switch (cmd) {
++ case KDBUS_CMD_EP_CREATE:
++ /* create a new endpoint for this bus */
++ if (copy_from_user(&name, argp, sizeof(struct kdbus_cmd_name)))
++ return -EFAULT;
++ return kdbus_ep_new(conn->ep->bus, name.name,
++ 0660, current_fsuid(), current_fsgid(),
++ NULL);
++
++ case KDBUS_CMD_EP_REMOVE:
++ /* remove an endpoint from this bus */
++ if (copy_from_user(&name, argp, sizeof(struct kdbus_cmd_name)))
++ return -EFAULT;
++ ep = endpoint_find(conn->bus_owner, name.name);
++ if (!ep)
++ return -EINVAL;
++
++ return endpoint_remove(ep);
++
++ case KDBUS_CMD_EP_POLICY_SET:
++ /* upload a policy for this bus */
++ return -ENOSYS;
++
++ case KDBUS_CMD_NAME_ACQUIRE:
++ /* acquire a well-known name */
++ return -ENOSYS;
++
++ case KDBUS_CMD_NAME_RELEASE:
++ /* release a well-known name */
++ return -ENOSYS;
++
++ case KDBUS_CMD_NAME_LIST:
++ /* return all current well-known names */
++ return -ENOSYS;
++
++ case KDBUS_CMD_MATCH_ADD:
++ /* subscribe to/filter for broadcast messages */
++ return -ENOSYS;
++
++ case KDBUS_CMD_MATCH_REMOVE:
++ /* unsubscribe from broadcast messages */
++ return -ENOSYS;
++
++ case KDBUS_CMD_MSG_SEND:
++ /* send a message */
++ err = kdbus_msg_new(conn, argp, &msg);
++ if (err < 0)
++ return err;
++ return kdbus_msg_send(conn, msg);
++
++ case KDBUS_CMD_MSG_RECV:
++ /* receive a message, needs to be freed */
++ return -ENOSYS;
++
++ default:
++ return -ENOTTY;
++ }
++}
++
++static long kdbus_conn_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
++{
++ struct kdbus_conn *conn = file->private_data;
++ void __user *argp = (void __user *)arg;
++
++ switch (conn->type) {
++ case KDBUS_CONN_CONTROL:
++ return kdbus_conn_ioctl_control(file, cmd, argp);
++
++ case KDBUS_CONN_EP:
++ return kdbus_conn_ioctl_ep(file, cmd, argp);
++
++ default:
++ return -EINVAL;
++ }
++}
++
++const struct file_operations kdbus_device_ops = {
++ .owner = THIS_MODULE,
++ .open = kdbus_conn_open,
++ .release = kdbus_conn_release,
++ .unlocked_ioctl = kdbus_conn_ioctl,
++ .compat_ioctl = kdbus_conn_ioctl,
++ .llseek = noop_llseek,
++};
++
++static void kdbus_msg_free(struct kdbus_msg *msg)
++{
++ kfree(msg);
++}
++
++static int kdbus_msg_new(struct kdbus_conn *conn, struct kdbus_msg __user *umsg,
++ struct kdbus_msg **msg)
++{
++ struct kdbus_msg *m;
++ int err;
++
++ m = kmalloc(GFP_KERNEL, sizeof(struct kdbus_msg));
++ if (!m)
++ return -ENOMEM;
++ if (copy_from_user(m, umsg, sizeof(struct kdbus_msg))) {
++ err = -EFAULT;
++ goto out_err;
++ }
++
++ m->src_id = conn->id;
++ m->id = conn->ep->bus->msg_id_next++;
++ *msg = m;
++ return 0;
++out_err:
++ kdbus_msg_free(m);
++ return err;
++}
++
++static int kdbus_msg_send(struct kdbus_conn *conn, struct kdbus_msg *msg)
++{
++ struct kdbus_conn *conn_dst;
++
++ conn_dst = idr_find(&conn->ep->bus->conn_idr, msg->dst_id);
++ if (!conn_dst)
++ return -ENOENT;
++
++ pr_info("sending message %llu from %llu to %llu\n",
++ (unsigned long long)msg->id, (unsigned long long)msg->src_id,
++ (unsigned long long)msg->dst_id);
++
++ kdbus_msg_free(msg);
++ return 0;
++}
++
++int __init kdbus_init(void)
++{
++ int err;
++
++ err = bus_register(&kdbus_subsys);
++ if (err < 0)
++ return err;
++
++ err = kdbus_ns_new(NULL, NULL, &kdbus_ns_init);
++ if (err < 0) {
++ bus_unregister(&kdbus_subsys);
++ pr_err("kdbus: failed to initialize err=%i\n", err);
++ return err;
++ }
++
++ pr_info("kdbus: initialized\n");
++ return 0;
++}
++
++void __exit kdbus_exit(void)
++{
++ kdbus_ns_unref(kdbus_ns_init);
++ bus_unregister(&kdbus_subsys);
++ pr_info("kdbus: unloaded\n");
++}
++
++module_init(kdbus_init);
++module_exit(kdbus_exit);
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("kdbus interprocess message router");
++MODULE_ALIAS_CHARDEV(KDBUS_CHAR_MAJOR, 0);
++MODULE_ALIAS("devname:kdbus/control");
+--- /dev/null
++++ b/include/uapi/kdbus/kdbus.h
+@@ -0,0 +1,46 @@
++/*
++ * kdbus - interprocess message routing
++ *
++ * Copyright (C) 2013
++ *
++ * kdbus is free software; you can redistribute it and/or modify it under
++ * the terms of the GNU Lesser General Public License as published by the
++ * Free Software Foundation; either version 2.1 of the License, or (at
++ * your option) any later version.
++ *
++ */
++
++#ifndef _KDBUS_H_
++#define _KDBUS_H_
++
++#define KDBUS_IOC_MAGIC 0x95
++
++/* kdbus control device commands */
++struct kdbus_cmd_name {
++ uint64_t capabilities;
++ char name[256];
++ char reserved[256];
++};
++
++enum kdbus_cmd {
++ /* kdbus control commands */
++ KDBUS_CMD_BUS_CREATE = _IOW(KDBUS_IOC_MAGIC, 0x00, struct kdbus_cmd_name),
++ KDBUS_CMD_NS_CREATE = _IOW(KDBUS_IOC_MAGIC, 0x10, struct kdbus_cmd_name),
++
++ /* kdbus endpoint commands */
++ KDBUS_CMD_EP_CREATE = _IOWR(KDBUS_IOC_MAGIC, 0x30, struct kdbus_cmd_name),
++ KDBUS_CMD_EP_REMOVE = _IOWR(KDBUS_IOC_MAGIC, 0x31, int),
++ KDBUS_CMD_EP_POLICY_SET = _IOWR(KDBUS_IOC_MAGIC, 0x32, int),
++
++ KDBUS_CMD_NAME_ACQUIRE = _IOWR(KDBUS_IOC_MAGIC, 0x50, int),
++ KDBUS_CMD_NAME_RELEASE = _IOWR(KDBUS_IOC_MAGIC, 0x51, int),
++ KDBUS_CMD_NAME_LIST = _IOWR(KDBUS_IOC_MAGIC, 0x52, int),
++
++ KDBUS_CMD_MATCH_ADD = _IOWR(KDBUS_IOC_MAGIC, 0x60, int),
++ KDBUS_CMD_MATCH_REMOVE = _IOWR(KDBUS_IOC_MAGIC, 0x61, int),
++
++ KDBUS_CMD_MSG_SEND = _IOWR(KDBUS_IOC_MAGIC, 0x80, int),
++ KDBUS_CMD_MSG_RECV = _IOWR(KDBUS_IOC_MAGIC, 0x81, int),
++};
++
++#endif
+--- a/include/uapi/linux/major.h
++++ b/include/uapi/linux/major.h
+@@ -166,6 +166,8 @@
+
+ #define OSST_MAJOR 206 /* OnStream-SCx0 SCSI tape */
+
++#define KDBUS_CHAR_MAJOR 222
++
+ #define IBM_TTY3270_MAJOR 227
+ #define IBM_FS3270_MAJOR 228
+
+--- /dev/null
++++ b/kdbus.c
+@@ -0,0 +1,64 @@
++#define _GNU_SOURCE
++#include <stdio.h>
++#include <string.h>
++#include <time.h>
++#include <fcntl.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <stdint.h>
++#include <errno.h>
++#include <assert.h>
++#include <sys/ioctl.h>
++
++#include "include/uapi/kdbus/kdbus.h"
++
++int main(int argc, char *argv[])
++{
++ int fdc;
++ int fdb;
++ struct kdbus_cmd_name name;
++ char *busname;
++ char *bus;
++ char *ep;
++ uid_t uid;
++
++ uid = getuid();
++ if (argv[1])
++ busname = argv[1];
++ else if (uid > 0)
++ busname = "system";
++ else
++ busname = "user";
++ strcpy(name.name, busname);
++
++ printf("-- opening /dev/kdbus/control\n");
++ fdc = open("/dev/kdbus/control", O_RDWR|O_CLOEXEC);
++ if (fdc < 0)
++ return EXIT_FAILURE;
++
++ printf("-- creating bus '%s'\n", name.name);
++ ioctl(fdc, KDBUS_CMD_BUS_CREATE, &name);
++
++ if (uid > 0)
++ asprintf(&bus, "/dev/kdbus/%u-%s/bus", uid, busname);
++ else
++ asprintf(&bus, "/dev/kdbus/%s/bus", busname);
++ printf("-- opening bus connection %s\n", bus);
++ fdb = open(bus, O_RDWR|O_CLOEXEC);
++
++
++ asprintf(&ep, "ep-42");
++ strcpy(name.name, ep);
++ printf("-- creating endpoint for bus %s called %s\n", bus, ep);
++ ioctl(fdb, KDBUS_CMD_EP_CREATE, &name);
++
++ printf("-- sleeping 10s\n");
++ sleep(10);
++
++ printf("-- closing bus connection\n");
++ close(fdb);
++
++ printf("-- closing bus master\n");
++ close(fdc);
++ return EXIT_SUCCESS;
++}
diff --git a/dev_removal.patch b/dev_removal.patch
index 5aa627d8f859c0..26888827a32d85 100644
--- a/dev_removal.patch
+++ b/dev_removal.patch
@@ -61,11 +61,21 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/iio/magnetometer/hid-sensor-magn-3d.c | 4 +-
drivers/memory/tegra20-mc.c | 4 +-
drivers/memory/tegra30-mc.c | 4 +-
+ drivers/scsi/NCR_Q720.c | 2 -
drivers/scsi/a100u2w.c | 8 ++--
drivers/scsi/aacraid/linit.c | 15 ++-------
drivers/scsi/aic94xx/aic94xx_init.c | 23 ++++++--------
drivers/scsi/arm/cumana_2.c | 8 ++--
- 57 files changed, 248 insertions(+), 262 deletions(-)
+ drivers/scsi/bvme6000_scsi.c | 6 +--
+ drivers/scsi/ips.c | 10 +++---
+ drivers/scsi/jazz_esp.c | 6 +--
+ drivers/scsi/lasi700.c | 2 -
+ drivers/scsi/mac_esp.c | 6 +--
+ drivers/scsi/sni_53c710.c | 4 +-
+ drivers/scsi/stex.c | 5 +--
+ drivers/scsi/sun_esp.c | 30 ++++++++----------
+ drivers/scsi/zorro7xx.c | 12 +++----
+ 67 files changed, 288 insertions(+), 305 deletions(-)
--- a/drivers/ide/aec62xx.c
+++ b/drivers/ide/aec62xx.c
@@ -2096,6 +2106,17 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
{
struct resource *irq;
struct tegra30_mc *mc;
+--- a/drivers/scsi/NCR_Q720.c
++++ b/drivers/scsi/NCR_Q720.c
+@@ -351,7 +351,7 @@ static struct mca_driver NCR_Q720_driver
+ .name = "NCR_Q720",
+ .bus = &mca_bus_type,
+ .probe = NCR_Q720_probe,
+- .remove = __devexit_p(NCR_Q720_remove),
++ .remove = NCR_Q720_remove,
+ },
+ };
+
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -1082,8 +1082,8 @@ static struct scsi_host_template inia100
@@ -2305,3 +2326,352 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
.id_table = cumanascsi2_cids,
.drv = {
.name = "cumanascsi2",
+--- a/drivers/scsi/bvme6000_scsi.c
++++ b/drivers/scsi/bvme6000_scsi.c
+@@ -34,7 +34,7 @@ static struct scsi_host_template bvme600
+
+ static struct platform_device *bvme6000_scsi_device;
+
+-static __devinit int
++static int
+ bvme6000_probe(struct platform_device *dev)
+ {
+ struct Scsi_Host *host;
+@@ -88,7 +88,7 @@ bvme6000_probe(struct platform_device *d
+ return -ENODEV;
+ }
+
+-static __devexit int
++static int
+ bvme6000_device_remove(struct platform_device *dev)
+ {
+ struct Scsi_Host *host = platform_get_drvdata(dev);
+@@ -108,7 +108,7 @@ static struct platform_driver bvme6000_s
+ .owner = THIS_MODULE,
+ },
+ .probe = bvme6000_probe,
+- .remove = __devexit_p(bvme6000_device_remove),
++ .remove = bvme6000_device_remove,
+ };
+
+ static int __init bvme6000_scsi_init(void)
+--- a/drivers/scsi/ips.c
++++ b/drivers/scsi/ips.c
+@@ -389,14 +389,14 @@ MODULE_DEVICE_TABLE( pci, ips_pci_table
+
+ static char ips_hot_plug_name[] = "ips";
+
+-static int __devinit ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent);
+-static void __devexit ips_remove_device(struct pci_dev *pci_dev);
++static int ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent);
++static void ips_remove_device(struct pci_dev *pci_dev);
+
+ static struct pci_driver ips_pci_driver = {
+ .name = ips_hot_plug_name,
+ .id_table = ips_pci_table,
+ .probe = ips_insert_device,
+- .remove = __devexit_p(ips_remove_device),
++ .remove = ips_remove_device,
+ };
+
+
+@@ -6837,7 +6837,7 @@ err_out_sh:
+ /* Routine Description: */
+ /* Remove one Adapter ( Hot Plugging ) */
+ /*---------------------------------------------------------------------------*/
+-static void __devexit
++static void
+ ips_remove_device(struct pci_dev *pci_dev)
+ {
+ struct Scsi_Host *sh = pci_get_drvdata(pci_dev);
+@@ -6898,7 +6898,7 @@ module_exit(ips_module_exit);
+ /* Return Value: */
+ /* 0 if Successful, else non-zero */
+ /*---------------------------------------------------------------------------*/
+-static int __devinit
++static int
+ ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent)
+ {
+ int index = -1;
+--- a/drivers/scsi/jazz_esp.c
++++ b/drivers/scsi/jazz_esp.c
+@@ -129,7 +129,7 @@ static const struct esp_driver_ops jazz_
+ .dma_error = jazz_esp_dma_error,
+ };
+
+-static int __devinit esp_jazz_probe(struct platform_device *dev)
++static int esp_jazz_probe(struct platform_device *dev)
+ {
+ struct scsi_host_template *tpnt = &scsi_esp_template;
+ struct Scsi_Host *host;
+@@ -201,7 +201,7 @@ fail:
+ return err;
+ }
+
+-static int __devexit esp_jazz_remove(struct platform_device *dev)
++static int esp_jazz_remove(struct platform_device *dev)
+ {
+ struct esp *esp = dev_get_drvdata(&dev->dev);
+ unsigned int irq = esp->host->irq;
+@@ -223,7 +223,7 @@ MODULE_ALIAS("platform:jazz_esp");
+
+ static struct platform_driver esp_jazz_driver = {
+ .probe = esp_jazz_probe,
+- .remove = __devexit_p(esp_jazz_remove),
++ .remove = esp_jazz_remove,
+ .driver = {
+ .name = "jazz_esp",
+ .owner = THIS_MODULE,
+--- a/drivers/scsi/lasi700.c
++++ b/drivers/scsi/lasi700.c
+@@ -168,7 +168,7 @@ static struct parisc_driver lasi700_driv
+ .name = "lasi_scsi",
+ .id_table = lasi700_ids,
+ .probe = lasi700_probe,
+- .remove = __devexit_p(lasi700_driver_remove),
++ .remove = lasi700_driver_remove,
+ };
+
+ static int __init
+--- a/drivers/scsi/mac_esp.c
++++ b/drivers/scsi/mac_esp.c
+@@ -481,7 +481,7 @@ static struct esp_driver_ops mac_esp_ops
+ .dma_error = mac_esp_dma_error,
+ };
+
+-static int __devinit esp_mac_probe(struct platform_device *dev)
++static int esp_mac_probe(struct platform_device *dev)
+ {
+ struct scsi_host_template *tpnt = &scsi_esp_template;
+ struct Scsi_Host *host;
+@@ -591,7 +591,7 @@ fail:
+ return err;
+ }
+
+-static int __devexit esp_mac_remove(struct platform_device *dev)
++static int esp_mac_remove(struct platform_device *dev)
+ {
+ struct mac_esp_priv *mep = platform_get_drvdata(dev);
+ struct esp *esp = mep->esp;
+@@ -614,7 +614,7 @@ static int __devexit esp_mac_remove(stru
+
+ static struct platform_driver esp_mac_driver = {
+ .probe = esp_mac_probe,
+- .remove = __devexit_p(esp_mac_remove),
++ .remove = esp_mac_remove,
+ .driver = {
+ .name = DRV_MODULE_NAME,
+ .owner = THIS_MODULE,
+--- a/drivers/scsi/sni_53c710.c
++++ b/drivers/scsi/sni_53c710.c
+@@ -65,7 +65,7 @@ static struct scsi_host_template snirm71
+ .module = THIS_MODULE,
+ };
+
+-static int __devinit snirm710_probe(struct platform_device *dev)
++static int snirm710_probe(struct platform_device *dev)
+ {
+ unsigned long base;
+ struct NCR_700_Host_Parameters *hostdata;
+@@ -134,7 +134,7 @@ static int __exit snirm710_driver_remove
+
+ static struct platform_driver snirm710_driver = {
+ .probe = snirm710_probe,
+- .remove = __devexit_p(snirm710_driver_remove),
++ .remove = snirm710_driver_remove,
+ .driver = {
+ .name = "snirm_53c710",
+ .owner = THIS_MODULE,
+--- a/drivers/scsi/stex.c
++++ b/drivers/scsi/stex.c
+@@ -1540,8 +1540,7 @@ static void stex_free_irq(struct st_hba
+ pci_disable_msi(pdev);
+ }
+
+-static int __devinit
+-stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
++static int stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ {
+ struct st_hba *hba;
+ struct Scsi_Host *host;
+@@ -1815,7 +1814,7 @@ static struct pci_driver stex_pci_driver
+ .name = DRV_NAME,
+ .id_table = stex_pci_tbl,
+ .probe = stex_probe,
+- .remove = __devexit_p(stex_remove),
++ .remove = stex_remove,
+ .shutdown = stex_shutdown,
+ };
+
+--- a/drivers/scsi/sun_esp.c
++++ b/drivers/scsi/sun_esp.c
+@@ -43,8 +43,7 @@ enum dvma_rev {
+ dvmahme
+ };
+
+-static int __devinit esp_sbus_setup_dma(struct esp *esp,
+- struct platform_device *dma_of)
++static int esp_sbus_setup_dma(struct esp *esp, struct platform_device *dma_of)
+ {
+ esp->dma = dma_of;
+
+@@ -79,7 +78,7 @@ static int __devinit esp_sbus_setup_dma(
+
+ }
+
+-static int __devinit esp_sbus_map_regs(struct esp *esp, int hme)
++static int esp_sbus_map_regs(struct esp *esp, int hme)
+ {
+ struct platform_device *op = esp->dev;
+ struct resource *res;
+@@ -99,7 +98,7 @@ static int __devinit esp_sbus_map_regs(s
+ return 0;
+ }
+
+-static int __devinit esp_sbus_map_command_block(struct esp *esp)
++static int esp_sbus_map_command_block(struct esp *esp)
+ {
+ struct platform_device *op = esp->dev;
+
+@@ -111,7 +110,7 @@ static int __devinit esp_sbus_map_comman
+ return 0;
+ }
+
+-static int __devinit esp_sbus_register_irq(struct esp *esp)
++static int esp_sbus_register_irq(struct esp *esp)
+ {
+ struct Scsi_Host *host = esp->host;
+ struct platform_device *op = esp->dev;
+@@ -120,7 +119,7 @@ static int __devinit esp_sbus_register_i
+ return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp);
+ }
+
+-static void __devinit esp_get_scsi_id(struct esp *esp, struct platform_device *espdma)
++static void esp_get_scsi_id(struct esp *esp, struct platform_device *espdma)
+ {
+ struct platform_device *op = esp->dev;
+ struct device_node *dp;
+@@ -142,7 +141,7 @@ done:
+ esp->scsi_id_mask = (1 << esp->scsi_id);
+ }
+
+-static void __devinit esp_get_differential(struct esp *esp)
++static void esp_get_differential(struct esp *esp)
+ {
+ struct platform_device *op = esp->dev;
+ struct device_node *dp;
+@@ -154,7 +153,7 @@ static void __devinit esp_get_differenti
+ esp->flags &= ~ESP_FLAG_DIFFERENTIAL;
+ }
+
+-static void __devinit esp_get_clock_params(struct esp *esp)
++static void esp_get_clock_params(struct esp *esp)
+ {
+ struct platform_device *op = esp->dev;
+ struct device_node *bus_dp, *dp;
+@@ -170,7 +169,7 @@ static void __devinit esp_get_clock_para
+ esp->cfreq = fmhz;
+ }
+
+-static void __devinit esp_get_bursts(struct esp *esp, struct platform_device *dma_of)
++static void esp_get_bursts(struct esp *esp, struct platform_device *dma_of)
+ {
+ struct device_node *dma_dp = dma_of->dev.of_node;
+ struct platform_device *op = esp->dev;
+@@ -195,7 +194,7 @@ static void __devinit esp_get_bursts(str
+ esp->bursts = bursts;
+ }
+
+-static void __devinit esp_sbus_get_props(struct esp *esp, struct platform_device *espdma)
++static void esp_sbus_get_props(struct esp *esp, struct platform_device *espdma)
+ {
+ esp_get_scsi_id(esp, espdma);
+ esp_get_differential(esp);
+@@ -487,9 +486,8 @@ static const struct esp_driver_ops sbus_
+ .dma_error = sbus_esp_dma_error,
+ };
+
+-static int __devinit esp_sbus_probe_one(struct platform_device *op,
+- struct platform_device *espdma,
+- int hme)
++static int esp_sbus_probe_one(struct platform_device *op,
++ struct platform_device *espdma, int hme)
+ {
+ struct scsi_host_template *tpnt = &scsi_esp_template;
+ struct Scsi_Host *host;
+@@ -562,7 +560,7 @@ fail:
+ return err;
+ }
+
+-static int __devinit esp_sbus_probe(struct platform_device *op)
++static int esp_sbus_probe(struct platform_device *op)
+ {
+ struct device_node *dma_node = NULL;
+ struct device_node *dp = op->dev.of_node;
+@@ -585,7 +583,7 @@ static int __devinit esp_sbus_probe(stru
+ return esp_sbus_probe_one(op, dma_of, hme);
+ }
+
+-static int __devexit esp_sbus_remove(struct platform_device *op)
++static int esp_sbus_remove(struct platform_device *op)
+ {
+ struct esp *esp = dev_get_drvdata(&op->dev);
+ struct platform_device *dma_of = esp->dma;
+@@ -639,7 +637,7 @@ static struct platform_driver esp_sbus_d
+ .of_match_table = esp_match,
+ },
+ .probe = esp_sbus_probe,
+- .remove = __devexit_p(esp_sbus_remove),
++ .remove = esp_sbus_remove,
+ };
+
+ static int __init sunesp_init(void)
+--- a/drivers/scsi/zorro7xx.c
++++ b/drivers/scsi/zorro7xx.c
+@@ -38,7 +38,7 @@ static struct zorro_driver_data {
+ const char *name;
+ unsigned long offset;
+ int absolute; /* offset is absolute address */
+-} zorro7xx_driver_data[] __devinitdata = {
++} zorro7xx_driver_data[] = {
+ { .name = "PowerUP 603e+", .offset = 0xf40000, .absolute = 1 },
+ { .name = "WarpEngine 40xx", .offset = 0x40000 },
+ { .name = "A4091", .offset = 0x800000 },
+@@ -46,7 +46,7 @@ static struct zorro_driver_data {
+ { 0 }
+ };
+
+-static struct zorro_device_id zorro7xx_zorro_tbl[] __devinitdata = {
++static struct zorro_device_id zorro7xx_zorro_tbl[] = {
+ {
+ .id = ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS,
+ .driver_data = (unsigned long)&zorro7xx_driver_data[0],
+@@ -71,8 +71,8 @@ static struct zorro_device_id zorro7xx_z
+ };
+ MODULE_DEVICE_TABLE(zorro, zorro7xx_zorro_tbl);
+
+-static int __devinit zorro7xx_init_one(struct zorro_dev *z,
+- const struct zorro_device_id *ent)
++static int zorro7xx_init_one(struct zorro_dev *z,
++ const struct zorro_device_id *ent)
+ {
+ struct Scsi_Host *host;
+ struct NCR_700_Host_Parameters *hostdata;
+@@ -150,7 +150,7 @@ static int __devinit zorro7xx_init_one(s
+ return -ENODEV;
+ }
+
+-static __devexit void zorro7xx_remove_one(struct zorro_dev *z)
++static void zorro7xx_remove_one(struct zorro_dev *z)
+ {
+ struct Scsi_Host *host = zorro_get_drvdata(z);
+ struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
+@@ -167,7 +167,7 @@ static struct zorro_driver zorro7xx_driv
+ .name = "zorro7xx-scsi",
+ .id_table = zorro7xx_zorro_tbl,
+ .probe = zorro7xx_init_one,
+- .remove = __devexit_p(zorro7xx_remove_one),
++ .remove = zorro7xx_remove_one,
+ };
+
+ static int __init zorro7xx_scsi_init(void)
diff --git a/devnode_gid.patch b/devnode_gid.patch
new file mode 100644
index 00000000000000..f6ca7f9d7f2e0b
--- /dev/null
+++ b/devnode_gid.patch
@@ -0,0 +1,206 @@
+From 8c41f3b1fb98a30664c73d61745b346d4013ced5 Mon Sep 17 00:00:00 2001
+From: Kay Sievers <kay@vrfy.org>
+Date: Sat, 22 Dec 2012 18:36:55 +0100
+Subject: [PATCH] driver core: add uid and gid to devtmpfs
+
+
+---
+ block/genhd.c | 3 ++-
+ drivers/base/core.c | 17 +++++++++++++----
+ drivers/base/devtmpfs.c | 27 +++++++++++++++++----------
+ drivers/usb/core/usb.c | 3 ++-
+ include/linux/device.h | 7 +++++--
+ 5 files changed, 39 insertions(+), 18 deletions(-)
+
+--- a/block/genhd.c
++++ b/block/genhd.c
+@@ -1107,7 +1107,8 @@ struct class block_class = {
+ .name = "block",
+ };
+
+-static char *block_devnode(struct device *dev, umode_t *mode)
++static char *block_devnode(struct device *dev, umode_t *mode,
++ uid_t *uid, gid_t *gid)
+ {
+ struct gendisk *disk = dev_to_disk(dev);
+
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -283,15 +283,21 @@ static int dev_uevent(struct kset *kset,
+ const char *tmp;
+ const char *name;
+ umode_t mode = 0;
++ uid_t uid = 0;
++ gid_t gid = 0;
+
+ add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt));
+ add_uevent_var(env, "MINOR=%u", MINOR(dev->devt));
+- name = device_get_devnode(dev, &mode, &tmp);
++ name = device_get_devnode(dev, &mode, &uid, &gid, &tmp);
+ if (name) {
+ add_uevent_var(env, "DEVNAME=%s", name);
+- kfree(tmp);
+ if (mode)
+ add_uevent_var(env, "DEVMODE=%#o", mode & 0777);
++ if (uid)
++ add_uevent_var(env, "DEVUID=%u", uid);
++ if (gid)
++ add_uevent_var(env, "DEVGID=%u", gid);
++ kfree(tmp);
+ }
+ }
+
+@@ -1274,6 +1280,8 @@ static struct device *next_device(struct
+ * device_get_devnode - path of device node file
+ * @dev: device
+ * @mode: returned file access mode
++ * @uid: returned file owner
++ * @gid: returned file group
+ * @tmp: possibly allocated string
+ *
+ * Return the relative path of a possible device node.
+@@ -1282,7 +1290,8 @@ static struct device *next_device(struct
+ * freed by the caller.
+ */
+ const char *device_get_devnode(struct device *dev,
+- umode_t *mode, const char **tmp)
++ umode_t *mode, uid_t *uid, gid_t *gid,
++ const char **tmp)
+ {
+ char *s;
+
+@@ -1290,7 +1299,7 @@ const char *device_get_devnode(struct de
+
+ /* the device type may provide a specific name */
+ if (dev->type && dev->type->devnode)
+- *tmp = dev->type->devnode(dev, mode);
++ *tmp = dev->type->devnode(dev, mode, uid, gid);
+ if (*tmp)
+ return *tmp;
+
+--- a/drivers/base/devtmpfs.c
++++ b/drivers/base/devtmpfs.c
+@@ -41,6 +41,8 @@ static struct req {
+ int err;
+ const char *name;
+ umode_t mode; /* 0 => delete */
++ uid_t uid;
++ gid_t gid;
+ struct device *dev;
+ } *requests;
+
+@@ -85,7 +87,9 @@ int devtmpfs_create_node(struct device *
+ return 0;
+
+ req.mode = 0;
+- req.name = device_get_devnode(dev, &req.mode, &tmp);
++ req.uid = 0;
++ req.gid = 0;
++ req.name = device_get_devnode(dev, &req.mode, &req.uid, &req.gid, &tmp);
+ if (!req.name)
+ return -ENOMEM;
+
+@@ -121,7 +125,7 @@ int devtmpfs_delete_node(struct device *
+ if (!thread)
+ return 0;
+
+- req.name = device_get_devnode(dev, NULL, &tmp);
++ req.name = device_get_devnode(dev, NULL, NULL, NULL, &tmp);
+ if (!req.name)
+ return -ENOMEM;
+
+@@ -187,7 +191,8 @@ static int create_path(const char *nodep
+ return err;
+ }
+
+-static int handle_create(const char *nodename, umode_t mode, struct device *dev)
++static int handle_create(const char *nodename, umode_t mode, uid_t uid,
++ gid_t gid, struct device *dev)
+ {
+ struct dentry *dentry;
+ struct path path;
+@@ -201,14 +206,14 @@ static int handle_create(const char *nod
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
+- err = vfs_mknod(path.dentry->d_inode,
+- dentry, mode, dev->devt);
++ err = vfs_mknod(path.dentry->d_inode, dentry, mode, dev->devt);
+ if (!err) {
+ struct iattr newattrs;
+
+- /* fixup possibly umasked mode */
+ newattrs.ia_mode = mode;
+- newattrs.ia_valid = ATTR_MODE;
++ newattrs.ia_uid = uid;
++ newattrs.ia_gid = gid;
++ newattrs.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID;
+ mutex_lock(&dentry->d_inode->i_mutex);
+ notify_change(dentry, &newattrs);
+ mutex_unlock(&dentry->d_inode->i_mutex);
+@@ -357,10 +362,11 @@ int devtmpfs_mount(const char *mntdir)
+
+ static DECLARE_COMPLETION(setup_done);
+
+-static int handle(const char *name, umode_t mode, struct device *dev)
++static int handle(const char *name, umode_t mode, uid_t uid, gid_t gid,
++ struct device *dev)
+ {
+ if (mode)
+- return handle_create(name, mode, dev);
++ return handle_create(name, mode, uid, gid, dev);
+ else
+ return handle_remove(name, dev);
+ }
+@@ -386,7 +392,8 @@ static int devtmpfsd(void *p)
+ spin_unlock(&req_lock);
+ while (req) {
+ struct req *next = req->next;
+- req->err = handle(req->name, req->mode, req->dev);
++ req->err = handle(req->name, req->mode,
++ req->uid, req->gid, req->dev);
+ complete(&req->done);
+ req = next;
+ }
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -317,7 +317,8 @@ static const struct dev_pm_ops usb_devic
+ #endif /* CONFIG_PM */
+
+
+-static char *usb_devnode(struct device *dev, umode_t *mode)
++static char *usb_devnode(struct device *dev,
++ umode_t *mode, uid_t *uid, gid_t *gid)
+ {
+ struct usb_device *usb_dev;
+
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -24,6 +24,7 @@
+ #include <linux/pm.h>
+ #include <linux/atomic.h>
+ #include <linux/ratelimit.h>
++#include <linux/uidgid.h>
+ #include <asm/device.h>
+
+ struct device;
+@@ -470,7 +471,8 @@ struct device_type {
+ const char *name;
+ const struct attribute_group **groups;
+ int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
+- char *(*devnode)(struct device *dev, umode_t *mode);
++ char *(*devnode)(struct device *dev, umode_t *mode,
++ uid_t *uid, gid_t *gid);
+ void (*release)(struct device *dev);
+
+ const struct dev_pm_ops *pm;
+@@ -841,7 +843,8 @@ extern int device_rename(struct device *
+ extern int device_move(struct device *dev, struct device *new_parent,
+ enum dpm_order dpm_order);
+ extern const char *device_get_devnode(struct device *dev,
+- umode_t *mode, const char **tmp);
++ umode_t *mode, uid_t *uid, gid_t *gid,
++ const char **tmp);
+ extern void *dev_get_drvdata(const struct device *dev);
+ extern int dev_set_drvdata(struct device *dev, void *data);
+
diff --git a/series b/series
index c38853a342b171..52d9b1c4dec626 100644
--- a/series
+++ b/series
@@ -1,4 +1,6 @@
# My specific stuff, at the top to make it easier to work stuff below.
+devnode_gid.patch
+0001-kdbus-interprocess-message-router.patch
dbus.patch
dev_removal.patch