Commit 443d1129 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'driver-core-5.11-rc5' of...

Merge tag 'driver-core-5.11-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core

Pull driver core fixes from Greg KH:
 "Here are some small driver core fixes for 5.11-rc5 that resolve some
  reported problems:

   - revert of a -rc1 patch that was causing problems with some machines

   - device link device name collision problem fix (busses only have to
     name devices unique to their bus, not unique to all busses)

   - kernfs splice bugfixes to resolve firmware loading problems for
     Qualcomm systems.

   - other tiny driver core fixes for minor issues reported.

  All of these have been in linux-next with no reported problems"

* tag 'driver-core-5.11-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core:
  driver core: Fix device link device name collision
  driver core: Extend device_is_dependent()
  kernfs: wire up ->splice_read and ->splice_write
  kernfs: implement ->write_iter
  kernfs: implement ->read_iter
  Revert "driver core: Reorder devices on successful probe"
  Driver core: platform: Add extra error check in devm_platform_get_irqs_affinity()
  drivers core: Free dma_range_map when driver probe failed
parents 832bceef e020ff61
...@@ -5,8 +5,8 @@ Description: ...@@ -5,8 +5,8 @@ Description:
Provide a place in sysfs for the device link objects in the Provide a place in sysfs for the device link objects in the
kernel at any given time. The name of a device link directory, kernel at any given time. The name of a device link directory,
denoted as ... above, is of the form <supplier>--<consumer> denoted as ... above, is of the form <supplier>--<consumer>
where <supplier> is the supplier device name and <consumer> is where <supplier> is the supplier bus:device name and <consumer>
the consumer device name. is the consumer bus:device name.
What: /sys/class/devlink/.../auto_remove_on What: /sys/class/devlink/.../auto_remove_on
Date: May 2020 Date: May 2020
......
...@@ -4,5 +4,6 @@ Contact: Saravana Kannan <saravanak@google.com> ...@@ -4,5 +4,6 @@ Contact: Saravana Kannan <saravanak@google.com>
Description: Description:
The /sys/devices/.../consumer:<consumer> are symlinks to device The /sys/devices/.../consumer:<consumer> are symlinks to device
links where this device is the supplier. <consumer> denotes the links where this device is the supplier. <consumer> denotes the
name of the consumer in that device link. There can be zero or name of the consumer in that device link and is of the form
more of these symlinks for a given device. bus:device name. There can be zero or more of these symlinks
for a given device.
...@@ -4,5 +4,6 @@ Contact: Saravana Kannan <saravanak@google.com> ...@@ -4,5 +4,6 @@ Contact: Saravana Kannan <saravanak@google.com>
Description: Description:
The /sys/devices/.../supplier:<supplier> are symlinks to device The /sys/devices/.../supplier:<supplier> are symlinks to device
links where this device is the consumer. <supplier> denotes the links where this device is the consumer. <supplier> denotes the
name of the supplier in that device link. There can be zero or name of the supplier in that device link and is of the form
more of these symlinks for a given device. bus:device name. There can be zero or more of these symlinks
for a given device.
...@@ -208,6 +208,16 @@ int device_links_read_lock_held(void) ...@@ -208,6 +208,16 @@ int device_links_read_lock_held(void)
#endif #endif
#endif /* !CONFIG_SRCU */ #endif /* !CONFIG_SRCU */
static bool device_is_ancestor(struct device *dev, struct device *target)
{
while (target->parent) {
target = target->parent;
if (dev == target)
return true;
}
return false;
}
/** /**
* device_is_dependent - Check if one device depends on another one * device_is_dependent - Check if one device depends on another one
* @dev: Device to check dependencies for. * @dev: Device to check dependencies for.
...@@ -221,7 +231,12 @@ int device_is_dependent(struct device *dev, void *target) ...@@ -221,7 +231,12 @@ int device_is_dependent(struct device *dev, void *target)
struct device_link *link; struct device_link *link;
int ret; int ret;
if (dev == target) /*
* The "ancestors" check is needed to catch the case when the target
* device has not been completely initialized yet and it is still
* missing from the list of children of its parent device.
*/
if (dev == target || device_is_ancestor(dev, target))
return 1; return 1;
ret = device_for_each_child(dev, target, device_is_dependent); ret = device_for_each_child(dev, target, device_is_dependent);
...@@ -456,7 +471,9 @@ static int devlink_add_symlinks(struct device *dev, ...@@ -456,7 +471,9 @@ static int devlink_add_symlinks(struct device *dev,
struct device *con = link->consumer; struct device *con = link->consumer;
char *buf; char *buf;
len = max(strlen(dev_name(sup)), strlen(dev_name(con))); len = max(strlen(dev_bus_name(sup)) + strlen(dev_name(sup)),
strlen(dev_bus_name(con)) + strlen(dev_name(con)));
len += strlen(":");
len += strlen("supplier:") + 1; len += strlen("supplier:") + 1;
buf = kzalloc(len, GFP_KERNEL); buf = kzalloc(len, GFP_KERNEL);
if (!buf) if (!buf)
...@@ -470,12 +487,12 @@ static int devlink_add_symlinks(struct device *dev, ...@@ -470,12 +487,12 @@ static int devlink_add_symlinks(struct device *dev,
if (ret) if (ret)
goto err_con; goto err_con;
snprintf(buf, len, "consumer:%s", dev_name(con)); snprintf(buf, len, "consumer:%s:%s", dev_bus_name(con), dev_name(con));
ret = sysfs_create_link(&sup->kobj, &link->link_dev.kobj, buf); ret = sysfs_create_link(&sup->kobj, &link->link_dev.kobj, buf);
if (ret) if (ret)
goto err_con_dev; goto err_con_dev;
snprintf(buf, len, "supplier:%s", dev_name(sup)); snprintf(buf, len, "supplier:%s:%s", dev_bus_name(sup), dev_name(sup));
ret = sysfs_create_link(&con->kobj, &link->link_dev.kobj, buf); ret = sysfs_create_link(&con->kobj, &link->link_dev.kobj, buf);
if (ret) if (ret)
goto err_sup_dev; goto err_sup_dev;
...@@ -483,7 +500,7 @@ static int devlink_add_symlinks(struct device *dev, ...@@ -483,7 +500,7 @@ static int devlink_add_symlinks(struct device *dev,
goto out; goto out;
err_sup_dev: err_sup_dev:
snprintf(buf, len, "consumer:%s", dev_name(con)); snprintf(buf, len, "consumer:%s:%s", dev_bus_name(con), dev_name(con));
sysfs_remove_link(&sup->kobj, buf); sysfs_remove_link(&sup->kobj, buf);
err_con_dev: err_con_dev:
sysfs_remove_link(&link->link_dev.kobj, "consumer"); sysfs_remove_link(&link->link_dev.kobj, "consumer");
...@@ -506,7 +523,9 @@ static void devlink_remove_symlinks(struct device *dev, ...@@ -506,7 +523,9 @@ static void devlink_remove_symlinks(struct device *dev,
sysfs_remove_link(&link->link_dev.kobj, "consumer"); sysfs_remove_link(&link->link_dev.kobj, "consumer");
sysfs_remove_link(&link->link_dev.kobj, "supplier"); sysfs_remove_link(&link->link_dev.kobj, "supplier");
len = max(strlen(dev_name(sup)), strlen(dev_name(con))); len = max(strlen(dev_bus_name(sup)) + strlen(dev_name(sup)),
strlen(dev_bus_name(con)) + strlen(dev_name(con)));
len += strlen(":");
len += strlen("supplier:") + 1; len += strlen("supplier:") + 1;
buf = kzalloc(len, GFP_KERNEL); buf = kzalloc(len, GFP_KERNEL);
if (!buf) { if (!buf) {
...@@ -514,9 +533,9 @@ static void devlink_remove_symlinks(struct device *dev, ...@@ -514,9 +533,9 @@ static void devlink_remove_symlinks(struct device *dev,
return; return;
} }
snprintf(buf, len, "supplier:%s", dev_name(sup)); snprintf(buf, len, "supplier:%s:%s", dev_bus_name(sup), dev_name(sup));
sysfs_remove_link(&con->kobj, buf); sysfs_remove_link(&con->kobj, buf);
snprintf(buf, len, "consumer:%s", dev_name(con)); snprintf(buf, len, "consumer:%s:%s", dev_bus_name(con), dev_name(con));
sysfs_remove_link(&sup->kobj, buf); sysfs_remove_link(&sup->kobj, buf);
kfree(buf); kfree(buf);
} }
...@@ -737,8 +756,9 @@ struct device_link *device_link_add(struct device *consumer, ...@@ -737,8 +756,9 @@ struct device_link *device_link_add(struct device *consumer,
link->link_dev.class = &devlink_class; link->link_dev.class = &devlink_class;
device_set_pm_not_required(&link->link_dev); device_set_pm_not_required(&link->link_dev);
dev_set_name(&link->link_dev, "%s--%s", dev_set_name(&link->link_dev, "%s:%s--%s:%s",
dev_name(supplier), dev_name(consumer)); dev_bus_name(supplier), dev_name(supplier),
dev_bus_name(consumer), dev_name(consumer));
if (device_register(&link->link_dev)) { if (device_register(&link->link_dev)) {
put_device(consumer); put_device(consumer);
put_device(supplier); put_device(supplier);
...@@ -1808,9 +1828,7 @@ const char *dev_driver_string(const struct device *dev) ...@@ -1808,9 +1828,7 @@ const char *dev_driver_string(const struct device *dev)
* never change once they are set, so they don't need special care. * never change once they are set, so they don't need special care.
*/ */
drv = READ_ONCE(dev->driver); drv = READ_ONCE(dev->driver);
return drv ? drv->name : return drv ? drv->name : dev_bus_name(dev);
(dev->bus ? dev->bus->name :
(dev->class ? dev->class->name : ""));
} }
EXPORT_SYMBOL(dev_driver_string); EXPORT_SYMBOL(dev_driver_string);
......
...@@ -370,13 +370,6 @@ static void driver_bound(struct device *dev) ...@@ -370,13 +370,6 @@ static void driver_bound(struct device *dev)
device_pm_check_callbacks(dev); device_pm_check_callbacks(dev);
/*
* Reorder successfully probed devices to the end of the device list.
* This ensures that suspend/resume order matches probe order, which
* is usually what drivers rely on.
*/
device_pm_move_to_tail(dev);
/* /*
* Make sure the device is no longer in one of the deferred lists and * Make sure the device is no longer in one of the deferred lists and
* kick off retrying all pending devices * kick off retrying all pending devices
...@@ -619,6 +612,8 @@ static int really_probe(struct device *dev, struct device_driver *drv) ...@@ -619,6 +612,8 @@ static int really_probe(struct device *dev, struct device_driver *drv)
else if (drv->remove) else if (drv->remove)
drv->remove(dev); drv->remove(dev);
probe_failed: probe_failed:
kfree(dev->dma_range_map);
dev->dma_range_map = NULL;
if (dev->bus) if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier, blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_DRIVER_NOT_BOUND, dev); BUS_NOTIFY_DRIVER_NOT_BOUND, dev);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/sched/mm.h> #include <linux/sched/mm.h>
#include <linux/fsnotify.h> #include <linux/fsnotify.h>
#include <linux/uio.h>
#include "kernfs-internal.h" #include "kernfs-internal.h"
...@@ -180,11 +181,10 @@ static const struct seq_operations kernfs_seq_ops = { ...@@ -180,11 +181,10 @@ static const struct seq_operations kernfs_seq_ops = {
* it difficult to use seq_file. Implement simplistic custom buffering for * it difficult to use seq_file. Implement simplistic custom buffering for
* bin files. * bin files.
*/ */
static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of, static ssize_t kernfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
char __user *user_buf, size_t count,
loff_t *ppos)
{ {
ssize_t len = min_t(size_t, count, PAGE_SIZE); struct kernfs_open_file *of = kernfs_of(iocb->ki_filp);
ssize_t len = min_t(size_t, iov_iter_count(iter), PAGE_SIZE);
const struct kernfs_ops *ops; const struct kernfs_ops *ops;
char *buf; char *buf;
...@@ -210,7 +210,7 @@ static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of, ...@@ -210,7 +210,7 @@ static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of,
of->event = atomic_read(&of->kn->attr.open->event); of->event = atomic_read(&of->kn->attr.open->event);
ops = kernfs_ops(of->kn); ops = kernfs_ops(of->kn);
if (ops->read) if (ops->read)
len = ops->read(of, buf, len, *ppos); len = ops->read(of, buf, len, iocb->ki_pos);
else else
len = -EINVAL; len = -EINVAL;
...@@ -220,12 +220,12 @@ static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of, ...@@ -220,12 +220,12 @@ static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of,
if (len < 0) if (len < 0)
goto out_free; goto out_free;
if (copy_to_user(user_buf, buf, len)) { if (copy_to_iter(buf, len, iter) != len) {
len = -EFAULT; len = -EFAULT;
goto out_free; goto out_free;
} }
*ppos += len; iocb->ki_pos += len;
out_free: out_free:
if (buf == of->prealloc_buf) if (buf == of->prealloc_buf)
...@@ -235,31 +235,14 @@ static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of, ...@@ -235,31 +235,14 @@ static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of,
return len; return len;
} }
/** static ssize_t kernfs_fop_read_iter(struct kiocb *iocb, struct iov_iter *iter)
* kernfs_fop_read - kernfs vfs read callback
* @file: file pointer
* @user_buf: data to write
* @count: number of bytes
* @ppos: starting offset
*/
static ssize_t kernfs_fop_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{ {
struct kernfs_open_file *of = kernfs_of(file); if (kernfs_of(iocb->ki_filp)->kn->flags & KERNFS_HAS_SEQ_SHOW)
return seq_read_iter(iocb, iter);
if (of->kn->flags & KERNFS_HAS_SEQ_SHOW) return kernfs_file_read_iter(iocb, iter);
return seq_read(file, user_buf, count, ppos);
else
return kernfs_file_direct_read(of, user_buf, count, ppos);
} }
/** /*
* kernfs_fop_write - kernfs vfs write callback
* @file: file pointer
* @user_buf: data to write
* @count: number of bytes
* @ppos: starting offset
*
* Copy data in from userland and pass it to the matching kernfs write * Copy data in from userland and pass it to the matching kernfs write
* operation. * operation.
* *
...@@ -269,20 +252,18 @@ static ssize_t kernfs_fop_read(struct file *file, char __user *user_buf, ...@@ -269,20 +252,18 @@ static ssize_t kernfs_fop_read(struct file *file, char __user *user_buf,
* modify only the the value you're changing, then write entire buffer * modify only the the value you're changing, then write entire buffer
* back. * back.
*/ */
static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf, static ssize_t kernfs_fop_write_iter(struct kiocb *iocb, struct iov_iter *iter)
size_t count, loff_t *ppos)
{ {
struct kernfs_open_file *of = kernfs_of(file); struct kernfs_open_file *of = kernfs_of(iocb->ki_filp);
ssize_t len = iov_iter_count(iter);
const struct kernfs_ops *ops; const struct kernfs_ops *ops;
ssize_t len;
char *buf; char *buf;
if (of->atomic_write_len) { if (of->atomic_write_len) {
len = count;
if (len > of->atomic_write_len) if (len > of->atomic_write_len)
return -E2BIG; return -E2BIG;
} else { } else {
len = min_t(size_t, count, PAGE_SIZE); len = min_t(size_t, len, PAGE_SIZE);
} }
buf = of->prealloc_buf; buf = of->prealloc_buf;
...@@ -293,7 +274,7 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf, ...@@ -293,7 +274,7 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf,
if (!buf) if (!buf)
return -ENOMEM; return -ENOMEM;
if (copy_from_user(buf, user_buf, len)) { if (copy_from_iter(buf, len, iter) != len) {
len = -EFAULT; len = -EFAULT;
goto out_free; goto out_free;
} }
...@@ -312,7 +293,7 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf, ...@@ -312,7 +293,7 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf,
ops = kernfs_ops(of->kn); ops = kernfs_ops(of->kn);
if (ops->write) if (ops->write)
len = ops->write(of, buf, len, *ppos); len = ops->write(of, buf, len, iocb->ki_pos);
else else
len = -EINVAL; len = -EINVAL;
...@@ -320,7 +301,7 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf, ...@@ -320,7 +301,7 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf,
mutex_unlock(&of->mutex); mutex_unlock(&of->mutex);
if (len > 0) if (len > 0)
*ppos += len; iocb->ki_pos += len;
out_free: out_free:
if (buf == of->prealloc_buf) if (buf == of->prealloc_buf)
...@@ -673,7 +654,7 @@ static int kernfs_fop_open(struct inode *inode, struct file *file) ...@@ -673,7 +654,7 @@ static int kernfs_fop_open(struct inode *inode, struct file *file)
/* /*
* Write path needs to atomic_write_len outside active reference. * Write path needs to atomic_write_len outside active reference.
* Cache it in open_file. See kernfs_fop_write() for details. * Cache it in open_file. See kernfs_fop_write_iter() for details.
*/ */
of->atomic_write_len = ops->atomic_write_len; of->atomic_write_len = ops->atomic_write_len;
...@@ -960,14 +941,16 @@ void kernfs_notify(struct kernfs_node *kn) ...@@ -960,14 +941,16 @@ void kernfs_notify(struct kernfs_node *kn)
EXPORT_SYMBOL_GPL(kernfs_notify); EXPORT_SYMBOL_GPL(kernfs_notify);
const struct file_operations kernfs_file_fops = { const struct file_operations kernfs_file_fops = {
.read = kernfs_fop_read, .read_iter = kernfs_fop_read_iter,
.write = kernfs_fop_write, .write_iter = kernfs_fop_write_iter,
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
.mmap = kernfs_fop_mmap, .mmap = kernfs_fop_mmap,
.open = kernfs_fop_open, .open = kernfs_fop_open,
.release = kernfs_fop_release, .release = kernfs_fop_release,
.poll = kernfs_fop_poll, .poll = kernfs_fop_poll,
.fsync = noop_fsync, .fsync = noop_fsync,
.splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
}; };
/** /**
......
...@@ -609,6 +609,18 @@ static inline const char *dev_name(const struct device *dev) ...@@ -609,6 +609,18 @@ static inline const char *dev_name(const struct device *dev)
return kobject_name(&dev->kobj); return kobject_name(&dev->kobj);
} }
/**
* dev_bus_name - Return a device's bus/class name, if at all possible
* @dev: struct device to get the bus/class name of
*
* Will return the name of the bus/class the device is attached to. If it is
* not attached to a bus/class, an empty string will be returned.
*/
static inline const char *dev_bus_name(const struct device *dev)
{
return dev->bus ? dev->bus->name : (dev->class ? dev->class->name : "");
}
__printf(2, 3) int dev_set_name(struct device *dev, const char *name, ...); __printf(2, 3) int dev_set_name(struct device *dev, const char *name, ...);
#ifdef CONFIG_NUMA #ifdef CONFIG_NUMA
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment