Commit 7240153a authored by Linus Torvalds's avatar Linus Torvalds

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

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

Pull driver core updates from Greg KH:
 "Here is the big driver core updates for 5.11-rc1

  This time there was a lot of different work happening here for some
  reason:

   - redo of the fwnode link logic, speeding it up greatly

   - auxiliary bus added (this was a tag that will be pulled in from
     other trees/maintainers this merge window as well, as driver
     subsystems started to rely on it)

   - platform driver core cleanups on the way to fixing some long-time
     api updates in future releases

   - minor fixes and tweaks.

  All have been in linux-next with no (finally) reported issues. Testing
  there did helped in shaking issues out a lot :)"

* tag 'driver-core-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (39 commits)
  driver core: platform: don't oops in platform_shutdown() on unbound devices
  ACPI: Use fwnode_init() to set up fwnode
  misc: pvpanic: Replace OF headers by mod_devicetable.h
  misc: pvpanic: Combine ACPI and platform drivers
  usb: host: sl811: Switch to use platform_get_mem_or_io()
  vfio: platform: Switch to use platform_get_mem_or_io()
  driver core: platform: Introduce platform_get_mem_or_io()
  dyndbg: fix use before null check
  soc: fix comment for freeing soc_dev_attr
  driver core: platform: use bus_type functions
  driver core: platform: change logic implementing platform_driver_probe
  driver core: platform: reorder functions
  driver core: make driver_probe_device() static
  driver core: Fix a couple of typos
  driver core: Reorder devices on successful probe
  driver core: Delete pointless parameter in fwnode_operations.add_links
  driver core: Refactor fw_devlink feature
  efi: Update implementation of add_links() to create fwnode links
  of: property: Update implementation of add_links() to create fwnode links
  driver core: Use device's fwnode to check if it is waiting for suppliers
  ...
