powerpc: Only include kup-radix.h for 64-bit Book3S
[linux-2.6-microblaze.git] / drivers / base / core.c
index f6f620a..78114dd 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/netdevice.h>
 #include <linux/sched/signal.h>
+#include <linux/sched/mm.h>
 #include <linux/sysfs.h>
 
 #include "base.h"
@@ -239,27 +240,35 @@ void device_pm_move_to_tail(struct device *dev)
 #define to_devlink(dev)        container_of((dev), struct device_link, link_dev)
 
 static ssize_t status_show(struct device *dev,
-                         struct device_attribute *attr, char *buf)
+                          struct device_attribute *attr, char *buf)
 {
-       char *status;
+       const char *output;
 
        switch (to_devlink(dev)->status) {
        case DL_STATE_NONE:
-               status = "not tracked"; break;
+               output = "not tracked";
+               break;
        case DL_STATE_DORMANT:
-               status = "dormant"; break;
+               output = "dormant";
+               break;
        case DL_STATE_AVAILABLE:
-               status = "available"; break;
+               output = "available";
+               break;
        case DL_STATE_CONSUMER_PROBE:
-               status = "consumer probing"; break;
+               output = "consumer probing";
+               break;
        case DL_STATE_ACTIVE:
-               status = "active"; break;
+               output = "active";
+               break;
        case DL_STATE_SUPPLIER_UNBIND:
-               status = "supplier unbinding"; break;
+               output = "supplier unbinding";
+               break;
        default:
-               status = "unknown"; break;
+               output = "unknown";
+               break;
        }
-       return sprintf(buf, "%s\n", status);
+
+       return sysfs_emit(buf, "%s\n", output);
 }
 static DEVICE_ATTR_RO(status);
 
@@ -267,16 +276,16 @@ static ssize_t auto_remove_on_show(struct device *dev,
                                   struct device_attribute *attr, char *buf)
 {
        struct device_link *link = to_devlink(dev);
-       char *str;
+       const char *output;
 
        if (link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER)
-               str = "supplier unbind";
+               output = "supplier unbind";
        else if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER)
-               str = "consumer unbind";
+               output = "consumer unbind";
        else
-               str = "never";
+               output = "never";
 
-       return sprintf(buf, "%s\n", str);
+       return sysfs_emit(buf, "%s\n", output);
 }
 static DEVICE_ATTR_RO(auto_remove_on);
 
@@ -285,7 +294,7 @@ static ssize_t runtime_pm_show(struct device *dev,
 {
        struct device_link *link = to_devlink(dev);
 
-       return sprintf(buf, "%d\n", !!(link->flags & DL_FLAG_PM_RUNTIME));
+       return sysfs_emit(buf, "%d\n", !!(link->flags & DL_FLAG_PM_RUNTIME));
 }
 static DEVICE_ATTR_RO(runtime_pm);
 
@@ -294,7 +303,8 @@ static ssize_t sync_state_only_show(struct device *dev,
 {
        struct device_link *link = to_devlink(dev);
 
-       return sprintf(buf, "%d\n", !!(link->flags & DL_FLAG_SYNC_STATE_ONLY));
+       return sysfs_emit(buf, "%d\n",
+                         !!(link->flags & DL_FLAG_SYNC_STATE_ONLY));
 }
 static DEVICE_ATTR_RO(sync_state_only);
 
@@ -807,9 +817,7 @@ static void device_link_put_kref(struct device_link *link)
 void device_link_del(struct device_link *link)
 {
        device_links_write_lock();
-       device_pm_lock();
        device_link_put_kref(link);
-       device_pm_unlock();
        device_links_write_unlock();
 }
 EXPORT_SYMBOL_GPL(device_link_del);
@@ -830,7 +838,6 @@ void device_link_remove(void *consumer, struct device *supplier)
                return;
 
        device_links_write_lock();
-       device_pm_lock();
 
        list_for_each_entry(link, &supplier->links.consumers, s_node) {
                if (link->consumer == consumer) {
@@ -839,7 +846,6 @@ void device_link_remove(void *consumer, struct device *supplier)
                }
        }
 
-       device_pm_unlock();
        device_links_write_unlock();
 }
 EXPORT_SYMBOL_GPL(device_link_remove);
@@ -1063,7 +1069,7 @@ static ssize_t waiting_for_supplier_show(struct device *dev,
              && dev->links.need_for_probe;
        mutex_unlock(&wfs_lock);
        device_unlock(dev);
-       return sprintf(buf, "%u\n", val);
+       return sysfs_emit(buf, "%u\n", val);
 }
 static DEVICE_ATTR_RO(waiting_for_supplier);
 
@@ -1713,7 +1719,7 @@ ssize_t device_show_ulong(struct device *dev,
                          char *buf)
 {
        struct dev_ext_attribute *ea = to_ext_attr(attr);
-       return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var));
+       return sysfs_emit(buf, "%lx\n", *(unsigned long *)(ea->var));
 }
 EXPORT_SYMBOL_GPL(device_show_ulong);
 
