Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f6403f83 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "driver-core: fix build for !CONFIG_MODULES"

parents 08db3066 b548d9f4
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -929,6 +929,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
			Enable debug messages at boot time.  See
			Documentation/dynamic-debug-howto.txt for details.

	module.async_probe [KNL]
			Enable asynchronous probe on this module.

	early_ioremap_debug [KNL]
			Enable debug messages in early_ioremap support. This
			is useful for tracking down temporary early mappings
+2 −2
Original line number Diff line number Diff line
@@ -333,7 +333,7 @@ int alloc_bootmem_huge_page(struct hstate *hstate)
unsigned long gpage_npages[MMU_PAGE_COUNT];

static int __init do_gpage_early_setup(char *param, char *val,
				       const char *unused)
				       const char *unused, void *arg)
{
	static phys_addr_t size;
	unsigned long npages;
@@ -375,7 +375,7 @@ void __init reserve_hugetlb_gpages(void)

	strlcpy(cmdline, boot_command_line, COMMAND_LINE_SIZE);
	parse_args("hugetlb gpages", cmdline, NULL, 0, 0, 0,
			&do_gpage_early_setup);
			NULL, &do_gpage_early_setup);

	/*
	 * Walk gpage list in reverse, allocating larger page sizes first.
+1 −0
Original line number Diff line number Diff line
@@ -116,6 +116,7 @@ static inline int driver_match_device(struct device_driver *drv,
{
	return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
extern bool driver_allows_async_probing(struct device_driver *drv);

extern int driver_add_groups(struct device_driver *drv,
			     const struct attribute_group **groups);
+23 −8
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
 *
 */

#include <linux/async.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/errno.h>
@@ -549,15 +550,12 @@ void bus_probe_device(struct device *dev)
{
	struct bus_type *bus = dev->bus;
	struct subsys_interface *sif;
	int ret;

	if (!bus)
		return;

	if (bus->p->drivers_autoprobe) {
		ret = device_attach(dev);
		WARN_ON(ret < 0);
	}
	if (bus->p->drivers_autoprobe)
		device_initial_probe(dev);

	mutex_lock(&bus->p->mutex);
	list_for_each_entry(sif, &bus->p->interfaces, node)
@@ -659,6 +657,17 @@ static ssize_t uevent_store(struct device_driver *drv, const char *buf,
}
static DRIVER_ATTR_WO(uevent);

static void driver_attach_async(void *_drv, async_cookie_t cookie)
{
	struct device_driver *drv = _drv;
	int ret;

	ret = driver_attach(drv);

	pr_debug("bus: '%s': driver %s async attach completed: %d\n",
		 drv->bus->name, drv->name, ret);
}

/**
 * bus_add_driver - Add a driver to the bus.
 * @drv: driver.
@@ -691,10 +700,16 @@ int bus_add_driver(struct device_driver *drv)

	klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
	if (drv->bus->p->drivers_autoprobe) {
		if (driver_allows_async_probing(drv)) {
			pr_debug("bus: '%s': probing driver %s asynchronously\n",
				drv->bus->name, drv->name);
			async_schedule(driver_attach_async, drv);
		} else {
			error = driver_attach(drv);
			if (error)
				goto out_unregister;
		}
	}
	module_add_driver(drv->owner, drv);

	error = driver_create_file(drv, &driver_attr_uevent);
+142 −19
Original line number Diff line number Diff line
@@ -425,31 +425,107 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)
	return ret;
}

static int __device_attach(struct device_driver *drv, void *data)
bool driver_allows_async_probing(struct device_driver *drv)
{
	struct device *dev = data;
	switch (drv->probe_type) {
	case PROBE_PREFER_ASYNCHRONOUS:
		return true;

	case PROBE_FORCE_SYNCHRONOUS:
		return false;

	default:
		if (module_requested_async_probing(drv->owner))
			return true;

		return false;
	}
}

struct device_attach_data {
	struct device *dev;

	/*
	 * Indicates whether we are are considering asynchronous probing or
	 * not. Only initial binding after device or driver registration
	 * (including deferral processing) may be done asynchronously, the
	 * rest is always synchronous, as we expect it is being done by
	 * request from userspace.
	 */
	bool check_async;

	/*
	 * Indicates if we are binding synchronous or asynchronous drivers.
	 * When asynchronous probing is enabled we'll execute 2 passes
	 * over drivers: first pass doing synchronous probing and second
	 * doing asynchronous probing (if synchronous did not succeed -
	 * most likely because there was no driver requiring synchronous
	 * probing - and we found asynchronous driver during first pass).
	 * The 2 passes are done because we can't shoot asynchronous
	 * probe for given device and driver from bus_for_each_drv() since
	 * driver pointer is not guaranteed to stay valid once
	 * bus_for_each_drv() iterates to the next driver on the bus.
	 */
	bool want_async;

	/*
	 * We'll set have_async to 'true' if, while scanning for matching
	 * driver, we'll encounter one that requests asynchronous probing.
	 */
	bool have_async;
};