parents 157f8098 46e85af0
...@@ -76,7 +76,7 @@ static bool acpi_nondev_subnode_extract(const union acpi_object *desc, ...@@ -76,7 +76,7 @@ static bool acpi_nondev_subnode_extract(const union acpi_object *desc,
return false; return false;
dn->name = link->package.elements[0].string.pointer; dn->name = link->package.elements[0].string.pointer;
dn->fwnode.ops = &acpi_data_fwnode_ops; fwnode_init(&dn->fwnode, &acpi_data_fwnode_ops);
dn->parent = parent; dn->parent = parent;
INIT_LIST_HEAD(&dn->data.properties); INIT_LIST_HEAD(&dn->data.properties);
INIT_LIST_HEAD(&dn->data.subnodes); INIT_LIST_HEAD(&dn->data.subnodes);
......
...@@ -1589,7 +1589,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, ...@@ -1589,7 +1589,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
device->device_type = type; device->device_type = type;
device->handle = handle; device->handle = handle;
device->parent = acpi_bus_get_parent(handle); device->parent = acpi_bus_get_parent(handle);
device->fwnode.ops = &acpi_device_fwnode_ops; fwnode_init(&device->fwnode, &acpi_device_fwnode_ops);
acpi_set_device_status(device, sta); acpi_set_device_status(device, sta);
acpi_device_get_busid(device); acpi_device_get_busid(device);
acpi_set_pnp_ids(handle, &device->pnp, type); acpi_set_pnp_ids(handle, &device->pnp, type);
......
...@@ -92,10 +92,15 @@ static int auxiliary_bus_remove(struct device *dev) ...@@ -92,10 +92,15 @@ static int auxiliary_bus_remove(struct device *dev)
static void auxiliary_bus_shutdown(struct device *dev) static void auxiliary_bus_shutdown(struct device *dev)
{ {
struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver); struct auxiliary_driver *auxdrv = NULL;
struct auxiliary_device *auxdev = to_auxiliary_dev(dev); struct auxiliary_device *auxdev;
if (dev->driver) {
auxdrv = to_auxiliary_drv(dev->driver);
auxdev = to_auxiliary_dev(dev);
}
if (auxdrv->shutdown) if (auxdrv && auxdrv->shutdown)
auxdrv->shutdown(auxdev); auxdrv->shutdown(auxdev);
} }
......
...@@ -133,7 +133,6 @@ extern void device_release_driver_internal(struct device *dev, ...@@ -133,7 +133,6 @@ extern void device_release_driver_internal(struct device *dev,
struct device *parent); struct device *parent);
extern void driver_detach(struct device_driver *drv); extern void driver_detach(struct device_driver *drv);
extern int driver_probe_device(struct device_driver *drv, struct device *dev);
extern void driver_deferred_probe_del(struct device *dev); extern void driver_deferred_probe_del(struct device *dev);
extern void device_set_deferred_probe_reason(const struct device *dev, extern void device_set_deferred_probe_reason(const struct device *dev,
struct va_format *vaf); struct va_format *vaf);
......
...@@ -210,7 +210,7 @@ static void class_create_release(struct class *cls) ...@@ -210,7 +210,7 @@ static void class_create_release(struct class *cls)
} }
/** /**
* class_create - create a struct class structure * __class_create - create a struct class structure
* @owner: pointer to the module that is to "own" this struct class * @owner: pointer to the module that is to "own" this struct class
* @name: pointer to a string for the name of this class. * @name: pointer to a string for the name of this class.
* @key: the lock_class_key for this class; used by mutex lock debugging * @key: the lock_class_key for this class; used by mutex lock debugging
......
This diff is collapsed.
...@@ -370,6 +370,13 @@ static void driver_bound(struct device *dev) ...@@ -370,6 +370,13 @@ 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
...@@ -717,7 +724,7 @@ EXPORT_SYMBOL_GPL(wait_for_device_probe); ...@@ -717,7 +724,7 @@ EXPORT_SYMBOL_GPL(wait_for_device_probe);
* *
* If the device has a parent, runtime-resume the parent before driver probing. * If the device has a parent, runtime-resume the parent before driver probing.
*/ */
int driver_probe_device(struct device_driver *drv, struct device *dev) static int driver_probe_device(struct device_driver *drv, struct device *dev)
{ {
int ret = 0; int ret = 0;
......
...@@ -149,7 +149,7 @@ void * __devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, int nid ...@@ -149,7 +149,7 @@ void * __devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, int nid
EXPORT_SYMBOL_GPL(__devres_alloc_node); EXPORT_SYMBOL_GPL(__devres_alloc_node);
#else #else
/** /**
* devres_alloc - Allocate device resource data * devres_alloc_node - Allocate device resource data
* @release: Release function devres will be associated with * @release: Release function devres will be associated with
* @size: Allocation size * @size: Allocation size
* @gfp: Allocation flags * @gfp: Allocation flags
......
...@@ -128,7 +128,7 @@ static ssize_t timeout_show(struct class *class, struct class_attribute *attr, ...@@ -128,7 +128,7 @@ static ssize_t timeout_show(struct class *class, struct class_attribute *attr,
} }
/** /**
* firmware_timeout_store() - set number of seconds to wait for firmware * timeout_store() - set number of seconds to wait for firmware
* @class: device class pointer * @class: device class pointer
* @attr: device attribute pointer * @attr: device attribute pointer
* @buf: buffer to scan for timeout value * @buf: buffer to scan for timeout value
......
This diff is collapsed.
...@@ -614,6 +614,31 @@ struct fwnode_handle *fwnode_get_next_parent(struct fwnode_handle *fwnode) ...@@ -614,6 +614,31 @@ struct fwnode_handle *fwnode_get_next_parent(struct fwnode_handle *fwnode)
} }
EXPORT_SYMBOL_GPL(fwnode_get_next_parent); EXPORT_SYMBOL_GPL(fwnode_get_next_parent);
/**
* fwnode_get_next_parent_dev - Find device of closest ancestor fwnode
* @fwnode: firmware node
*
* Given a firmware node (@fwnode), this function finds its closest ancestor
* firmware node that has a corresponding struct device and returns that struct
* device.
*
* The caller of this function is expected to call put_device() on the returned
* device when they are done.
*/
struct device *fwnode_get_next_parent_dev(struct fwnode_handle *fwnode)
{
struct device *dev = NULL;
fwnode_handle_get(fwnode);
do {
fwnode = fwnode_get_next_parent(fwnode);
if (fwnode)
dev = get_dev_from_fwnode(fwnode);
} while (fwnode && !dev);
fwnode_handle_put(fwnode);
return dev;
}
/** /**
* fwnode_count_parents - Return the number of parents a node has * fwnode_count_parents - Return the number of parents a node has
* @fwnode: The node the parents of which are to be counted * @fwnode: The node the parents of which are to be counted
...@@ -660,6 +685,33 @@ struct fwnode_handle *fwnode_get_nth_parent(struct fwnode_handle *fwnode, ...@@ -660,6 +685,33 @@ struct fwnode_handle *fwnode_get_nth_parent(struct fwnode_handle *fwnode,
} }
EXPORT_SYMBOL_GPL(fwnode_get_nth_parent); EXPORT_SYMBOL_GPL(fwnode_get_nth_parent);
/**
* fwnode_is_ancestor_of - Test if @test_ancestor is ancestor of @test_child
* @test_ancestor: Firmware which is tested for being an ancestor
* @test_child: Firmware which is tested for being the child
*
* A node is considered an ancestor of itself too.
*
* Returns true if @test_ancestor is an ancestor of @test_child.
* Otherwise, returns false.
*/
bool fwnode_is_ancestor_of(struct fwnode_handle *test_ancestor,
struct fwnode_handle *test_child)
{
if (!test_ancestor)
return false;
fwnode_handle_get(test_child);
while (test_child) {
if (test_child == test_ancestor) {
fwnode_handle_put(test_child);
return true;
}
test_child = fwnode_get_next_parent(test_child);
}
return false;
}
/** /**
* fwnode_get_next_child_node - Return the next child node handle for a node * fwnode_get_next_child_node - Return the next child node handle for a node
* @fwnode: Firmware node to find the next child node for. * @fwnode: Firmware node to find the next child node for.
......
...@@ -168,7 +168,7 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr ...@@ -168,7 +168,7 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr
} }
EXPORT_SYMBOL_GPL(soc_device_register); EXPORT_SYMBOL_GPL(soc_device_register);
/* Ensure soc_dev->attr is freed prior to calling soc_device_unregister. */ /* Ensure soc_dev->attr is freed after calling soc_device_unregister. */
void soc_device_unregister(struct soc_device *soc_dev) void soc_device_unregister(struct soc_device *soc_dev)
{ {
device_unregister(&soc_dev->dev); device_unregister(&soc_dev->dev);
......
...@@ -653,7 +653,7 @@ swnode_register(const struct software_node *node, struct swnode *parent, ...@@ -653,7 +653,7 @@ swnode_register(const struct software_node *node, struct swnode *parent,
swnode->parent = parent; swnode->parent = parent;
swnode->allocated = allocated; swnode->allocated = allocated;
swnode->kobj.kset = swnode_kset; swnode->kobj.kset = swnode_kset;
swnode->fwnode.ops = &software_node_ops; fwnode_init(&swnode->fwnode, &software_node_ops);
ida_init(&swnode->child_ids); ida_init(&swnode->child_ids);
INIT_LIST_HEAD(&swnode->entry); INIT_LIST_HEAD(&swnode->entry);
......
...@@ -316,11 +316,9 @@ static struct device_node *find_pci_overlap_node(void) ...@@ -316,11 +316,9 @@ static struct device_node *find_pci_overlap_node(void)
* resource reservation conflict on the memory window that the efifb * resource reservation conflict on the memory window that the efifb
* framebuffer steals from the PCIe host bridge. * framebuffer steals from the PCIe host bridge.
*/ */
static int efifb_add_links(const struct fwnode_handle *fwnode, static int efifb_add_links(struct fwnode_handle *fwnode)
struct device *dev)
{ {
struct device_node *sup_np; struct device_node *sup_np;
struct device *sup_dev;
sup_np = find_pci_overlap_node(); sup_np = find_pci_overlap_node();
...@@ -331,27 +329,9 @@ static int efifb_add_links(const struct fwnode_handle *fwnode, ...@@ -331,27 +329,9 @@ static int efifb_add_links(const struct fwnode_handle *fwnode,
if (!sup_np) if (!sup_np)
return 0; return 0;
sup_dev = get_dev_from_fwnode(&sup_np->fwnode); fwnode_link_add(fwnode, of_fwnode_handle(sup_np));
of_node_put(sup_np); of_node_put(sup_np);
/*
* Return -ENODEV if the PCI graphics controller device hasn't been
* registered yet. This ensures that efifb isn't allowed to probe
* and this function is retried again when new devices are
* registered.
*/
if (!sup_dev)
return -ENODEV;
/*
* If this fails, retrying this function at a later point won't
* change anything. So, don't return an error after this.
*/
if (!device_link_add(dev, sup_dev, fw_devlink_get_flags()))
dev_warn(dev, "device_link_add() failed\n");
put_device(sup_dev);
return 0; return 0;
} }
...@@ -359,9 +339,7 @@ static const struct fwnode_operations efifb_fwnode_ops = { ...@@ -359,9 +339,7 @@ static const struct fwnode_operations efifb_fwnode_ops = {
.add_links = efifb_add_links, .add_links = efifb_add_links,
}; };
static struct fwnode_handle efifb_fwnode = { static struct fwnode_handle efifb_fwnode;
.ops = &efifb_fwnode_ops,
};
static int __init register_gop_device(void) static int __init register_gop_device(void)
{ {
...@@ -375,8 +353,10 @@ static int __init register_gop_device(void) ...@@ -375,8 +353,10 @@ static int __init register_gop_device(void)
if (!pd) if (!pd)
return -ENOMEM; return -ENOMEM;
if (IS_ENABLED(CONFIG_PCI)) if (IS_ENABLED(CONFIG_PCI)) {
fwnode_init(&efifb_fwnode, &efifb_fwnode_ops);
pd->dev.fwnode = &efifb_fwnode; pd->dev.fwnode = &efifb_fwnode;
}
err = platform_device_add_data(pd, &screen_info, sizeof(screen_info)); err = platform_device_add_data(pd, &screen_info, sizeof(screen_info));
if (err) if (err)
......
...@@ -8,14 +8,14 @@ ...@@ -8,14 +8,14 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/acpi.h> #include <linux/io.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/types.h> #include <linux/types.h>
#include <uapi/misc/pvpanic.h> #include <uapi/misc/pvpanic.h>
static void __iomem *base; static void __iomem *base;
...@@ -49,101 +49,16 @@ static struct notifier_block pvpanic_panic_nb = { ...@@ -49,101 +49,16 @@ static struct notifier_block pvpanic_panic_nb = {
.priority = 1, /* let this called before broken drm_fb_helper */ .priority = 1, /* let this called before broken drm_fb_helper */
}; };
#ifdef CONFIG_ACPI
static int pvpanic_add(struct acpi_device *device);
static int pvpanic_remove(struct acpi_device *device);
static const struct acpi_device_id pvpanic_device_ids[] = {
{ "QEMU0001", 0 },
{ "", 0 }
};
MODULE_DEVICE_TABLE(acpi, pvpanic_device_ids);
static struct acpi_driver pvpanic_driver = {
.name = "pvpanic",
.class = "QEMU",
.ids = pvpanic_device_ids,
.ops = {
.add = pvpanic_add,
.remove = pvpanic_remove,
},
.owner = THIS_MODULE,
};
static acpi_status
pvpanic_walk_resources(struct acpi_resource *res, void *context)
{
struct resource r;
if (acpi_dev_resource_io(res, &r)) {
#ifdef CONFIG_HAS_IOPORT_MAP
base = ioport_map(r.start, resource_size(&r));
return AE_OK;
#else
return AE_ERROR;
#endif
} else if (acpi_dev_resource_memory(res, &r)) {
base = ioremap(r.start, resource_size(&r));
return AE_OK;
}
return AE_ERROR;
}
static int pvpanic_add(struct acpi_device *device)
{
int ret;
ret = acpi_bus_get_status(device);
if (ret < 0)
return ret;
if (!device->status.enabled || !device->status.functional)
return -ENODEV;
acpi_walk_resources(device->handle, METHOD_NAME__CRS,
pvpanic_walk_resources, NULL);
if (!base)
return -ENODEV;
atomic_notifier_chain_register(&panic_notifier_list,
&pvpanic_panic_nb);
return 0;
}
static int pvpanic_remove(struct acpi_device *device)
{
atomic_notifier_chain_unregister(&panic_notifier_list,
&pvpanic_panic_nb);
iounmap(base);
return 0;
}
static int pvpanic_register_acpi_driver(void)
{
return acpi_bus_register_driver(&pvpanic_driver);
}
static void pvpanic_unregister_acpi_driver(void)
{
acpi_bus_unregister_driver(&pvpanic_driver);
}
#else
static int pvpanic_register_acpi_driver(void)
{
return -ENODEV;
}
static void pvpanic_unregister_acpi_driver(void) {}
#endif
static int pvpanic_mmio_probe(struct platform_device *pdev) static int pvpanic_mmio_probe(struct platform_device *pdev)
{ {
base = devm_platform_ioremap_resource(pdev, 0); struct device *dev = &pdev->dev;
struct resource *res;
res = platform_get_mem_or_io(pdev, 0);
if (res && resource_type(res) == IORESOURCE_IO)
base = devm_ioport_map(dev, res->start, resource_size(res));
else
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base)) if (IS_ERR(base))
return PTR_ERR(base); return PTR_ERR(base);
...@@ -167,30 +82,19 @@ static const struct of_device_id pvpanic_mmio_match[] = { ...@@ -167,30 +82,19 @@ static const struct of_device_id pvpanic_mmio_match[] = {
{} {}
}; };
static const struct acpi_device_id pvpanic_device_ids[] = {
{ "QEMU0001", 0 },
{ "", 0 }
};
MODULE_DEVICE_TABLE(acpi, pvpanic_device_ids);
static struct platform_driver pvpanic_mmio_driver = { static struct platform_driver pvpanic_mmio_driver = {
.driver = { .driver = {
.name = "pvpanic-mmio", .name = "pvpanic-mmio",
.of_match_table = pvpanic_mmio_match, .of_match_table = pvpanic_mmio_match,
.acpi_match_table = pvpanic_device_ids,
}, },
.probe = pvpanic_mmio_probe, .probe = pvpanic_mmio_probe,
.remove = pvpanic_mmio_remove, .remove = pvpanic_mmio_remove,
}; };
module_platform_driver(pvpanic_mmio_driver);
static int __init pvpanic_mmio_init(void)
{
if (acpi_disabled)
return platform_driver_register(&pvpanic_mmio_driver);
else
return pvpanic_register_acpi_driver();
}
static void __exit pvpanic_mmio_exit(void)
{
if (acpi_disabled)
platform_driver_unregister(&pvpanic_mmio_driver);
else
pvpanic_unregister_acpi_driver();
}
module_init(pvpanic_mmio_init);
module_exit(pvpanic_mmio_exit);
...@@ -356,6 +356,7 @@ void of_node_release(struct kobject *kobj) ...@@ -356,6 +356,7 @@ void of_node_release(struct kobject *kobj)
property_list_free(node->properties); property_list_free(node->properties);
property_list_free(node->deadprops); property_list_free(node->deadprops);
fwnode_links_purge(of_fwnode_handle(node));
kfree(node->full_name); kfree(node->full_name);
kfree(node->data); kfree(node->data);
......
...@@ -538,9 +538,7 @@ static int __init of_platform_default_populate_init(void) ...@@ -538,9 +538,7 @@ static int __init of_platform_default_populate_init(void)
} }
/* Populate everything else. */ /* Populate everything else. */
fw_devlink_pause();
of_platform_default_populate(NULL, NULL, NULL); of_platform_default_populate(NULL, NULL, NULL);
fw_devlink_resume();
return 0; return 0;
} }
......
...@@ -1038,33 +1038,9 @@ static bool of_is_ancestor_of(struct device_node *test_ancestor, ...@@ -1038,33 +1038,9 @@ static bool of_is_ancestor_of(struct device_node *test_ancestor,
} }
/** /**
* of_get_next_parent_dev - Add device link to supplier from supplier phandle * of_link_to_phandle - Add fwnode link to supplier from supplier phandle
* @np: device tree node * @con_np: consumer device tree node
* * @sup_np: supplier device tree node
* Given a device tree node (@np), this function finds its closest ancestor
* device tree node that has a corresponding struct device.
*
* The caller of this function is expected to call put_device() on the returned
* device when they are done.
*/
static struct device *of_get_next_parent_dev(struct device_node *np)
{
struct device *dev = NULL;
of_node_get(np);
do {
np = of_get_next_parent(np);
if (np)
dev = get_dev_from_fwnode(&np->fwnode);
} while (np && !dev);
of_node_put(np);
return dev;
}
/**
* of_link_to_phandle - Add device link to supplier from supplier phandle
* @dev: consumer device
* @sup_np: phandle to supplier device tree node
* *
* Given a phandle to a supplier device tree node (@sup_np), this function * Given a phandle to a supplier device tree node (@sup_np), this function
* finds the device that owns the supplier device tree node and creates a * finds the device that owns the supplier device tree node and creates a
...@@ -1074,16 +1050,14 @@ static struct device *of_get_next_parent_dev(struct device_node *np) ...@@ -1074,16 +1050,14 @@ static struct device *of_get_next_parent_dev(struct device_node *np)
* cases, it returns an error. * cases, it returns an error.
* *
* Returns: * Returns:
* - 0 if link successfully created to supplier * - 0 if fwnode link successfully created to supplier
* - -EAGAIN if linking to the supplier should be reattempted
* - -EINVAL if the supplier link is invalid and should not be created * - -EINVAL if the supplier link is invalid and should not be created
* - -ENODEV if there is no device that corresponds to the supplier phandle * - -ENODEV if struct device will never be create for supplier
*/ */
static int of_link_to_phandle(struct device *dev, struct device_node *sup_np, static int of_link_to_phandle(struct device_node *con_np,
u32 dl_flags) struct device_node *sup_np)
{ {
struct device *sup_dev, *sup_par_dev; struct device *sup_dev;
int ret = 0;
struct device_node *tmp_np = sup_np; struct device_node *tmp_np = sup_np;
of_node_get(sup_np); of_node_get(sup_np);
...@@ -1106,7 +1080,8 @@ static int of_link_to_phandle(struct device *dev, struct device_node *sup_np, ...@@ -1106,7 +1080,8 @@ static int of_link_to_phandle(struct device *dev, struct device_node *sup_np,
} }
if (!sup_np) { if (!sup_np) {
dev_dbg(dev, "Not linking to %pOFP - No device\n", tmp_np); pr_debug("Not linking %pOFP to %pOFP - No device\n",
con_np, tmp_np);
return -ENODEV; return -ENODEV;
} }
...@@ -1115,53 +1090,30 @@ static int of_link_to_phandle(struct device *dev, struct device_node *sup_np, ...@@ -1115,53 +1090,30 @@ static int of_link_to_phandle(struct device *dev, struct device_node *sup_np,
* descendant nodes. By definition, a child node can't be a functional * descendant nodes. By definition, a child node can't be a functional
* dependency for the parent node. * dependency for the parent node.
*/ */
if (of_is_ancestor_of(dev->of_node, sup_np)) { if (of_is_ancestor_of(con_np, sup_np)) {
dev_dbg(dev, "Not linking to %pOFP - is descendant\n", sup_np); pr_debug("Not linking %pOFP to %pOFP - is descendant\n",
con_np, sup_np);
of_node_put(sup_np); of_node_put(sup_np);
return -EINVAL; return -EINVAL;
} }
/*
* Don't create links to "early devices" that won't have struct devices
* created for them.
*/
sup_dev = get_dev_from_fwnode(&sup_np->fwnode); sup_dev = get_dev_from_fwnode(&sup_np->fwnode);
if (!sup_dev && of_node_check_flag(sup_np, OF_POPULATED)) { if (!sup_dev && of_node_check_flag(sup_np, OF_POPULATED)) {
/* Early device without struct device. */ pr_debug("Not linking %pOFP to %pOFP - No struct device\n",
dev_dbg(dev, "Not linking to %pOFP - No struct device\n", con_np, sup_np);
sup_np);
of_node_put(sup_np); of_node_put(sup_np);
return -ENODEV; return -ENODEV;
} else if (!sup_dev) {
/*
* DL_FLAG_SYNC_STATE_ONLY doesn't block probing and supports
* cycles. So cycle detection isn't necessary and shouldn't be
* done.
*/
if (dl_flags & DL_FLAG_SYNC_STATE_ONLY) {
of_node_put(sup_np);
return -EAGAIN;
}
sup_par_dev = of_get_next_parent_dev(sup_np);
if (sup_par_dev && device_is_dependent(dev, sup_par_dev)) {
/* Cyclic dependency detected, don't try to link */
dev_dbg(dev, "Not linking to %pOFP - cycle detected\n",
sup_np);
ret = -EINVAL;
} else {
/*
* Can't check for cycles or no cycles. So let's try
* again later.
*/
ret = -EAGAIN;
} }
put_device(sup_dev);
fwnode_link_add(of_fwnode_handle(con_np), of_fwnode_handle(sup_np));
of_node_put(sup_np); of_node_put(sup_np);
put_device(sup_par_dev);
return ret; return 0;
}
of_node_put(sup_np);
if (!device_link_add(dev, sup_dev, dl_flags))
ret = -EINVAL;
put_device(sup_dev);
return ret;
} }
/** /**
...@@ -1361,37 +1313,29 @@ static const struct supplier_bindings of_supplier_bindings[] = { ...@@ -1361,37 +1313,29 @@ static const struct supplier_bindings of_supplier_bindings[] = {
* that list phandles to suppliers. If @prop_name isn't one, this function * that list phandles to suppliers. If @prop_name isn't one, this function
* doesn't do anything. * doesn't do anything.
* *
* If @prop_name is one, this function attempts to create device links from the * If @prop_name is one, this function attempts to create fwnode links from the
* consumer device @dev to all the devices of the suppliers listed in * consumer device tree node @con_np to all the suppliers device tree nodes
* @prop_name. * listed in @prop_name.
* *
* Any failed attempt to create a device link will NOT result in an immediate * Any failed attempt to create a fwnode link will NOT result in an immediate
* return. of_link_property() must create links to all the available supplier * return. of_link_property() must create links to all the available supplier
* devices even when attempts to create a link to one or more suppliers fail. * device tree nodes even when attempts to create a link to one or more
* suppliers fail.
*/ */
static int of_link_property(struct device *dev, struct device_node *con_np, static int of_link_property(struct device_node *con_np, const char *prop_name)
const char *prop_name)
{ {
struct device_node *phandle; struct device_node *phandle;
const struct supplier_bindings *s = of_supplier_bindings; const struct supplier_bindings *s = of_supplier_bindings;
unsigned int i = 0; unsigned int i = 0;
bool matched = false; bool matched = false;
int ret = 0; int ret = 0;
u32 dl_flags;
if (dev->of_node == con_np)
dl_flags = fw_devlink_get_flags();
else
dl_flags = DL_FLAG_SYNC_STATE_ONLY;
/* Do not stop at first failed link, link all available suppliers. */ /* Do not stop at first failed link, link all available suppliers. */
while (!matched && s->parse_prop) { while (!matched && s->parse_prop) {
while ((phandle = s->parse_prop(con_np, prop_name, i))) { while ((phandle = s->parse_prop(con_np, prop_name, i))) {
matched = true; matched = true;
i++; i++;
if (of_link_to_phandle(dev, phandle, dl_flags) of_link_to_phandle(con_np, phandle);
== -EAGAIN)
ret = -EAGAIN;
of_node_put(phandle); of_node_put(phandle);
} }
s++; s++;
...@@ -1399,31 +1343,18 @@ static int of_link_property(struct device *dev, struct device_node *con_np, ...@@ -1399,31 +1343,18 @@ static int of_link_property(struct device *dev, struct device_node *con_np,
return ret; return ret;
} }
static int of_link_to_suppliers(struct device *dev, static int of_fwnode_add_links(struct fwnode_handle *fwnode)
struct device_node *con_np)
{ {
struct device_node *child;
struct property *p; struct property *p;
int ret = 0; struct device_node *con_np = to_of_node(fwnode);
for_each_property_of_node(con_np, p) if (!con_np)
if (of_link_property(dev, con_np, p->name)) return -EINVAL;
ret = -ENODEV;
for_each_available_child_of_node(con_np, child)
if (of_link_to_suppliers(dev, child) && !ret)
ret = -EAGAIN;
return ret; for_each_property_of_node(con_np, p)
} of_link_property(con_np, p->name);
static int of_fwnode_add_links(const struct fwnode_handle *fwnode,
struct device *dev)
{
if (unlikely(!is_of_node(fwnode)))
return 0; return 0;
return of_link_to_suppliers(dev, to_of_node(fwnode));
} }
const struct fwnode_operations of_fwnode_ops = { const struct fwnode_operations of_fwnode_ops = {
......
...@@ -1614,12 +1614,18 @@ sl811h_probe(struct platform_device *dev) ...@@ -1614,12 +1614,18 @@ sl811h_probe(struct platform_device *dev)
void __iomem *addr_reg; void __iomem *addr_reg;
void __iomem *data_reg; void __iomem *data_reg;
int retval; int retval;
u8 tmp, ioaddr = 0; u8 tmp, ioaddr;
unsigned long irqflags; unsigned long irqflags;
if (usb_disabled()) if (usb_disabled())
return -ENODEV; return -ENODEV;
/* the chip may be wired for either kind of addressing */
addr = platform_get_mem_or_io(dev, 0);
data = platform_get_mem_or_io(dev, 1);
if (!addr || !data || resource_type(addr) != resource_type(data))
return -ENODEV;
/* basic sanity checks first. board-specific init logic should /* basic sanity checks first. board-specific init logic should
* have initialized these three resources and probably board * have initialized these three resources and probably board
* specific platform_data. we don't probe for IRQs, and do only * specific platform_data. we don't probe for IRQs, and do only
...@@ -1632,16 +1638,8 @@ sl811h_probe(struct platform_device *dev) ...@@ -1632,16 +1638,8 @@ sl811h_probe(struct platform_device *dev)
irq = ires->start; irq = ires->start;
irqflags = ires->flags & IRQF_TRIGGER_MASK; irqflags = ires->flags & IRQF_TRIGGER_MASK;
/* the chip may be wired for either kind of addressing */ ioaddr = resource_type(addr) == IORESOURCE_IO;
addr = platform_get_resource(dev, IORESOURCE_MEM, 0); if (ioaddr) {
data = platform_get_resource(dev, IORESOURCE_MEM, 1);
retval = -EBUSY;
if (!addr || !data) {
addr = platform_get_resource(dev, IORESOURCE_IO, 0);
data = platform_get_resource(dev, IORESOURCE_IO, 1);
if (!addr || !data)
return -ENODEV;
ioaddr = 1;
/* /*
* NOTE: 64-bit resource->start is getting truncated * NOTE: 64-bit resource->start is getting truncated
* to avoid compiler warning, assuming that ->start * to avoid compiler warning, assuming that ->start
......
...@@ -25,19 +25,8 @@ static struct resource *get_platform_resource(struct vfio_platform_device *vdev, ...@@ -25,19 +25,8 @@ static struct resource *get_platform_resource(struct vfio_platform_device *vdev,
int num) int num)
{ {
struct platform_device *dev = (struct platform_device *) vdev->opaque; struct platform_device *dev = (struct platform_device *) vdev->opaque;
int i;
for (i = 0; i < dev->num_resources; i++) { return platform_get_mem_or_io(dev, num);
struct resource *r = &dev->resource[i];
if (resource_type(r) & (IORESOURCE_MEM|IORESOURCE_IO)) {
if (!num)
return r;
num--;
}
}
return NULL;
} }
static int get_platform_irq(struct vfio_platform_device *vdev, int i) static int get_platform_irq(struct vfio_platform_device *vdev, int i)
......
...@@ -604,8 +604,7 @@ const struct dentry_operations kernfs_dops = { ...@@ -604,8 +604,7 @@ const struct dentry_operations kernfs_dops = {
*/ */
struct kernfs_node *kernfs_node_from_dentry(struct dentry *dentry) struct kernfs_node *kernfs_node_from_dentry(struct dentry *dentry)
{ {
if (dentry->d_sb->s_op == &kernfs_sops && if (dentry->d_sb->s_op == &kernfs_sops)
!d_really_is_negative(dentry))
return kernfs_dentry_node(dentry); return kernfs_dentry_node(dentry);
return NULL; return NULL;
} }
...@@ -1599,7 +1598,7 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, ...@@ -1599,7 +1598,7 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
return error; return error;
} }
/* Relationship between s_mode and the DT_xxx types */ /* Relationship between mode and the DT_xxx types */
static inline unsigned char dt_type(struct kernfs_node *kn) static inline unsigned char dt_type(struct kernfs_node *kn)
{ {
return (kn->mode >> 12) & 15; return (kn->mode >> 12) & 15;
......
...@@ -55,7 +55,7 @@ static inline struct fwnode_handle *acpi_alloc_fwnode_static(void) ...@@ -55,7 +55,7 @@ static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
if (!fwnode) if (!fwnode)
return NULL; return NULL;
fwnode->ops = &acpi_static_fwnode_ops; fwnode_init(fwnode, &acpi_static_fwnode_ops);
return fwnode; return fwnode;
} }
......
...@@ -351,19 +351,13 @@ enum dl_dev_state { ...@@ -351,19 +351,13 @@ enum dl_dev_state {
* struct dev_links_info - Device data related to device links. * struct dev_links_info - Device data related to device links.
* @suppliers: List of links to supplier devices. * @suppliers: List of links to supplier devices.
* @consumers: List of links to consumer devices. * @consumers: List of links to consumer devices.
* @needs_suppliers: Hook to global list of devices waiting for suppliers. * @defer_sync: Hook to global list of devices that have deferred sync_state.
* @defer_hook: Hook to global list of devices that have deferred sync_state or
* deferred fw_devlink.
* @need_for_probe: If needs_suppliers is on a list, this indicates if the
* suppliers are needed for probe or not.
* @status: Driver status information. * @status: Driver status information.
*/ */
struct dev_links_info { struct dev_links_info {
struct list_head suppliers; struct list_head suppliers;
struct list_head consumers; struct list_head consumers;
struct list_head needs_suppliers; struct list_head defer_sync;
struct list_head defer_hook;
bool need_for_probe;
enum dl_dev_state status; enum dl_dev_state status;
}; };
......
...@@ -256,6 +256,20 @@ extern void class_destroy(struct class *cls); ...@@ -256,6 +256,20 @@ extern void class_destroy(struct class *cls);
/* This is a #define to keep the compiler from merging different /* This is a #define to keep the compiler from merging different
* instances of the __key variable */ * instances of the __key variable */
/**
* class_create - create a struct class structure
* @owner: pointer to the module that is to "own" this struct class
* @name: pointer to a string for the name of this class.
*
* This is used to create a struct class pointer that can then be used
* in calls to device_create().
*
* Returns &struct class pointer on success, or ERR_PTR() on error.
*
* Note, the pointer created here is to be destroyed when finished by
* making a call to class_destroy().
*/
#define class_create(owner, name) \ #define class_create(owner, name) \
({ \ ({ \
static struct lock_class_key __key; \ static struct lock_class_key __key; \
......
...@@ -10,14 +10,32 @@ ...@@ -10,14 +10,32 @@
#define _LINUX_FWNODE_H_ #define _LINUX_FWNODE_H_
#include <linux/types.h> #include <linux/types.h>
#include <linux/list.h>
struct fwnode_operations; struct fwnode_operations;
struct device; struct device;
/*
* fwnode link flags
*
* LINKS_ADDED: The fwnode has already be parsed to add fwnode links.
*/
#define FWNODE_FLAG_LINKS_ADDED BIT(0)
struct fwnode_handle { struct fwnode_handle {
struct fwnode_handle *secondary; struct fwnode_handle *secondary;
const struct fwnode_operations *ops; const struct fwnode_operations *ops;
struct device *dev; struct device *dev;
struct list_head suppliers;
struct list_head consumers;
u8 flags;
};
struct fwnode_link {
struct fwnode_handle *supplier;
struct list_head s_hook;
struct fwnode_handle *consumer;
struct list_head c_hook;
}; };
/** /**
...@@ -68,44 +86,8 @@ struct fwnode_reference_args { ...@@ -68,44 +86,8 @@ struct fwnode_reference_args {
* endpoint node. * endpoint node.
* @graph_get_port_parent: Return the parent node of a port node. * @graph_get_port_parent: Return the parent node of a port node.
* @graph_parse_endpoint: Parse endpoint for port and endpoint id. * @graph_parse_endpoint: Parse endpoint for port and endpoint id.
* @add_links: Called after the device corresponding to the fwnode is added * @add_links: Create fwnode links to all the suppliers of the fwnode. Return
* using device_add(). The function is expected to create device * zero on success, a negative error code otherwise.
* links to all the suppliers of the device that are available at
* the time this function is called. The function must NOT stop
* at the first failed device link if other unlinked supplier
* devices are present in the system. This is necessary for the
* driver/bus sync_state() callbacks to work correctly.
*
* For example, say Device-C depends on suppliers Device-S1 and
* Device-S2 and the dependency is listed in that order in the
* firmware. Say, S1 gets populated from the firmware after
* late_initcall_sync(). Say S2 is populated and probed way
* before that in device_initcall(). When C is populated, if this
* add_links() function doesn't continue past a "failed linking to
* S1" and continue linking C to S2, then S2 will get a
* sync_state() callback before C is probed. This is because from
* the perspective of S2, C was never a consumer when its
* sync_state() evaluation is done. To avoid this, the add_links()
* function has to go through all available suppliers of the
* device (that corresponds to this fwnode) and link to them
* before returning.
*
* If some suppliers are not yet available (indicated by an error
* return value), this function will be called again when other
* devices are added to allow creating device links to any newly
* available suppliers.
*
* Return 0 if device links have been successfully created to all
* the known suppliers of this device or if the supplier
* information is not known.
*
* Return -ENODEV if the suppliers needed for probing this device
* have not been registered yet (because device links can only be
* created to devices registered with the driver core).
*
* Return -EAGAIN if some of the suppliers of this device have not
* been registered yet, but none of those suppliers are necessary
* for probing the device.
*/ */
struct fwnode_operations { struct fwnode_operations {
struct fwnode_handle *(*get)(struct fwnode_handle *fwnode); struct fwnode_handle *(*get)(struct fwnode_handle *fwnode);
...@@ -145,8 +127,7 @@ struct fwnode_operations { ...@@ -145,8 +127,7 @@ struct fwnode_operations {
(*graph_get_port_parent)(struct fwnode_handle *fwnode); (*graph_get_port_parent)(struct fwnode_handle *fwnode);
int (*graph_parse_endpoint)(const struct fwnode_handle *fwnode, int (*graph_parse_endpoint)(const struct fwnode_handle *fwnode,
struct fwnode_endpoint *endpoint); struct fwnode_endpoint *endpoint);
int (*add_links)(const struct fwnode_handle *fwnode, int (*add_links)(struct fwnode_handle *fwnode);
struct device *dev);
}; };
#define fwnode_has_op(fwnode, op) \ #define fwnode_has_op(fwnode, op) \
...@@ -170,8 +151,16 @@ struct fwnode_operations { ...@@ -170,8 +151,16 @@ struct fwnode_operations {
} while (false) } while (false)
#define get_dev_from_fwnode(fwnode) get_device((fwnode)->dev) #define get_dev_from_fwnode(fwnode) get_device((fwnode)->dev)
static inline void fwnode_init(struct fwnode_handle *fwnode,
const struct fwnode_operations *ops)
{
fwnode->ops = ops;
INIT_LIST_HEAD(&fwnode->consumers);
INIT_LIST_HEAD(&fwnode->suppliers);
}
extern u32 fw_devlink_get_flags(void); extern u32 fw_devlink_get_flags(void);
void fw_devlink_pause(void); int fwnode_link_add(struct fwnode_handle *con, struct fwnode_handle *sup);
void fw_devlink_resume(void); void fwnode_links_purge(struct fwnode_handle *fwnode);
#endif #endif
...@@ -116,7 +116,7 @@ struct kernfs_elem_attr { ...@@ -116,7 +116,7 @@ struct kernfs_elem_attr {
* kernfs node is represented by single kernfs_node. Most fields are * kernfs node is represented by single kernfs_node. Most fields are
* private to kernfs and shouldn't be accessed directly by kernfs users. * private to kernfs and shouldn't be accessed directly by kernfs users.
* *
* As long as s_count reference is held, the kernfs_node itself is * As long as count reference is held, the kernfs_node itself is
* accessible. Dereferencing elem or any other outer entity requires * accessible. Dereferencing elem or any other outer entity requires
* active reference. * active reference.
*/ */
......
...@@ -108,7 +108,7 @@ static inline void of_node_init(struct device_node *node) ...@@ -108,7 +108,7 @@ static inline void of_node_init(struct device_node *node)
#if defined(CONFIG_OF_KOBJ) #if defined(CONFIG_OF_KOBJ)
kobject_init(&node->kobj, &of_node_ktype); kobject_init(&node->kobj, &of_node_ktype);
#endif #endif
node->fwnode.ops = &of_fwnode_ops; fwnode_init(&node->fwnode, &of_fwnode_ops);
} }
#if defined(CONFIG_OF_KOBJ) #if defined(CONFIG_OF_KOBJ)
...@@ -1307,6 +1307,7 @@ static inline int of_get_available_child_count(const struct device_node *np) ...@@ -1307,6 +1307,7 @@ static inline int of_get_available_child_count(const struct device_node *np)
#define _OF_DECLARE(table, name, compat, fn, fn_type) \ #define _OF_DECLARE(table, name, compat, fn, fn_type) \
static const struct of_device_id __of_table_##name \ static const struct of_device_id __of_table_##name \
__used __section("__" #table "_of_table") \ __used __section("__" #table "_of_table") \
__aligned(__alignof__(struct of_device_id)) \
= { .compatible = compat, \ = { .compatible = compat, \
.data = (fn == (fn_type)NULL) ? fn : fn } .data = (fn == (fn_type)NULL) ? fn : fn }
#else #else
......
...@@ -52,6 +52,9 @@ extern struct device platform_bus; ...@@ -52,6 +52,9 @@ extern struct device platform_bus;
extern struct resource *platform_get_resource(struct platform_device *, extern struct resource *platform_get_resource(struct platform_device *,
unsigned int, unsigned int); unsigned int, unsigned int);
extern struct resource *platform_get_mem_or_io(struct platform_device *,
unsigned int);
extern struct device * extern struct device *
platform_find_device_by_driver(struct device *start, platform_find_device_by_driver(struct device *start,
const struct device_driver *drv); const struct device_driver *drv);
......
...@@ -85,9 +85,12 @@ const char *fwnode_get_name_prefix(const struct fwnode_handle *fwnode); ...@@ -85,9 +85,12 @@ const char *fwnode_get_name_prefix(const struct fwnode_handle *fwnode);
struct fwnode_handle *fwnode_get_parent(const struct fwnode_handle *fwnode); struct fwnode_handle *fwnode_get_parent(const struct fwnode_handle *fwnode);
struct fwnode_handle *fwnode_get_next_parent( struct fwnode_handle *fwnode_get_next_parent(
struct fwnode_handle *fwnode); struct fwnode_handle *fwnode);
struct device *fwnode_get_next_parent_dev(struct fwnode_handle *fwnode);
unsigned int fwnode_count_parents(const struct fwnode_handle *fwn); unsigned int fwnode_count_parents(const struct fwnode_handle *fwn);
struct fwnode_handle *fwnode_get_nth_parent(struct fwnode_handle *fwn, struct fwnode_handle *fwnode_get_nth_parent(struct fwnode_handle *fwn,
unsigned int depth); unsigned int depth);
bool fwnode_is_ancestor_of(struct fwnode_handle *test_ancestor,
struct fwnode_handle *test_child);
struct fwnode_handle *fwnode_get_next_child_node( struct fwnode_handle *fwnode_get_next_child_node(
const struct fwnode_handle *fwnode, struct fwnode_handle *child); const struct fwnode_handle *fwnode, struct fwnode_handle *child);
struct fwnode_handle *fwnode_get_next_available_child_node( struct fwnode_handle *fwnode_get_next_available_child_node(
......
...@@ -100,7 +100,7 @@ struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id, ...@@ -100,7 +100,7 @@ struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
fwid->type = type; fwid->type = type;
fwid->name = n; fwid->name = n;
fwid->pa = pa; fwid->pa = pa;
fwid->fwnode.ops = &irqchip_fwnode_ops; fwnode_init(&fwid->fwnode, &irqchip_fwnode_ops);
return &fwid->fwnode; return &fwid->fwnode;
} }
EXPORT_SYMBOL_GPL(__irq_domain_alloc_fwnode); EXPORT_SYMBOL_GPL(__irq_domain_alloc_fwnode);
......
...@@ -561,9 +561,14 @@ static int ddebug_exec_queries(char *query, const char *modname) ...@@ -561,9 +561,14 @@ static int ddebug_exec_queries(char *query, const char *modname)
int dynamic_debug_exec_queries(const char *query, const char *modname) int dynamic_debug_exec_queries(const char *query, const char *modname)
{ {
int rc; int rc;
char *qry = kstrndup(query, PAGE_SIZE, GFP_KERNEL); char *qry; /* writable copy of query */
if (!query) if (!query) {
pr_err("non-null query/command string expected\n");
return -EINVAL;
}
qry = kstrndup(query, PAGE_SIZE, GFP_KERNEL);
if (!qry)
return -ENOMEM; return -ENOMEM;
rc = ddebug_exec_queries(qry, modname); rc = ddebug_exec_queries(qry, modname);
......
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