@@ -1743,7 +1749,7 @@ ssize_t device_show_int(struct device *dev,
 {
        struct dev_ext_attribute *ea = to_ext_attr(attr);
 
-       return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var));
+       return sysfs_emit(buf, "%d\n", *(int *)(ea->var));
 }
 EXPORT_SYMBOL_GPL(device_show_int);
 
@@ -1764,7 +1770,7 @@ ssize_t device_show_bool(struct device *dev, struct device_attribute *attr,
 {
        struct dev_ext_attribute *ea = to_ext_attr(attr);
 
-       return snprintf(buf, PAGE_SIZE, "%d\n", *(bool *)(ea->var));
+       return sysfs_emit(buf, "%d\n", *(bool *)(ea->var));
 }
 EXPORT_SYMBOL_GPL(device_show_bool);
 
@@ -1792,6 +1798,8 @@ static void device_release(struct kobject *kobj)
         */
        devres_release_all(dev);
 
+       kfree(dev->dma_range_map);
+
        if (dev->release)
                dev->release(dev);
        else if (dev->type && dev->type->release)
@@ -1936,7 +1944,7 @@ static ssize_t uevent_show(struct device *dev, struct device_attribute *attr,
        struct kset *kset;
        struct kobj_uevent_env *env = NULL;
        int i;
-       size_t count = 0;
+       int len = 0;
        int retval;
 
        /* search the kset, the device belongs to */
@@ -1966,10 +1974,10 @@ static ssize_t uevent_show(struct device *dev, struct device_attribute *attr,
 
        /* copy keys to file */
        for (i = 0; i < env->envp_idx; i++)
-               count += sprintf(&buf[count], "%s\n", env->envp[i]);
+               len += sysfs_emit_at(buf, len, "%s\n", env->envp[i]);
 out:
        kfree(env);
-       return count;
+       return len;
 }
 
 static ssize_t uevent_store(struct device *dev, struct device_attribute *attr,
@@ -1996,7 +2004,7 @@ static ssize_t online_show(struct device *dev, struct device_attribute *attr,
        device_lock(dev);
        val = !dev->offline;
        device_unlock(dev);
-       return sprintf(buf, "%u\n", val);
+       return sysfs_emit(buf, "%u\n", val);
 }
 
 static ssize_t online_store(struct device *dev, struct device_attribute *attr,
@@ -3066,6 +3074,7 @@ void device_del(struct device *dev)
        struct device *parent = dev->parent;
        struct kobject *glue_dir = NULL;
        struct class_interface *class_intf;
+       unsigned int noio_flag;
 
        device_lock(dev);
        kill_device(dev);
@@ -3077,6 +3086,7 @@ void device_del(struct device *dev)
        /* Notify clients of device removal.  This call must come
         * before dpm_sysfs_remove().
         */
+       noio_flag = memalloc_noio_save();
        if (dev->bus)
                blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                                             BUS_NOTIFY_DEL_DEVICE, dev);
@@ -3118,6 +3128,7 @@ void device_del(struct device *dev)
        glue_dir = get_glue_dir(dev);
        kobject_del(&dev->kobj);
        cleanup_glue_dir(dev, glue_dir);
+       memalloc_noio_restore(noio_flag);
        put_device(parent);
 }
 EXPORT_SYMBOL_GPL(device_del);
@@ -3328,7 +3339,7 @@ struct device *device_find_child_by_name(struct device *parent,
 
        klist_iter_init(&parent->p->klist_children, &i);
        while ((child = next_device(&i)))
-               if (!strcmp(dev_name(child), name) && get_device(child))
+               if (sysfs_streq(dev_name(child), name) && get_device(child))
                        break;
        klist_iter_exit(&i);
        return child;
@@ -4065,22 +4076,21 @@ void device_shutdown(void)
  */
 
 #ifdef CONFIG_PRINTK
-static int
-create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen)
+static void
+set_dev_info(const struct device *dev, struct dev_printk_info *dev_info)
 {
        const char *subsys;
-       size_t pos = 0;
+
+       memset(dev_info, 0, sizeof(*dev_info));
 
        if (dev->class)
                subsys = dev->class->name;
        else if (dev->bus)
                subsys = dev->bus->name;
        else
-               return 0;
+               return;
 
-       pos += snprintf(hdr + pos, hdrlen - pos, "SUBSYSTEM=%s", subsys);
-       if (pos >= hdrlen)
-               goto overflow;
+       strscpy(dev_info->subsystem, subsys, sizeof(dev_info->subsystem));
 
        /*
         * Add device identifier DEVICE=:
@@ -4096,41 +4106,28 @@ create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen)
                        c = 'b';
                else
                        c = 'c';
-               pos++;
-               pos += snprintf(hdr + pos, hdrlen - pos,
-                               "DEVICE=%c%u:%u",
-                               c, MAJOR(dev->devt), MINOR(dev->devt));
+
+               snprintf(dev_info->device, sizeof(dev_info->device),
+                        "%c%u:%u", c, MAJOR(dev->devt), MINOR(dev->devt));
        } else if (strcmp(subsys, "net") == 0) {
                struct net_device *net = to_net_dev(dev);
 
-               pos++;
-               pos += snprintf(hdr + pos, hdrlen - pos,
-                               "DEVICE=n%u", net->ifindex);
+               snprintf(dev_info->device, sizeof(dev_info->device),
+                        "n%u", net->ifindex);
        } else {
-               pos++;
-               pos += snprintf(hdr + pos, hdrlen - pos,
-                               "DEVICE=+%s:%s", subsys, dev_name(dev));
+               snprintf(dev_info->device, sizeof(dev_info->device),
+                        "+%s:%s", subsys, dev_name(dev));
        }
-
-       if (pos >= hdrlen)
-               goto overflow;
-
-       return pos;
-
-overflow:
-       dev_WARN(dev, "device/subsystem name too long");
-       return 0;
 }
 
 int dev_vprintk_emit(int level, const struct device *dev,
                     const char *fmt, va_list args)
 {
-       char hdr[128];
-       size_t hdrlen;
+       struct dev_printk_info dev_info;
 
-       hdrlen = create_syslog_header(dev, hdr, sizeof(hdr));
+       set_dev_info(dev, &dev_info);
 
-       return vprintk_emit(0, level, hdrlen ? hdr : NULL, hdrlen, fmt, args);
+       return vprintk_emit(0, level, &dev_info, fmt, args);
 }
 EXPORT_SYMBOL(dev_vprintk_emit);
 
@@ -4215,13 +4212,16 @@ define_dev_printk_level(_dev_info, KERN_INFO);
  * -EPROBE_DEFER and propagate error upwards.
  * In case of -EPROBE_DEFER it sets also defer probe reason, which can be
  * checked later by reading devices_deferred debugfs attribute.
- * It replaces code sequence:
+ * It replaces code sequence::
+ *
  *     if (err != -EPROBE_DEFER)
  *             dev_err(dev, ...);
  *     else
  *             dev_dbg(dev, ...);
  *     return err;
- * with
+ *
+ * with::
+ *
  *     return dev_err_probe(dev, err, ...);
  *
  * Returns @err.
@@ -4237,10 +4237,10 @@ int dev_err_probe(const struct device *dev, int err, const char *fmt, ...)
        vaf.va = &args;
 
        if (err != -EPROBE_DEFER) {
-               dev_err(dev, "error %d: %pV", err, &vaf);
+               dev_err(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
        } else {
                device_set_deferred_probe_reason(dev, &vaf);
-               dev_dbg(dev, "error %d: %pV", err, &vaf);
+               dev_dbg(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
        }
 
        va_end(args);
@@ -4264,6 +4264,7 @@ static inline bool fwnode_is_primary(struct fwnode_handle *fwnode)
  */
 void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
 {
+       struct device *parent = dev->parent;
        struct fwnode_handle *fn = dev->fwnode;
 
        if (fwnode) {
@@ -4278,7 +4279,8 @@ void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
        } else {
                if (fwnode_is_primary(fn)) {
                        dev->fwnode = fn->secondary;
-                       fn->secondary = NULL;
+                       if (!(parent && fn == parent->fwnode))
+                               fn->secondary = ERR_PTR(-ENODEV);
                } else {
                        dev->fwnode = NULL;
                }