public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC][PATCH] add driver matching priorities
@ 2005-01-28 22:30 Adam Belay
  2005-01-28 23:23 ` Dmitry Torokhov
  2005-02-10  8:41 ` Greg KH
  0 siblings, 2 replies; 20+ messages in thread
From: Adam Belay @ 2005-01-28 22:30 UTC (permalink / raw)
  To: greg; +Cc: rml, linux-kernel

Hi,

This patch adds initial support for driver matching priorities to the
driver model.  It is needed for my work on converting the pci bridge
driver to use "struct device_driver".  It may also be helpful for driver
with more complex (or long id lists as I've seen in many cases) matching
criteria. 

"match" has been added to "struct device_driver".  There are now two
steps in the matching process.  The first step is a bus specific filter
that determines possible driver candidates.  The second step is a driver
specific match function that verifies if the driver will work with the
hardware, and returns a priority code (how well it is able to handle the
device).  The bus layer could override the driver's match function if
necessary (similar to how it passes *probe through it's layer and then
on to the actual driver).

The current priorities are as follows:

enum {
	MATCH_PRIORITY_FAILURE = 0,
	MATCH_PRIORITY_GENERIC,
	MATCH_PRIORITY_NORMAL,
	MATCH_PRIORITY_VENDOR,
};

let me know if any of this would need to be changed.  For example, the
"struct bus_type" match function could return a priority code.

Of course this patch is not going to be effective alone.  We also need
to change the init order.  If a driver is registered early but isn't the
best available, it will be bound to the device prematurely.  This would
be a problem for carbus (yenta) bridges.

I think we may have to load all in kernel drivers first, and then begin
matching them to hardware.  Do you agree?  If so, I'd be happy to make a
patch for that too.

Thanks,
Adam


--- a/drivers/base/bus.c	2005-01-20 17:37:46.000000000 -0500
+++ b/drivers/base/bus.c	2005-01-28 16:59:00.000000000 -0500
@@ -286,6 +286,9 @@
 	if (drv->bus->match && !drv->bus->match(dev, drv))
 		return -ENODEV;
 
+	if (drv->match && !drv->match(dev))
+		return -ENODEV;
+
 	dev->driver = drv;
 	if (drv->probe) {
 		int error = drv->probe(dev);
@@ -299,6 +302,42 @@
 	return 0;
 }
 
+/**
+ *	driver_probe_device_priority - attempt to bind device & driver with a
+ *				       given match level priority 
+ *	@drv:		driver.
+ *	@dev:		device.
+ *	@priority	the match level priority
+ */
+
+static int driver_probe_device_priority(struct device_driver * drv,
+					struct device * dev, int priority)
+{
+	int matchp;
+
+	if (drv->bus->match && !drv->bus->match(dev, drv))
+		return -ENODEV;
+
+	if (drv->match) {
+		matchp = drv->match(dev);
+	} else
+		matchp = MATCH_PRIORITY_NORMAL;
+
+	if (matchp != priority)
+		return -ENODEV;
+
+	dev->driver = drv;
+	if (drv->probe) {
+		int error = drv->probe(dev);
+		if (error) {
+			dev->driver = NULL;
+			return error;
+		}
+	}
+
+	device_bind_driver(dev);
+	return 0;
+}
 
 /**
  *	device_attach - try to attach device to a driver.
@@ -312,17 +351,20 @@
 {
  	struct bus_type * bus = dev->bus;
 	struct list_head * entry;
-	int error;
+	int error, matchp = MATCH_PRIORITY_VENDOR;
 
 	if (dev->driver) {
 		device_bind_driver(dev);
 		return 1;
 	}
 
-	if (bus->match) {
+	if (!bus->match)
+		return 0;
+		
+	while (matchp > 0) {
 		list_for_each(entry, &bus->drivers.list) {
 			struct device_driver * drv = to_drv(entry);
-			error = driver_probe_device(drv, dev);
+			error = driver_probe_device_priority(drv, dev, matchp);
 			if (!error)
 				/* success, driver matched */
 				return 1;
@@ -332,6 +374,7 @@
 				    "%s: probe of %s failed with error %d\n",
 				    drv->name, dev->bus_id, error);
 		}
+		matchp--;
 	}
 
 	return 0;
--- a/include/linux/device.h	2005-01-20 17:37:26.000000000 -0500
+++ b/include/linux/device.h	2005-01-28 16:40:22.000000000 -0500
@@ -41,6 +41,13 @@
 	RESUME_ENABLE,
 };
 
+enum {
+	MATCH_PRIORITY_FAILURE = 0,
+	MATCH_PRIORITY_GENERIC,
+	MATCH_PRIORITY_NORMAL,
+	MATCH_PRIORITY_VENDOR,
+};
+
 struct device;
 struct device_driver;
 struct class;
@@ -108,6 +115,7 @@
 
 	struct module 		* owner;
 
+	int	(*match)	(struct device * dev);
 	int	(*probe)	(struct device * dev);
 	int 	(*remove)	(struct device * dev);
 	void	(*shutdown)	(struct device * dev);




^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2005-03-01  8:20 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-01-28 22:30 [RFC][PATCH] add driver matching priorities Adam Belay
2005-01-28 23:23 ` Dmitry Torokhov
2005-01-28 23:33   ` Adam Belay
2005-01-28 23:51     ` Dmitry Torokhov
2005-01-29  0:05       ` Adam Belay
2005-01-29  0:11   ` Al Viro
2005-01-29  2:45     ` Dmitry Torokhov
2005-02-10  8:41 ` Greg KH
2005-02-10 17:18   ` Adam Belay
2005-02-10 18:08     ` Dmitry Torokhov
2005-02-10 18:12     ` Greg KH
2005-02-10 21:26       ` Adam Belay
2005-02-10 18:33     ` Greg KH
2005-02-10 18:46       ` Dmitry Torokhov
2005-02-10 21:32         ` Adam Belay
2005-02-10 18:45     ` Russell King
2005-02-10 21:37       ` Adam Belay
2005-02-25 23:41         ` Greg KH
2005-03-01  0:05           ` Adam Belay
2005-03-01  7:58             ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox