Commit 241590e5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull driver core updates from Greg KH:
 "Here is the "big" set of driver core and kernfs changes for 6.9-rc1.

  Nothing all that crazy here, just some good updates that include:

   - automatic attribute group hiding from Dan Williams (he fixed up my
     horrible attempt at doing this.)

   - kobject lock contention fixes from Eric Dumazet

   - driver core cleanups from Andy

   - kernfs rcu work from Tejun

   - fw_devlink changes to resolve some reported issues

   - other minor changes, all details in the shortlog

  All of these have been in linux-next for a long time with no reported
  issues"

* tag 'driver-core-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (28 commits)
  device: core: Log warning for devices pending deferred probe on timeout
  driver: core: Use dev_* instead of pr_* so device metadata is added
  driver: core: Log probe failure as error and with device metadata
  of: property: fw_devlink: Add support for "post-init-providers" property
  driver core: Add FWLINK_FLAG_IGNORE to completely ignore a fwnode link
  driver core: Adds flags param to fwnode_link_add()
  debugfs: fix wait/cancellation handling during remove
  device property: Don't use "proxy" headers
  device property: Move enum dev_dma_attr to fwnode.h
  driver core: Move fw_devlink stuff to where it belongs
  driver core: Drop unneeded 'extern' keyword in fwnode.h
  firmware_loader: Suppress warning on FW_OPT_NO_WARN flag
  sysfs:Addresses documentation in sysfs_merge_group and sysfs_unmerge_group.
  firmware_loader: introduce __free() cleanup hanler
  platform-msi: Remove usage of the deprecated ida_simple_xx() API
  sysfs: Introduce DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE()
  sysfs: Document new "group visible" helpers
  sysfs: Fix crash on empty group attributes array
  sysfs: Introduce a mechanism to hide static attribute_groups
  sysfs: Introduce a mechanism to hide static attribute_groups
  ...
parents bb41fe35 6aeb8850
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -751,7 +751,7 @@ static int __component_add(struct device *dev, const struct component_ops *ops,
 * component_bind_all(). See also &struct component_ops.
 *
 * @subcomponent must be nonzero and is used to differentiate between multiple
 * components registerd on the same device @dev. These components are match
 * components registered on the same device @dev. These components are match
 * using component_match_add_typed().
 *
 * The component needs to be unregistered at driver unload/disconnect by
@@ -781,7 +781,7 @@ EXPORT_SYMBOL_GPL(component_add_typed);
 * The component needs to be unregistered at driver unload/disconnect by
 * calling component_del().
 *
 * See also component_add_typed() for a variant that allows multipled different
 * See also component_add_typed() for a variant that allows multiple different
 * components on the same device.
 */
int component_add(struct device *dev, const struct component_ops *ops)
+69 −3
Original line number Diff line number Diff line
@@ -92,12 +92,13 @@ static int __fwnode_link_add(struct fwnode_handle *con,
	return 0;
}

int fwnode_link_add(struct fwnode_handle *con, struct fwnode_handle *sup)
int fwnode_link_add(struct fwnode_handle *con, struct fwnode_handle *sup,
		    u8 flags)
{
	int ret;

	mutex_lock(&fwnode_link_lock);
	ret = __fwnode_link_add(con, sup, 0);
	ret = __fwnode_link_add(con, sup, flags);
	mutex_unlock(&fwnode_link_lock);
	return ret;
}
@@ -1011,7 +1012,8 @@ static struct fwnode_handle *fwnode_links_check_suppliers(
		return NULL;

	list_for_each_entry(link, &fwnode->suppliers, c_hook)
		if (!(link->flags & FWLINK_FLAG_CYCLE))
		if (!(link->flags &
		      (FWLINK_FLAG_CYCLE | FWLINK_FLAG_IGNORE)))
			return link->supplier;

	return NULL;
@@ -1871,6 +1873,7 @@ static void fw_devlink_unblock_consumers(struct device *dev)
	device_links_write_unlock();
}

#define get_dev_from_fwnode(fwnode)	get_device((fwnode)->dev)

static bool fwnode_init_without_drv(struct fwnode_handle *fwnode)
{
@@ -1901,6 +1904,63 @@ static bool fwnode_ancestor_init_without_drv(struct fwnode_handle *fwnode)
	return false;
}

/**
 * fwnode_is_ancestor_of - Test if @ancestor is ancestor of @child
 * @ancestor: Firmware which is tested for being an ancestor
 * @child: Firmware which is tested for being the child
 *
 * A node is considered an ancestor of itself too.
 *
 * Return: true if @ancestor is an ancestor of @child. Otherwise, returns false.
 */
static bool fwnode_is_ancestor_of(const struct fwnode_handle *ancestor,
				  const struct fwnode_handle *child)
{
	struct fwnode_handle *parent;

	if (IS_ERR_OR_NULL(ancestor))
		return false;

	if (child == ancestor)
		return true;

	fwnode_for_each_parent_node(child, parent) {
		if (parent == ancestor) {
			fwnode_handle_put(parent);
			return true;
		}
	}
	return false;
}

/**
 * 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 is responsible for calling put_device() on the returned device
 * pointer.
 *
 * Return: a pointer to the device of the @fwnode's closest ancestor.
 */
static struct device *fwnode_get_next_parent_dev(const struct fwnode_handle *fwnode)
{
	struct fwnode_handle *parent;
	struct device *dev;

	fwnode_for_each_parent_node(fwnode, parent) {
		dev = get_dev_from_fwnode(parent);
		if (dev) {
			fwnode_handle_put(parent);
			return dev;
		}
	}
	return NULL;
}

/**
 * __fw_devlink_relax_cycles - Relax and mark dependency cycles.
 * @con: Potential consumer device.
@@ -1962,6 +2022,9 @@ static bool __fw_devlink_relax_cycles(struct device *con,
	}

	list_for_each_entry(link, &sup_handle->suppliers, c_hook) {
		if (link->flags & FWLINK_FLAG_IGNORE)
			continue;

		if (__fw_devlink_relax_cycles(con, link->supplier)) {
			__fwnode_link_cycle(link);
			ret = true;
@@ -2040,6 +2103,9 @@ static int fw_devlink_create_devlink(struct device *con,
	int ret = 0;
	u32 flags;

	if (link->flags & FWLINK_FLAG_IGNORE)
		return 0;

	if (con->fwnode == link->consumer)
		flags = fw_devlink_get_flags(link->flags);
	else
+1 −1
Original line number Diff line number Diff line
@@ -366,7 +366,7 @@ static int cpu_uevent(const struct device *dev, struct kobj_uevent_env *env)
}
#endif

struct bus_type cpu_subsys = {
const struct bus_type cpu_subsys = {
	.name = "cpu",
	.dev_name = "cpu",
	.match = cpu_subsys_match,
+15 −17
Original line number Diff line number Diff line
@@ -313,7 +313,7 @@ static void deferred_probe_timeout_work_func(struct work_struct *work)

	mutex_lock(&deferred_probe_mutex);
	list_for_each_entry(p, &deferred_probe_pending_list, deferred_probe)
		dev_info(p->device, "deferred probe pending: %s", p->deferred_probe_reason ?: "(reason unknown)\n");
		dev_warn(p->device, "deferred probe pending: %s", p->deferred_probe_reason ?: "(reason unknown)\n");
	mutex_unlock(&deferred_probe_mutex);

	fw_devlink_probing_done();
@@ -397,13 +397,12 @@ bool device_is_bound(struct device *dev)
static void driver_bound(struct device *dev)
{
	if (device_is_bound(dev)) {
		pr_warn("%s: device %s already bound\n",
			__func__, kobject_name(&dev->kobj));
		dev_warn(dev, "%s: device already bound\n", __func__);
		return;
	}

	pr_debug("driver: '%s': %s: bound to device '%s'\n", dev->driver->name,
		 __func__, dev_name(dev));
	dev_dbg(dev, "driver: '%s': %s: bound to device\n", dev->driver->name,
		__func__);

	klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);
	device_links_driver_bound(dev);
@@ -587,13 +586,13 @@ static int call_driver_probe(struct device *dev, struct device_driver *drv)
		break;
	case -ENODEV:
	case -ENXIO:
		pr_debug("%s: probe of %s rejects match %d\n",
			 drv->name, dev_name(dev), ret);
		dev_dbg(dev, "probe with driver %s rejects match %d\n",
			drv->name, ret);
		break;
	default:
		/* driver matched but the probe failed */
		pr_warn("%s: probe of %s failed with error %d\n",
			drv->name, dev_name(dev), ret);
		dev_err(dev, "probe with driver %s failed with error %d\n",
			drv->name, ret);
		break;
	}