static int __device_attach_driver(struct device_driver *drv, void *_data)
{
	struct device_attach_data *data = _data;
	struct device *dev = data->dev;
	bool async_allowed;

	/*
	 * Check if device has already been claimed. This may
	 * happen with driver loading, device discovery/registration,
	 * and deferred probe processing happens all at once with
	 * multiple threads.
	 */
	if (dev->driver)
		return -EBUSY;

	if (!driver_match_device(drv, dev))
		return 0;

	async_allowed = driver_allows_async_probing(drv);

	if (async_allowed)
		data->have_async = true;

	if (data->check_async && async_allowed != data->want_async)
		return 0;

	return driver_probe_device(drv, dev);
}

/**
 * device_attach - try to attach device to a driver.
 * @dev: device.
 *
 * Walk the list of drivers that the bus has and call
 * driver_probe_device() for each pair. If a compatible
 * pair is found, break out and return.
 *
 * Returns 1 if the device was bound to a driver;
 * 0 if no matching driver was found;
 * -ENODEV if the device is not registered.
 *
 * When called for a USB interface, @dev->parent lock must be held.
 */
int device_attach(struct device *dev)
static void __device_attach_async_helper(void *_dev, async_cookie_t cookie)
{
	struct device *dev = _dev;
	struct device_attach_data data = {
		.dev		= dev,
		.check_async	= true,
		.want_async	= true,
	};

	device_lock(dev);

	bus_for_each_drv(dev->bus, NULL, &data, __device_attach_driver);
	dev_dbg(dev, "async probe completed\n");

	pm_request_idle(dev);

	device_unlock(dev);

	put_device(dev);
}

static int __device_attach(struct device *dev, bool allow_async)
{
	int ret = 0;

@@ -467,15 +543,59 @@ int device_attach(struct device *dev)
			ret = 0;
		}
	} else {
		ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
		struct device_attach_data data = {
			.dev = dev,
			.check_async = allow_async,
			.want_async = false,
		};

		ret = bus_for_each_drv(dev->bus, NULL, &data,
					__device_attach_driver);
		if (!ret && allow_async && data.have_async) {
			/*
			 * If we could not find appropriate driver
			 * synchronously and we are allowed to do
			 * async probes and there are drivers that
			 * want to probe asynchronously, we'll
			 * try them.
			 */
			dev_dbg(dev, "scheduling asynchronous probe\n");
			get_device(dev);
			async_schedule(__device_attach_async_helper, dev);
		} else {
			pm_request_idle(dev);
		}
	}
out_unlock:
	device_unlock(dev);
	return ret;
}

/**
 * device_attach - try to attach device to a driver.
 * @dev: device.
 *
 * Walk the list of drivers that the bus has and call
 * driver_probe_device() for each pair. If a compatible
 * pair is found, break out and return.
 *
 * Returns 1 if the device was bound to a driver;
 * 0 if no matching driver was found;
 * -ENODEV if the device is not registered.
 *
 * When called for a USB interface, @dev->parent lock must be held.
 */
int device_attach(struct device *dev)
{
	return __device_attach(dev, false);
}
EXPORT_SYMBOL_GPL(device_attach);

void device_initial_probe(struct device *dev)
{
	__device_attach(dev, true);
}

static int __driver_attach(struct device *dev, void *data)
{
	struct device_driver *drv = data;
@@ -530,6 +650,9 @@ static void __device_release_driver(struct device *dev)

	drv = dev->driver;
	if (drv) {
		if (driver_allows_async_probing(drv))
			async_synchronize_full();

		pm_runtime_get_sync(dev);

		driver_sysfs_remove(dev);
Loading