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

Commit 837525e3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6:
  firmware: remove orphaned Email
  kobject: use the proper printk level for kobject error
  Driver core: kill unused code
  Driver core: keep PHYSDEV for old struct class_device
  update Documentation/driver-model/platform.txt
parents 217397d7 87d37a4f
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -96,6 +96,46 @@ System setup also associates those clocks with the device, so that that
calls to clk_get(&pdev->dev, clock_name) return them as needed.


Legacy Drivers:  Device Probing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Some drivers are not fully converted to the driver model, because they take
on a non-driver role:  the driver registers its platform device, rather than
leaving that for system infrastructure.  Such drivers can't be hotplugged
or coldplugged, since those mechanisms require device creation to be in a
different system component than the driver.

The only "good" reason for this is to handle older system designs which, like
original IBM PCs, rely on error-prone "probe-the-hardware" models for hardware
configuration.  Newer systems have largely abandoned that model, in favor of
bus-level support for dynamic configuration (PCI, USB), or device tables
provided by the boot firmware (e.g. PNPACPI on x86).  There are too many
conflicting options about what might be where, and even educated guesses by
an operating system will be wrong often enough to make trouble.

This style of driver is discouraged.  If you're updating such a driver,
please try to move the device enumeration to a more appropriate location,
outside the driver.  This will usually be cleanup, since such drivers
tend to already have "normal" modes, such as ones using device nodes that
were created by PNP or by platform device setup.

None the less, there are some APIs to support such legacy drivers.  Avoid
using these calls except with such hotplug-deficient drivers.

	struct platform_device *platform_device_alloc(
			char *name, unsigned id);

You can use platform_device_alloc() to dynamically allocate a device, which
you will then initialize with resources and platform_device_register().
A better solution is usually:

	struct platform_device *platform_device_register_simple(
			char *name, unsigned id,
			struct resource *res, unsigned nres);

You can use platform_device_register_simple() as a one-step call to allocate
and register a device.


Device Naming and Driver Binding
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The platform_device.dev.bus_id is the canonical name for the devices.
+1 −1
Original line number Diff line number Diff line

 request_firmware() hotplug interface:
 ------------------------------------
	Copyright (C) 2003 Manuel Estrada Sainz <ranty@debian.org>
	Copyright (C) 2003 Manuel Estrada Sainz

 Why:
 ---
+1 −1
Original line number Diff line number Diff line
/*
 * firmware_sample_driver.c -
 *
 * Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org>
 * Copyright (c) 2003 Manuel Estrada Sainz
 *
 * Sample code on how to use request_firmware() from drivers.
 *
+2 −2
Original line number Diff line number Diff line
/*
 * firmware_sample_firmware_class.c -
 *
 * Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org>
 * Copyright (c) 2003 Manuel Estrada Sainz
 *
 * NOTE: This is just a probe of concept, if you think that your driver would
 * be well served by this mechanism please contact me first.
@@ -19,7 +19,7 @@
#include <linux/firmware.h>


MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
MODULE_AUTHOR("Manuel Estrada Sainz");
MODULE_DESCRIPTION("Hackish sample for using firmware class directly");
MODULE_LICENSE("GPL");

+21 −38
Original line number Diff line number Diff line
@@ -369,36 +369,6 @@ char *make_class_name(const char *name, struct kobject *kobj)
	return class_name;
}

static int deprecated_class_uevent(char **envp, int num_envp, int *cur_index,
				   char *buffer, int buffer_size,
				   int *cur_len,
				   struct class_device *class_dev)
{
	struct device *dev = class_dev->dev;
	char *path;

	if (!dev)
		return 0;

	/* add device, backing this class device (deprecated) */
	path = kobject_get_path(&dev->kobj, GFP_KERNEL);

	add_uevent_var(envp, num_envp, cur_index, buffer, buffer_size,
		       cur_len, "PHYSDEVPATH=%s", path);
	kfree(path);

	if (dev->bus)
		add_uevent_var(envp, num_envp, cur_index,
			       buffer, buffer_size, cur_len,
			       "PHYSDEVBUS=%s", dev->bus->name);

	if (dev->driver)
		add_uevent_var(envp, num_envp, cur_index,
			       buffer, buffer_size, cur_len,
			       "PHYSDEVDRIVER=%s", dev->driver->name);
	return 0;
}

static int make_deprecated_class_device_links(struct class_device *class_dev)
{
	char *class_name;
@@ -430,11 +400,6 @@ static void remove_deprecated_class_device_links(struct class_device *class_dev)
	kfree(class_name);
}
#else
static inline int deprecated_class_uevent(char **envp, int num_envp,
					  int *cur_index, char *buffer,
					  int buffer_size, int *cur_len,
					  struct class_device *class_dev)
{ return 0; }
static inline int make_deprecated_class_device_links(struct class_device *cd)
{ return 0; }
static void remove_deprecated_class_device_links(struct class_device *cd)
@@ -445,15 +410,13 @@ static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
			 int num_envp, char *buffer, int buffer_size)
{
	struct class_device *class_dev = to_class_dev(kobj);
	struct device *dev = class_dev->dev;
	int i = 0;
	int length = 0;
	int retval = 0;

	pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);

	deprecated_class_uevent(envp, num_envp, &i, buffer, buffer_size,
				&length, class_dev);

	if (MAJOR(class_dev->devt)) {
		add_uevent_var(envp, num_envp, &i,
			       buffer, buffer_size, &length,
@@ -464,6 +427,26 @@ static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
			       "MINOR=%u", MINOR(class_dev->devt));
	}

	if (dev) {
		const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
		if (path) {
			add_uevent_var(envp, num_envp, &i,
				       buffer, buffer_size, &length,
				       "PHYSDEVPATH=%s", path);
			kfree(path);
		}

		if (dev->bus)
			add_uevent_var(envp, num_envp, &i,
				       buffer, buffer_size, &length,
				       "PHYSDEVBUS=%s", dev->bus->name);

		if (dev->driver)
			add_uevent_var(envp, num_envp, &i,
				       buffer, buffer_size, &length,
				       "PHYSDEVDRIVER=%s", dev->driver->name);
	}

	/* terminate, set to next free slot, shrink available space */
	envp[i] = NULL;
	envp = &envp[i];
Loading