@@ -620,8 +619,8 @@ static int really_probe(struct device *dev, struct device_driver *drv)
	if (link_ret == -EPROBE_DEFER)
		return link_ret;

	pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
		 drv->bus->name, __func__, drv->name, dev_name(dev));
	dev_dbg(dev, "bus: '%s': %s: probing driver %s with device\n",
		drv->bus->name, __func__, drv->name);
	if (!list_empty(&dev->devres_head)) {
		dev_crit(dev, "Resources present before probing\n");
		ret = -EBUSY;
@@ -644,8 +643,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)

	ret = driver_sysfs_add(dev);
	if (ret) {
		pr_err("%s: driver_sysfs_add(%s) failed\n",
		       __func__, dev_name(dev));
		dev_err(dev, "%s: driver_sysfs_add failed\n", __func__);
		goto sysfs_failed;
	}

@@ -706,8 +704,8 @@ static int really_probe(struct device *dev, struct device_driver *drv)
		dev->pm_domain->sync(dev);

	driver_bound(dev);
	pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
		 drv->bus->name, __func__, dev_name(dev), drv->name);
	dev_dbg(dev, "bus: '%s': %s: bound device to driver %s\n",
		drv->bus->name, __func__, drv->name);
	goto done;

dev_sysfs_state_synced_failed:
@@ -786,8 +784,8 @@ static int __driver_probe_device(struct device_driver *drv, struct device *dev)
		return -EBUSY;

	dev->can_match = true;
	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
		 drv->bus->name, __func__, dev_name(dev), drv->name);
	dev_dbg(dev, "bus: '%s': %s: matched device with driver %s\n",
		drv->bus->name, __func__, drv->name);

	pm_runtime_get_suppliers(dev);
	if (dev->parent)
+10 −6
Original line number Diff line number Diff line
@@ -551,12 +551,16 @@ fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv,
						       file_size_ptr,
						       READING_FIRMWARE);
		if (rc < 0) {
			if (!(fw_priv->opt_flags & FW_OPT_NO_WARN)) {
				if (rc != -ENOENT)
				dev_warn(device, "loading %s failed with error %d\n",
					dev_warn(device,
						 "loading %s failed with error %d\n",
						 path, rc);
				else
				dev_dbg(device, "loading %s failed for no such file or directory.\n",
					dev_dbg(device,
						"loading %s failed for no such file or directory.\n",
						path);
			}
			continue;
		}
		size = rc;
Loading