* Driver model ISA bus
@ 2006-05-04 22:07 Rene Herman
0 siblings, 0 replies; 9+ messages in thread
From: Rene Herman @ 2006-05-04 22:07 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Takashi Iwai, Jaroslav Kysela, Linux Kernel, ALSA devel
[-- Attachment #1: Type: text/plain, Size: 6142 bytes --]
Hi Greg.
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; Russel 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.
Rene.
[-- Attachment #2: isa_bus-3.diff --]
[-- Type: text/plain, Size: 5569 bytes --]
Index: local/drivers/base/isa.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ local/drivers/base/isa.c 2006-05-02 23:18:34.000000000 +0200
@@ -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);
Index: local/include/linux/isa.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ local/include/linux/isa.h 2006-05-02 23:17:18.000000000 +0200
@@ -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 */
Index: local/drivers/base/Makefile
===================================================================
--- local.orig/drivers/base/Makefile 2006-05-02 22:44:00.000000000 +0200
+++ local/drivers/base/Makefile 2006-05-02 22:45:32.000000000 +0200
@@ -4,6 +4,7 @@ obj-y := core.o sys.o bus.o dd.o \
driver.o class.o platform.o \
cpu.o firmware.o init.o map.o dmapool.o \
attribute_container.o transport_class.o
+obj-$(CONFIG_ISA) += isa.o
obj-y += power/
obj-$(CONFIG_FW_LOADER) += firmware_class.o
obj-$(CONFIG_NUMA) += node.o
^ permalink raw reply [flat|nested] 9+ messages in thread
* Driver model ISA bus
@ 2006-06-06 21:54 Rene Herman
2006-06-16 23:42 ` Greg KH
0 siblings, 1 reply; 9+ messages in thread
From: Rene Herman @ 2006-06-06 21:54 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Takashi Iwai, Jaroslav Kysela, Linux Kernel, ALSA devel
[-- Attachment #1: Type: text/plain, Size: 6318 bytes --]
Hi Greg.
The below was sent a month ago and I haven't heard anything back. Saw
you saying "it's getting there" about this thing on the kernelnewbies
list but where's there?
Signed-off-by: Rene Herman <rene.herman@keyaccess.nl>
===
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.
===
Rene.
[-- Attachment #2: isa_bus.diff --]
[-- Type: text/plain, Size: 5574 bytes --]
Index: local/drivers/base/isa.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ local/drivers/base/isa.c 2006-05-31 01:57:00.000000000 +0200
@@ -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);
Index: local/include/linux/isa.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ local/include/linux/isa.h 2006-05-31 01:23:24.000000000 +0200
@@ -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 */
Index: local/drivers/base/Makefile
===================================================================
--- local.orig/drivers/base/Makefile 2006-05-31 01:22:52.000000000 +0200
+++ local/drivers/base/Makefile 2006-05-31 01:23:24.000000000 +0200
@@ -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
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Driver model ISA bus
2006-06-06 21:54 Rene Herman
@ 2006-06-16 23:42 ` Greg KH
2006-06-18 18:51 ` Rene Herman
0 siblings, 1 reply; 9+ messages in thread
From: Greg KH @ 2006-06-16 23:42 UTC (permalink / raw)
To: Rene Herman
Cc: Greg Kroah-Hartman, Takashi Iwai, Jaroslav Kysela, Linux Kernel,
ALSA devel
On Tue, Jun 06, 2006 at 11:54:02PM +0200, Rene Herman wrote:
> Hi Greg.
>
> The below was sent a month ago and I haven't heard anything back. Saw
> you saying "it's getting there" about this thing on the kernelnewbies
> list but where's there?
>
Sorry for the delay. It looks great to me so I've added it to my tree
and will push it upstream when I can.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Driver model ISA bus
2006-06-16 23:42 ` Greg KH
@ 2006-06-18 18:51 ` Rene Herman
0 siblings, 0 replies; 9+ messages in thread
From: Rene Herman @ 2006-06-18 18:51 UTC (permalink / raw)
To: Greg KH
Cc: Greg Kroah-Hartman, Takashi Iwai, Jaroslav Kysela, Linux Kernel,
ALSA devel
Greg KH wrote:
> Sorry for the delay. It looks great to me so I've added it to my
> tree and will push it upstream when I can.
Okay, lovely, thanks.
Takashi: I'll be converting ALSA ISA drivers over to this now. What I'd
in fact would like to do is do that one driver at a time. I have a
metric buttload of these old ISA soundcards and believe it would be a
nice opportunity to actually test these old drivers (and possibly do
some cleanups) as I go along. Would you mind that?
If you'd rather the isa_bus thing was one discrete change, that's also
okay though. I'd then just do that as a somewhat mechanical change and
then revisit those drivers at some later time for additional testing
and/or cleanup.
In either case, I'll ofcourse not submit anything untill this thing has
made -mm.
Rene.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Driver model ISA bus
@ 2006-07-30 8:18 Simon White
2006-07-30 9:55 ` Rene Herman
0 siblings, 1 reply; 9+ messages in thread
From: Simon White @ 2006-07-30 8:18 UTC (permalink / raw)
To: linux-kernel
> On Tue, Jun 06, 2006 at 11:54:02PM +0200, Rene Herman wrote:
>> Hi Greg.
>>
>> The below was sent a month ago and I haven't heard anything back. Saw
>> you saying "it's getting there" about this thing on the kernelnewbies
>> list but where's there?
>>
>
> Sorry for the delay. It looks great to me so I've added it to my tree
> and will push it upstream when I can.
Would it be better to have a name variable directly in isa_device and
then copy that to driver in isa_register_device (like
pci_register_device does)?
I was trying to look for use examples of this code in 2.6.18-rc2 but
didn't see any. Is the intent of name to be the cards address, and
ndev to be the function on a specific card? Would it be better to
seperate name from the thing that ends up in bus_id?
I only ask as was looking to use something similiar to other code
I've seen in kernel in that it seemed the bus_type + bus_id would
uniquely identify a particular card that would pretty much persist
(on removal/addition of hardware?). When a legacy isa device was
found by this code they switched to mangling an id from the cards
address.
I think between that and a probe test you could make pretty sure
you had exactly the same card. Am wondering if this code allowed
for something similiar, in that bus_type + bus_id could be stored
and used later to locate the same card.
Regards,
Simon
--
___________________________________________________
Play 100s of games for FREE! http://games.mail.com/
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Driver model ISA bus
2006-07-30 8:18 Driver model ISA bus Simon White
@ 2006-07-30 9:55 ` Rene Herman
0 siblings, 0 replies; 9+ messages in thread
From: Rene Herman @ 2006-07-30 9:55 UTC (permalink / raw)
To: Simon White; +Cc: linux-kernel
Simon White wrote:
> Would it be better to have a name variable directly in isa_device and
> then copy that to driver in isa_register_device (like
> pci_register_device does)?
No, that wouldn't be useful. The point of this code is largely that the
devices belong to the driver; do not have a life of their own. As such,
naming them after the driver is the correct thibng to do.
> I was trying to look for use examples of this code in 2.6.18-rc2 but
> didn't see any.
Yes, apologies. I was converting ALSA ISA drivers to use it but had (and
have) to deal with a few other matters first all of a sudden. I'll get
to it shortly. There is a usage example I posted on the kernelnewbies
list a while ago:
http://www.spinics.net/lists/newbies/msg21845.html
> Is the intent of name to be the cards address, and ndev to be the
> function on a specific card?
No, the name is just an identifier under which the driver (and devices)
show up in sysfs and ndev the number of devices we want to the driver
code to call our methods with -- given that ISA devices do not announce
themselves we have to tell the driver core this.
By the way, please CC people on LKML. I'm still being busy and had to
pick this out of the trash where it caught my eye by chance...
Rene.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Driver model ISA bus
@ 2006-07-30 12:24 Simon White
2006-07-30 13:13 ` Rene Herman
0 siblings, 1 reply; 9+ messages in thread
From: Simon White @ 2006-07-30 12:24 UTC (permalink / raw)
To: Rene Herman; +Cc: linux-kernel
> > Is the intent of name to be the cards address, and ndev to be the
> > function on a specific card?
>
> No, the name is just an identifier under which the driver (and
> devices) show up in sysfs and ndev the number of devices we want to
> the driver code to call our methods with -- given that ISA devices
> do not announce themselves we have to tell the driver core this.
If I understood correctly, it is the maximum number of devices our
driver will support. I got confused with an earlier version of this
whereby devices were to be registered with the isa bus on finding
them.
One further thing I'd like to check. In my case there can only be
a maximum of 4 cards, limited by the possible hardware addresses
manually selectable. Will the probe calls just happen or do they
require some userspace activity to occur (referring to that echo
bind in the example).
> By the way, please CC people on LKML. I'm still being busy and had
> to pick this out of the trash where it caught my eye by chance...
Sorry, I caught this message on lkml.org and it had stripped the
email addresses. Not sure what else to use (am not currently
subscribed to the list either). I also seem to notice hitting
reply to a message appears to start a new thread rather than
add to an existing one...
Simon
--
___________________________________________________
Play 100s of games for FREE! http://games.mail.com/
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Driver model ISA bus
2006-07-30 12:24 Simon White
@ 2006-07-30 13:13 ` Rene Herman
2006-07-30 13:21 ` Rene Herman
0 siblings, 1 reply; 9+ messages in thread
From: Rene Herman @ 2006-07-30 13:13 UTC (permalink / raw)
To: Simon White; +Cc: linux-kernel
Simon White wrote:
>> No, the name is just an identifier under which the driver (and
>> devices) show up in sysfs and ndev the number of devices we want to
>> the driver code to call our methods with -- given that ISA devices
>> do not announce themselves we have to tell the driver core this.
>
> If I understood correctly, it is the maximum number of devices our
> driver will support.
Yes.
> I got confused with an earlier version of this whereby devices were
> to be registered with the isa bus on finding them.
>
> One further thing I'd like to check. In my case there can only be a
> maximum of 4 cards, limited by the possible hardware addresses
> manually selectable. Will the probe calls just happen or do they
> require some userspace activity to occur (referring to that echo bind
> in the example).
If you provide a match() method as part of the isa_driver struct the
calls to that method will just happen and if it returns non-zero,
indicating a match between this driver and the device, the calls to the
probe method will just happen. On a non-match (0), the device is
unregistered again.
The driver model ISA bus is meant to provide a framework for ISA drivers
close to the model from saner busses such as PCI. PCI drivers load
always (even without their PCI ID present) since the user could do
things such as supply a new PCI ID to the driver after it's loaded
through sysfs (the new_id file).
As the example says, the match() method is intended only for things
which should make the device fail to register since it could never be
useful anymore -- in the example, if a port value hasn't been passed in
we can't do anything so fail the device registration. Due to the fact
that most other problems could be fixed later while the driver is loaded
(such as by unloading a different driver which was keeping our ports
busy) things such as that are also really the only things you should
check in the match method, and do everything else from the probe method.
On the other hand, if you are really dead set against loading when you
can't immediately drive something that's up to you as well -- you decide
when to fail the match().
Rene.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Driver model ISA bus
2006-07-30 13:13 ` Rene Herman
@ 2006-07-30 13:21 ` Rene Herman
0 siblings, 0 replies; 9+ messages in thread
From: Rene Herman @ 2006-07-30 13:21 UTC (permalink / raw)
To: Simon White; +Cc: linux-kernel
Rene Herman wrote:
> On the other hand, if you are really dead set against loading when
> you can't immediately drive something that's up to you as well -- you
> decide when to fail the match().
Oh, forgot to mention, if vice-versa you don't mind always loading you
don't _have_ to supply a match() method at all.
Maybe you make your port/irq/dma parameter variables in the driver
writable through sysfs or, heaven forbid, you do autoprobing meaning
that there's nothing left that could not be fixed while the driver is
loaded. If you don't provide a .match, your .probe is called always
directly.
Rene.
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2006-07-30 13:17 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-07-30 8:18 Driver model ISA bus Simon White
2006-07-30 9:55 ` Rene Herman
-- strict thread matches above, loose matches on Subject: below --
2006-07-30 12:24 Simon White
2006-07-30 13:13 ` Rene Herman
2006-07-30 13:21 ` Rene Herman
2006-06-06 21:54 Rene Herman
2006-06-16 23:42 ` Greg KH
2006-06-18 18:51 ` Rene Herman
2006-05-04 22:07 Rene Herman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox