diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2006-06-16 15:31:08 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-06-16 15:31:08 -0700 |
commit | 5b88ea4d35a4788dcfbc3047149276898e194a4b (patch) | |
tree | 3873bcbf682aeb9ef089f69f4c88d8d2d5bc0073 /driver | |
parent | 3ab23ec21bc7eb5f1cc934b7c8ab126d01dd3f51 (diff) | |
download | patches-5b88ea4d35a4788dcfbc3047149276898e194a4b.tar.gz |
lots of new patches
Diffstat (limited to 'driver')
-rw-r--r-- | driver/driver-core-add-generic-subsystem-link-to-all-devices.patch | 160 | ||||
-rw-r--r-- | driver/driver-model-add-isa-bus.patch | 373 | ||||
-rw-r--r-- | driver/put_device-might_sleep.patch | 2 |
3 files changed, 534 insertions, 1 deletions
diff --git a/driver/driver-core-add-generic-subsystem-link-to-all-devices.patch b/driver/driver-core-add-generic-subsystem-link-to-all-devices.patch new file mode 100644 index 0000000000000..d2389ef3b05bb --- /dev/null +++ b/driver/driver-core-add-generic-subsystem-link-to-all-devices.patch @@ -0,0 +1,160 @@ +From kay.sievers@vrfy.org Thu Jun 15 06:32:03 2006 +Date: Thu, 15 Jun 2006 15:31:56 +0200 +From: Kay Sievers <kay.sievers@suse.de> +To: greg@kroah.com +Subject: Driver core: add generic "subsystem" link to all devices +Message-ID: <20060615133156.GA9472@vrfy.org> + +Like the SUBSYTEM= key we find in the environment of the uevent, this +creates a generic "subsystem" link in sysfs for every device. Userspace +usually doesn't care at all if its a "class" or a "bus" device. This +provides an unified way to determine the subsytem of a device, regardless +of the way the driver core has created it. + +Signed-off-by: Kay Sievers <kay.sievers@suse.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + block/genhd.c | 7 ++----- + drivers/base/bus.c | 2 ++ + drivers/base/class.c | 2 ++ + drivers/base/core.c | 11 +++++++++-- + fs/partitions/check.c | 4 ++++ + 5 files changed, 19 insertions(+), 7 deletions(-) + +--- gregkh-2.6.orig/block/genhd.c ++++ gregkh-2.6/block/genhd.c +@@ -17,8 +17,7 @@ + #include <linux/buffer_head.h> + #include <linux/mutex.h> + +-static struct subsystem block_subsys; +- ++struct subsystem block_subsys; + static DEFINE_MUTEX(block_subsys_lock); + + /* +@@ -511,9 +510,7 @@ static struct kset_uevent_ops block_ueve + .uevent = block_uevent, + }; + +-/* declare block_subsys. */ +-static decl_subsys(block, &ktype_block, &block_uevent_ops); +- ++decl_subsys(block, &ktype_block, &block_uevent_ops); + + /* + * aggregate disk stat collector. Uses the same stats that the sysfs +--- gregkh-2.6.orig/drivers/base/bus.c ++++ gregkh-2.6/drivers/base/bus.c +@@ -374,6 +374,7 @@ int bus_add_device(struct device * dev) + error = device_add_attrs(bus, dev); + if (!error) { + sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id); ++ sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "subsystem"); + sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus"); + } + } +@@ -408,6 +409,7 @@ void bus_attach_device(struct device * d + void bus_remove_device(struct device * dev) + { + if (dev->bus) { ++ sysfs_remove_link(&dev->kobj, "subsystem"); + sysfs_remove_link(&dev->kobj, "bus"); + sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); + device_remove_attrs(dev->bus, dev); +--- gregkh-2.6.orig/drivers/base/class.c ++++ gregkh-2.6/drivers/base/class.c +@@ -562,6 +562,7 @@ int class_device_add(struct class_device + goto out2; + + /* add the needed attributes to this device */ ++ sysfs_create_link(&class_dev->kobj, &parent_class->subsys.kset.kobj, "subsystem"); + class_dev->uevent_attr.attr.name = "uevent"; + class_dev->uevent_attr.attr.mode = S_IWUSR; + class_dev->uevent_attr.attr.owner = parent_class->owner; +@@ -736,6 +737,7 @@ void class_device_del(struct class_devic + sysfs_remove_link(&class_dev->kobj, "device"); + sysfs_remove_link(&class_dev->dev->kobj, class_name); + } ++ sysfs_remove_link(&class_dev->kobj, "subsystem"); + class_device_remove_file(class_dev, &class_dev->uevent_attr); + if (class_dev->devt_attr) + class_device_remove_file(class_dev, class_dev->devt_attr); +--- gregkh-2.6.orig/drivers/base/core.c ++++ gregkh-2.6/drivers/base/core.c +@@ -335,9 +335,12 @@ int device_add(struct device *dev) + dev->devt_attr = attr; + } + +- if (dev->class) ++ if (dev->class) { ++ sysfs_create_link(&dev->kobj, &dev->class->subsys.kset.kobj, ++ "subsystem"); + sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj, + dev->bus_id); ++ } + + if ((error = device_pm_add(dev))) + goto PMError; +@@ -438,8 +441,10 @@ void device_del(struct device * dev) + klist_del(&dev->knode_parent); + if (dev->devt_attr) + device_remove_file(dev, dev->devt_attr); +- if (dev->class) ++ if (dev->class) { ++ sysfs_remove_link(&dev->kobj, "subsystem"); + sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id); ++ } + device_remove_file(dev, &dev->uevent_attr); + + /* Notify the platform of the removal, in case they +@@ -581,6 +586,7 @@ struct device *device_create(struct clas + va_start(args, fmt); + vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args); + va_end(args); ++ sysfs_create_link(&dev->kobj, &class->subsys.kset.kobj, "subsystem"); + retval = device_register(dev); + if (retval) + goto error; +@@ -621,6 +627,7 @@ void device_destroy(struct class *class, + up(&class->sem); + + if (dev) { ++ sysfs_remove_link(&dev->kobj, "subsystem"); + list_del_init(&dev->node); + device_unregister(dev); + } +--- gregkh-2.6.orig/fs/partitions/check.c ++++ gregkh-2.6/fs/partitions/check.c +@@ -329,6 +329,7 @@ void delete_partition(struct gendisk *di + p->ios[0] = p->ios[1] = 0; + p->sectors[0] = p->sectors[1] = 0; + devfs_remove("%s/part%d", disk->devfs_name, part); ++ sysfs_remove_link(&p->kobj, "subsystem"); + if (p->holder_dir) + kobject_unregister(p->holder_dir); + kobject_uevent(&p->kobj, KOBJ_REMOVE); +@@ -363,6 +364,7 @@ void add_partition(struct gendisk *disk, + kobject_add(&p->kobj); + if (!disk->part_uevent_suppress) + kobject_uevent(&p->kobj, KOBJ_ADD); ++ sysfs_create_link(&p->kobj, &block_subsys.kset.kobj, "subsystem"); + partition_sysfs_add_subdir(p); + disk->part[part-1] = p; + } +@@ -398,6 +400,7 @@ static void disk_sysfs_symlinks(struct g + kfree(disk_name); + } + } ++ sysfs_create_link(&disk->kobj, &block_subsys.kset.kobj, "subsystem"); + } + + /* Not exported, helper to add_disk(). */ +@@ -548,5 +551,6 @@ void del_gendisk(struct gendisk *disk) + put_device(disk->driverfs_dev); + disk->driverfs_dev = NULL; + } ++ sysfs_remove_link(&disk->kobj, "subsystem"); + kobject_del(&disk->kobj); + } diff --git a/driver/driver-model-add-isa-bus.patch b/driver/driver-model-add-isa-bus.patch new file mode 100644 index 0000000000000..ca7366cc0cf93 --- /dev/null +++ b/driver/driver-model-add-isa-bus.patch @@ -0,0 +1,373 @@ +From rene.herman@keyaccess.nl Tue Jun 6 14:54:03 2006 +Message-ID: <4485F97A.6020205@keyaccess.nl> +Date: Tue, 06 Jun 2006 23:54:02 +0200 +From: Rene Herman <rene.herman@keyaccess.nl> +To: Greg Kroah-Hartman <gregkh@suse.de> +Cc: Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@suse.cz> +Subject: Driver model: add ISA bus + + +During the recent "isa drivers using platform devices" discussion it was +pointed out that (ALSA) ISA drivers ran into the problem of not having +the option to fail driver load (device registration rather) upon not +finding their hardware due to a probe() error not being passed up +through the driver model. In the course of that, I suggested a seperate +ISA bus might be best; Russell King agreed and suggested this bus could +use the .match() method for the actual device discovery. + +The attached does this. For this old non (generically) discoverable ISA +hardware only the driver itself can do discovery so as a difference with +the platform_bus, this isa_bus also distributes match() up to the driver. + +As another difference: these devices only exist in the driver model due +to the driver creating them because it might want to drive them, meaning +that all device creation has been made internal as well. + +The usage model this provides is nice, and has been acked from the ALSA +side by Takashi Iwai and Jaroslav Kysela. The ALSA driver module_init's +now (for oldisa-only drivers) become: + +static int __init alsa_card_foo_init(void) +{ + return isa_register_driver(&snd_foo_isa_driver, SNDRV_CARDS); +} + +static void __exit alsa_card_foo_exit(void) +{ + isa_unregister_driver(&snd_foo_isa_driver); +} + +Quite like the other bus models therefore. This removes a lot of +duplicated init code from the ALSA ISA drivers. + +The passed in isa_driver struct is the regular driver struct embedding a +struct device_driver, the normal probe/remove/shutdown/suspend/resume +callbacks, and as indicated that .match callback. + +The "SNDRV_CARDS" you see being passed in is a "unsigned int ndev" +parameter, indicating how many devices to create and call our methods with. + +The platform_driver callbacks are called with a platform_device param; +the isa_driver callbacks are being called with a "struct device *dev, +unsigned int id" pair directly -- with the device creation completely +internal to the bus it's much cleaner to not leak isa_dev's by passing +them in at all. The id is the only thing we ever want other then the +struct device * anyways, and it makes for nicer code in the callbacks as +well. + +With this additional .match() callback ISA drivers have all options. If +ALSA would want to keep the old non-load behaviour, it could stick all +of the old .probe in .match, which would only keep them registered after +everything was found to be present and accounted for. If it wanted the +behaviour of always loading as it inadvertently did for a bit after the +changeover to platform devices, it could just not provide a .match() and +do everything in .probe() as before. + +If it, as Takashi Iwai already suggested earlier as a way of following +the model from saner buses more closely, wants to load when a later bind +could conceivably succeed, it could use .match() for the prerequisites +(such as checking the user wants the card enabled and that port/irq/dma +values have been passed in) and .probe() for everything else. This is +the nicest model. + +To the code... + +This exports only two functions; isa_{,un}register_driver(). + +isa_register_driver() register's the struct device_driver, and then +loops over the passed in ndev creating devices and registering them. +This causes the bus match method to be called for them, which is: + +int isa_bus_match(struct device *dev, struct device_driver *driver) +{ + struct isa_driver *isa_driver = to_isa_driver(driver); + + if (dev->platform_data == isa_driver) { + if (!isa_driver->match || + isa_driver->match(dev, to_isa_dev(dev)->id)) + return 1; + dev->platform_data = NULL; + } + return 0; +} + +The first thing this does is check if this device is in fact one of this +driver's devices by seeing if the device's platform_data pointer is set +to this driver. Platform devices compare strings, but we don't need to +do that with everything being internal, so isa_register_driver() abuses +dev->platform_data as a isa_driver pointer which we can then check here. +I believe platform_data is available for this, but if rather not, moving +the isa_driver pointer to the private struct isa_dev is ofcourse fine as +well. + +Then, if the the driver did not provide a .match, it matches. If it did, +the driver match() method is called to determine a match. + +If it did _not_ match, dev->platform_data is reset to indicate this to +isa_register_driver which can then unregister the device again. + +If during all this, there's any error, or no devices matched at all +everything is backed out again and the error, or -ENODEV, is returned. + +isa_unregister_driver() just unregisters the matched devices and the +driver itself. + +More global points/questions... + +- I'm introducing include/linux/isa.h. It was available but is ofcourse +a somewhat generic name. Moving more isa stuff over to it in time is +ofcourse fine, so can I have it please? :) + +- I'm using device_initcall() and added the isa.o (dependent on +CONFIG_ISA) after the base driver model things in the Makefile. Will +this do, or I really need to stick it in drivers/base/init.c, inside +#ifdef CONFIG_ISA? It's working fine. + +Lastly -- I also looked, a bit, into integrating with PnP. "Old ISA" +could be another pnp_protocol, but this does not seem to be a good +match, largely due to the same reason platform_devices weren't -- the +devices do not have a life of their own outside the driver, meaning the +pnp_protocol {get,set}_resources callbacks would need to callback into +driver -- which again means you first need to _have_ that driver. Even +if there's clean way around that, you only end up inventing fake but +valid-form PnP IDs and generally catering to the PnP layer without any +practical advantages over this very simple isa_bus. The thing I also +suggested earlier about the user echoing values into /sys to set up the +hardware from userspace first is... well, cute, but a horrible idea from +a user standpoint. + +Comments ofcourse appreciated. Hope it's okay. As said, the usage model +is nice at least. + +Signed-off-by: Rene Herman <rene.herman@keyaccess.nl> + +--- + drivers/base/Makefile | 1 + drivers/base/isa.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/isa.h | 28 +++++++ + 3 files changed, 209 insertions(+) + +--- gregkh-2.6.orig/drivers/base/Makefile ++++ gregkh-2.6/drivers/base/Makefile +@@ -5,6 +5,7 @@ obj-y := core.o sys.o bus.o dd.o \ + cpu.o firmware.o init.o map.o dmapool.o \ + attribute_container.o transport_class.o + obj-y += power/ ++obj-$(CONFIG_ISA) += isa.o + obj-$(CONFIG_FW_LOADER) += firmware_class.o + obj-$(CONFIG_NUMA) += node.o + obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o +--- /dev/null ++++ gregkh-2.6/drivers/base/isa.c +@@ -0,0 +1,180 @@ ++/* ++ * ISA bus. ++ */ ++ ++#include <linux/device.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/isa.h> ++ ++static struct device isa_bus = { ++ .bus_id = "isa" ++}; ++ ++struct isa_dev { ++ struct device dev; ++ struct device *next; ++ unsigned int id; ++}; ++ ++#define to_isa_dev(x) container_of((x), struct isa_dev, dev) ++ ++static int isa_bus_match(struct device *dev, struct device_driver *driver) ++{ ++ struct isa_driver *isa_driver = to_isa_driver(driver); ++ ++ if (dev->platform_data == isa_driver) { ++ if (!isa_driver->match || ++ isa_driver->match(dev, to_isa_dev(dev)->id)) ++ return 1; ++ dev->platform_data = NULL; ++ } ++ return 0; ++} ++ ++static int isa_bus_probe(struct device *dev) ++{ ++ struct isa_driver *isa_driver = dev->platform_data; ++ ++ if (isa_driver->probe) ++ return isa_driver->probe(dev, to_isa_dev(dev)->id); ++ ++ return 0; ++} ++ ++static int isa_bus_remove(struct device *dev) ++{ ++ struct isa_driver *isa_driver = dev->platform_data; ++ ++ if (isa_driver->remove) ++ return isa_driver->remove(dev, to_isa_dev(dev)->id); ++ ++ return 0; ++} ++ ++static void isa_bus_shutdown(struct device *dev) ++{ ++ struct isa_driver *isa_driver = dev->platform_data; ++ ++ if (isa_driver->shutdown) ++ isa_driver->shutdown(dev, to_isa_dev(dev)->id); ++} ++ ++static int isa_bus_suspend(struct device *dev, pm_message_t state) ++{ ++ struct isa_driver *isa_driver = dev->platform_data; ++ ++ if (isa_driver->suspend) ++ return isa_driver->suspend(dev, to_isa_dev(dev)->id, state); ++ ++ return 0; ++} ++ ++static int isa_bus_resume(struct device *dev) ++{ ++ struct isa_driver *isa_driver = dev->platform_data; ++ ++ if (isa_driver->resume) ++ return isa_driver->resume(dev, to_isa_dev(dev)->id); ++ ++ return 0; ++} ++ ++static struct bus_type isa_bus_type = { ++ .name = "isa", ++ .match = isa_bus_match, ++ .probe = isa_bus_probe, ++ .remove = isa_bus_remove, ++ .shutdown = isa_bus_shutdown, ++ .suspend = isa_bus_suspend, ++ .resume = isa_bus_resume ++}; ++ ++static void isa_dev_release(struct device *dev) ++{ ++ kfree(to_isa_dev(dev)); ++} ++ ++void isa_unregister_driver(struct isa_driver *isa_driver) ++{ ++ struct device *dev = isa_driver->devices; ++ ++ while (dev) { ++ struct device *tmp = to_isa_dev(dev)->next; ++ device_unregister(dev); ++ dev = tmp; ++ } ++ driver_unregister(&isa_driver->driver); ++} ++EXPORT_SYMBOL_GPL(isa_unregister_driver); ++ ++int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev) ++{ ++ int error; ++ unsigned int id; ++ ++ isa_driver->driver.bus = &isa_bus_type; ++ isa_driver->devices = NULL; ++ ++ error = driver_register(&isa_driver->driver); ++ if (error) ++ return error; ++ ++ for (id = 0; id < ndev; id++) { ++ struct isa_dev *isa_dev; ++ ++ isa_dev = kzalloc(sizeof *isa_dev, GFP_KERNEL); ++ if (!isa_dev) { ++ error = -ENOMEM; ++ break; ++ } ++ ++ isa_dev->dev.parent = &isa_bus; ++ isa_dev->dev.bus = &isa_bus_type; ++ ++ snprintf(isa_dev->dev.bus_id, BUS_ID_SIZE, "%s.%u", ++ isa_driver->driver.name, id); ++ ++ isa_dev->dev.platform_data = isa_driver; ++ isa_dev->dev.release = isa_dev_release; ++ isa_dev->id = id; ++ ++ error = device_register(&isa_dev->dev); ++ if (error) { ++ put_device(&isa_dev->dev); ++ break; ++ } ++ ++ if (isa_dev->dev.platform_data) { ++ isa_dev->next = isa_driver->devices; ++ isa_driver->devices = &isa_dev->dev; ++ } else ++ device_unregister(&isa_dev->dev); ++ } ++ ++ if (!error && !isa_driver->devices) ++ error = -ENODEV; ++ ++ if (error) ++ isa_unregister_driver(isa_driver); ++ ++ return error; ++} ++EXPORT_SYMBOL_GPL(isa_register_driver); ++ ++static int __init isa_bus_init(void) ++{ ++ int error; ++ ++ error = bus_register(&isa_bus_type); ++ if (!error) { ++ error = device_register(&isa_bus); ++ if (error) ++ bus_unregister(&isa_bus_type); ++ } ++ return error; ++} ++ ++device_initcall(isa_bus_init); +--- /dev/null ++++ gregkh-2.6/include/linux/isa.h +@@ -0,0 +1,28 @@ ++/* ++ * ISA bus. ++ */ ++ ++#ifndef __LINUX_ISA_H ++#define __LINUX_ISA_H ++ ++#include <linux/device.h> ++#include <linux/kernel.h> ++ ++struct isa_driver { ++ int (*match)(struct device *, unsigned int); ++ int (*probe)(struct device *, unsigned int); ++ int (*remove)(struct device *, unsigned int); ++ void (*shutdown)(struct device *, unsigned int); ++ int (*suspend)(struct device *, unsigned int, pm_message_t); ++ int (*resume)(struct device *, unsigned int); ++ ++ struct device_driver driver; ++ struct device *devices; ++}; ++ ++#define to_isa_driver(x) container_of((x), struct isa_driver, driver) ++ ++int isa_register_driver(struct isa_driver *, unsigned int); ++void isa_unregister_driver(struct isa_driver *); ++ ++#endif /* __LINUX_ISA_H */ diff --git a/driver/put_device-might_sleep.patch b/driver/put_device-might_sleep.patch index 78871aa10c2f0..2c7eb2281b1c7 100644 --- a/driver/put_device-might_sleep.patch +++ b/driver/put_device-might_sleep.patch @@ -12,7 +12,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- gregkh-2.6.orig/drivers/base/core.c +++ gregkh-2.6/drivers/base/core.c -@@ -411,6 +411,7 @@ struct device * get_device(struct device +@@ -414,6 +414,7 @@ struct device * get_device(struct device */ void put_device(struct device * dev) { |