All of lore.kernel.org
 help / color / mirror / Atom feed
From: Nathaniel McCallum <nathaniel@natemccallum.com>
To: linux-kernel@vger.kernel.org
Subject: [RFC] [PATCH] Loaded driver modalias
Date: Tue, 04 Nov 2008 13:39:19 -0500	[thread overview]
Message-ID: <491096D7.10808@natemccallum.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 885 bytes --]

Please CC me to responses as I'm not subscribed to LKML.  Also, this is 
my first kernel patch, advise is certainly welcome.

For something I'm working on I have the need to answer the question, 
"given a hardware ID, does Linux distro X have a driver to support this 
hardware?" and more specifically, "which drivers support this hardware?" 
I can, generally speaking, get this data from files like 
/lib/modules/*/modules.alias.  However, this does not work for drivers 
built into the kernel.  With that in mind, I've cooked up a little proof 
of concept. Basically, its a sysfs file 
/sys/modules/$module/drivers/$driver/modalias that, when read, contains 
modalias-style filters for this driver.

The attached patch only does this for PCI drivers, each subsystem would 
need a patch like this.  Is this idea crazy?  Is there a better 
implementation?

Thanks!

Nathaniel McCallum

[-- Attachment #2: linux-2.6-pci-driver-modalias.patch --]
[-- Type: text/x-patch, Size: 2973 bytes --]

diff -Nru linux-2.6.27.orig/drivers/pci/pci-driver.c linux-2.6.27/drivers/pci/pci-driver.c
--- linux-2.6.27.orig/drivers/pci/pci-driver.c	2008-10-09 18:13:53.000000000 -0400
+++ linux-2.6.27/drivers/pci/pci-driver.c	2008-11-04 08:24:29.000000000 -0500
@@ -118,6 +118,70 @@
 static inline void pci_remove_newid_file(struct pci_driver *drv) {}
 #endif
 
+#define ADD(buf, size, cond, wdata, data, wodata)				\
+{										\
+	if (cond) {								\
+		if (snprintf(buf, size, "%s" wdata, buf, data) >= size)		\
+			return -ENOMEM;						\
+	}									\
+	else {									\
+		if (snprintf(buf, size, "%s" wodata, buf) >= size)		\
+			return -ENOMEM;						\
+	}									\
+}
+
+#define PCI_MODALIAS(buf, size, v, d, sv, sd, c, cm) \
+{											\
+ADD(buf, size, 1, "%s", "pci:", "")							\
+ADD(buf, size,  v != PCI_ANY_ID, "v%08X",  v,  "v*")					\
+ADD(buf, size,  d != PCI_ANY_ID, "d%08X",  d,  "d*")					\
+ADD(buf, size, sv != PCI_ANY_ID, "sv%08X", sv, "sv*")					\
+ADD(buf, size, sd != PCI_ANY_ID, "sd%08X", sd, "sd*")					\
+ADD(buf, size, ((cm >> 16) & 0xFF) == 0xFF, "bc%02X", ((c >> 16) & 0xFF), "bc*")	\
+ADD(buf, size, ((cm >>  8) & 0xFF) == 0xFF, "sc%02X", ((c >>  8) & 0xFF), "sc*")	\
+ADD(buf, size, ((cm >>  0) & 0xFF) == 0xFF, "i%02X*", ((c >>  0) & 0xFF), "i*")		\
+ADD(buf, size, 1, "%s", "\n", "")							\
+}
+
+static ssize_t
+show_modaliases(struct device_driver *driver, char *buf)
+{
+	struct pci_driver *pdrv = to_pci_driver(driver);
+	struct list_head *pos;
+	struct pci_dynid *dynid;
+	int i;
+
+	/* Reset the buffer to be blank */
+	buf[0] = '\0';
+
+	/* List the static ids */
+	for (i=0 ; pdrv->id_table[i].vendor != 0 &&
+                   pdrv->id_table[i].device != 0; i++) {
+		PCI_MODALIAS(buf, PAGE_SIZE,
+				pdrv->id_table[i].vendor,
+				pdrv->id_table[i].device,
+				pdrv->id_table[i].subvendor,
+				pdrv->id_table[i].subdevice,
+				pdrv->id_table[i].class,
+				pdrv->id_table[i].class_mask)
+	}
+	
+	/* List the dynamic ids */
+	list_for_each(pos, &pdrv->dynids.list) {
+		dynid = list_entry(pos, struct pci_dynid, node);
+		PCI_MODALIAS(buf, PAGE_SIZE,
+				dynid->id.vendor,
+				dynid->id.device,
+				dynid->id.subvendor,
+				dynid->id.subdevice,
+				dynid->id.class,
+				dynid->id.class_mask)
+	}
+
+	return strlen(buf);
+}
+static DRIVER_ATTR(modaliases, S_IRUGO, show_modaliases, NULL);
+
 /**
  * pci_match_id - See if a pci device matches a given pci_id table
  * @ids: array of PCI device id structures to search in
@@ -702,9 +766,11 @@
 		return error;
 
 	error = pci_create_newid_file(drv);
-	if (error)
-		driver_unregister(&drv->driver);
+	if (!error)
+		error = driver_create_file(&drv->driver, &driver_attr_modaliases);
 
+	if (error)
+		pci_unregister_driver(drv);
 	return error;
 }
 
@@ -722,6 +788,7 @@
 pci_unregister_driver(struct pci_driver *drv)
 {
 	pci_remove_newid_file(drv);
+	driver_remove_file(&drv->driver, &driver_attr_modaliases);
 	driver_unregister(&drv->driver);
 	pci_free_dynids(drv);
 }

             reply	other threads:[~2008-11-04 18:40 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-11-04 18:39 Nathaniel McCallum [this message]
2008-11-04 19:55 ` [RFC] [PATCH] Loaded driver modalias Kay Sievers
2008-11-04 20:25   ` Nathaniel McCallum
2008-11-04 21:22   ` Nathaniel McCallum

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=491096D7.10808@natemccallum.com \
    --to=nathaniel@natemccallum.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.