linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [UPDATED PATCH] pcmcia: add bus_type pcmcia_bus_type, struct pcmcia_driver
@ 2003-03-01 21:33 Dominik Brodowski
  2003-03-02 19:37 ` John Weber
  0 siblings, 1 reply; 4+ messages in thread
From: Dominik Brodowski @ 2003-03-01 21:33 UTC (permalink / raw)
  To: torvalds; +Cc: linux-kernel

This patch adds a new bus_type pcmcia_bus_type, and registers all pcmcia
drivers with this bus within the old register_pccard_driver()
function. 

Alternatively, a new registration function "pcmcia_register_driver()"
(and its counterpart,  "pcmcia_unregister_driver()") can be used --
the pcnet_cs.c driver is converted as an example.

This updated version fixes the compilation breakage seen with gcc-2.95.3
because of incompatible C99 initializers (sorry, Russell). 

Please apply,
       Dominik

 drivers/net/pcmcia/pcnet_cs.c |   13 ++
 drivers/pcmcia/ds.c           |  224 +++++++++++++++++++++++++++---------------
 include/pcmcia/ds.h           |   15 ++
 3 files changed, 175 insertions(+), 77 deletions(-)


diff -ruN linux-original/drivers/net/pcmcia/pcnet_cs.c linux/drivers/net/pcmcia/pcnet_cs.c
--- linux-original/drivers/net/pcmcia/pcnet_cs.c	2003-03-01 21:48:59.000000000 +0100
+++ linux/drivers/net/pcmcia/pcnet_cs.c	2003-03-01 21:50:47.000000000 +0100
@@ -1617,6 +1617,15 @@
 
 /*====================================================================*/
 
+static struct pcmcia_driver pcnet_driver = {
+	.drv		= {
+		.name	= "pcnet_cs",
+	},
+	.attach		= pcnet_attach,
+	.detach		= pcnet_detach,
+	.owner		= THIS_MODULE,
+};
+
 static int __init init_pcnet_cs(void)
 {
     servinfo_t serv;
@@ -1627,14 +1636,14 @@
 	       "does not match!\n");
 	return -EINVAL;
     }
-    register_pccard_driver(&dev_info, &pcnet_attach, &pcnet_detach);
+    pcmcia_register_driver(&pcnet_driver);
     return 0;
 }
 
 static void __exit exit_pcnet_cs(void)
 {
     DEBUG(0, "pcnet_cs: unloading\n");
-    unregister_pccard_driver(&dev_info);
+    pcmcia_unregister_driver(&pcnet_driver);
     while (dev_list != NULL)
 	pcnet_detach(dev_list);
 }
diff -ruN linux-original/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c
--- linux-original/drivers/pcmcia/ds.c	2003-03-01 21:49:03.000000000 +0100
+++ linux/drivers/pcmcia/ds.c	2003-03-01 22:14:30.000000000 +0100
@@ -86,7 +86,7 @@
 } driver_info_t;
 
 typedef struct socket_bind_t {
-    driver_info_t	*driver;
+    struct pcmcia_driver *driver;
     u_char		function;
     dev_link_t		*instance;
     struct socket_bind_t *next;
@@ -124,9 +124,6 @@
 /* Device driver ID passed to Card Services */
 static dev_info_t dev_info = "Driver Services";
 
-/* Linked list of all registered device drivers */
-static driver_info_t *root_driver = NULL;
-
 static int sockets = 0, major_dev = -1;
 static socket_info_t *socket_table = NULL;
 
@@ -143,35 +140,65 @@
     pcmcia_report_error(handle, &err);
 }
 
-/*======================================================================
 
-    Register_pccard_driver() and unregister_pccard_driver() are used
-    tell Driver Services that a PC Card client driver is available to
-    be bound to sockets.
-    
-======================================================================*/
+static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info);
+
+/**
+ * pcmcia_register_driver - register a PCMCIA driver with the bus core
+ *
+ * Registers a PCMCIA driver with the PCMCIA bus core.
+ */
+int pcmcia_register_driver(struct pcmcia_driver *driver)
+{
+	if (!driver)
+		return -EINVAL;
+
+ 	driver->use_count = 0;
+ 	driver->status = init_status;
+	driver->drv.bus = &pcmcia_bus_type;
+
+	return driver_register(&driver->drv);
+}
+EXPORT_SYMBOL(pcmcia_register_driver);
+
+/**
+ * pcmcia_unregister_driver - unregister a PCMCIA driver with the bus core
+ */
+void pcmcia_unregister_driver(struct pcmcia_driver *driver)
+{
+	socket_bind_t *b;
+	int i;
+
+	if (driver->use_count > 0) {
+		/* Blank out any left-over device instances */
+		driver->attach = NULL; driver->detach = NULL;
+		for (i = 0; i < sockets; i++)
+			for (b = socket_table[i].bind; b; b = b->next)
+				if (b->driver == driver) 
+					b->instance = NULL;
+ 	}
+	
+	driver_unregister(&driver->drv);
+}
+EXPORT_SYMBOL(pcmcia_unregister_driver);
+
 
 int register_pccard_driver(dev_info_t *dev_info,
 			   dev_link_t *(*attach)(void),
 			   void (*detach)(dev_link_t *))
 {
-    driver_info_t *driver;
+    struct pcmcia_driver *driver;
     socket_bind_t *b;
     int i;
 
     DEBUG(0, "ds: register_pccard_driver('%s')\n", (char *)dev_info);
-    for (driver = root_driver; driver; driver = driver->next)
-	if (strncmp((char *)dev_info, (char *)driver->dev_info,
-		    DEV_NAME_LEN) == 0)
-	    break;
+    driver = get_pcmcia_driver(dev_info);
     if (!driver) {
-	driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL);
+	driver = kmalloc(sizeof(struct pcmcia_driver), GFP_KERNEL);
 	if (!driver) return -ENOMEM;
-	strncpy(driver->dev_info, (char *)dev_info, DEV_NAME_LEN);
-	driver->use_count = 0;
-	driver->status = init_status;
-	driver->next = root_driver;
-	root_driver = driver;
+	memset(driver, 0, sizeof(struct pcmcia_driver));
+	driver->drv.name = (char *)dev_info;
+	pcmcia_register_driver(driver);
     }
 
     driver->attach = attach;
@@ -185,7 +212,7 @@
 	    b->instance = driver->attach();
 	    if (b->instance == NULL)
 		printk(KERN_NOTICE "ds: unable to create instance "
-		       "of '%s'!\n", driver->dev_info);
+		       "of '%s'!\n", driver->drv.name);
 	}
     
     return 0;
@@ -195,44 +222,43 @@
 
 int unregister_pccard_driver(dev_info_t *dev_info)
 {
-    driver_info_t *target, **d = &root_driver;
-    socket_bind_t *b;
-    int i;
+    struct pcmcia_driver *driver;
     
     DEBUG(0, "ds: unregister_pccard_driver('%s')\n",
 	  (char *)dev_info);
-    while ((*d) && (strncmp((*d)->dev_info, (char *)dev_info,
-			    DEV_NAME_LEN) != 0))
-	d = &(*d)->next;
-    if (*d == NULL)
+    driver = get_pcmcia_driver(dev_info);
+    if (!driver)
 	return -ENODEV;
-    
-    target = *d;
-    if (target->use_count == 0) {
-	*d = target->next;
-	kfree(target);
-    } else {
-	/* Blank out any left-over device instances */
-	target->attach = NULL; target->detach = NULL;
-	for (i = 0; i < sockets; i++)
-	    for (b = socket_table[i].bind; b; b = b->next)
-		if (b->driver == target) b->instance = NULL;
-    }
+    pcmcia_unregister_driver(driver);
+    kfree(driver);
     return 0;
 } /* unregister_pccard_driver */
 
 /*====================================================================*/
 
 #ifdef CONFIG_PROC_FS
+static int proc_read_drivers_callback(struct device_driver *driver, void *d)
+{
+	char **p = d;
+	struct pcmcia_driver *p_dev = container_of(driver, 
+						   struct pcmcia_driver, drv);
+
+	*p += sprintf(*p, "%-24.24s %d %d\n", driver->name, p_dev->status,
+		     p_dev->use_count);
+	d = (void *) p;
+
+	return 0;
+}
+
 static int proc_read_drivers(char *buf, char **start, off_t pos,
 			     int count, int *eof, void *data)
 {
-    driver_info_t *d;
-    char *p = buf;
-    for (d = root_driver; d; d = d->next)
-	p += sprintf(p, "%-24.24s %d %d\n", d->dev_info,
-		     d->status, d->use_count);
-    return (p - buf);
+	char *p = buf;
+
+	bus_for_each_drv(&pcmcia_bus_type, NULL, 
+			 (void *) &p, proc_read_drivers_callback);
+
+	return (p - buf);
 }
 #endif
 
@@ -376,7 +402,7 @@
 
 static int bind_request(int i, bind_info_t *bind_info)
 {
-    struct driver_info_t *driver;
+    struct pcmcia_driver *driver;
     socket_bind_t *b;
     bind_req_t bind_req;
     socket_info_t *s = &socket_table[i];
@@ -384,18 +410,14 @@
 
     DEBUG(2, "bind_request(%d, '%s')\n", i,
 	  (char *)bind_info->dev_info);
-    for (driver = root_driver; driver; driver = driver->next)
-	if (strcmp((char *)driver->dev_info,
-		   (char *)bind_info->dev_info) == 0)
-	    break;
+    driver = get_pcmcia_driver(&bind_info->dev_info);
     if (driver == NULL) {
-	driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL);
+	driver = kmalloc(sizeof(struct pcmcia_driver), GFP_KERNEL);
 	if (!driver) return -ENOMEM;
-	strncpy(driver->dev_info, bind_info->dev_info, DEV_NAME_LEN);
-	driver->use_count = 0;
-	driver->next = root_driver;
-	driver->attach = NULL; driver->detach = NULL;
-	root_driver = driver;
+	memset(driver, 0, sizeof(struct pcmcia_driver));
+
+	driver->drv.name = bind_info->dev_info;
+	pcmcia_register_driver(driver);
     }
 
     for (b = s->bind; b; b = b->next)
@@ -409,7 +431,7 @@
 
     bind_req.Socket = i;
     bind_req.Function = bind_info->function;
-    bind_req.dev_info = &driver->dev_info;
+    bind_req.dev_info = (dev_info_t *) driver->drv.name;
     ret = pcmcia_bind_device(&bind_req);
     if (ret != CS_SUCCESS) {
 	cs_error(NULL, BindDevice, ret);
@@ -490,7 +512,7 @@
 #endif
 
     for (b = s->bind; b; b = b->next)
-	if ((strcmp((char *)b->driver->dev_info,
+	if ((strcmp((char *)b->driver->drv.name,
 		    (char *)bind_info->dev_info) == 0) &&
 	    (b->function == bind_info->function))
 	    break;
@@ -524,7 +546,7 @@
     DEBUG(2, "unbind_request(%d, '%s')\n", i,
 	  (char *)bind_info->dev_info);
     for (b = &s->bind; *b; b = &(*b)->next)
-	if ((strcmp((char *)(*b)->driver->dev_info,
+	if ((strcmp((char *)(*b)->driver->drv.name,
 		    (char *)bind_info->dev_info) == 0) &&
 	    ((*b)->function == bind_info->function))
 	    break;
@@ -536,14 +558,6 @@
     if (c->driver->detach) {
 	if (c->instance)
 	    c->driver->detach(c->instance);
-    } else {
-	if (c->driver->use_count == 0) {
-	    driver_info_t **d;
-	    for (d = &root_driver; *d; d = &((*d)->next))
-		if (c->driver == *d) break;
-	    *d = (*d)->next;
-	    kfree(c->driver);
-	}
     }
     *b = c->next;
     kfree(c);
@@ -881,7 +895,18 @@
 
 /*====================================================================*/
 
-int __init init_pcmcia_ds(void)
+struct bus_type pcmcia_bus_type = {
+	.name = "pcmcia",
+};
+EXPORT_SYMBOL(pcmcia_bus_type);
+
+static int __init init_pcmcia_bus(void)
+{
+	bus_register(&pcmcia_bus_type);
+	return 0;
+}
+
+static int __init init_pcmcia_ds(void)
 {
     client_reg_t client_reg;
     servinfo_t serv;
@@ -967,11 +992,7 @@
     return 0;
 }
 
-late_initcall(init_pcmcia_ds);
-
-#ifdef MODULE
-
-void __exit cleanup_module(void)
+static void __exit exit_pcmcia_ds(void)
 {
     int i;
 #ifdef CONFIG_PROC_FS
@@ -984,6 +1005,59 @@
 	pcmcia_deregister_client(socket_table[i].handle);
     sockets = 0;
     kfree(socket_table);
+    bus_unregister(&pcmcia_bus_type);
 }
 
+#ifdef MODULE
+
+/* init_pcmcia_bus must be done early, init_pcmcia_ds late. If we load this 
+ * as a module, we can only specify one initcall, though... 
+ */
+static int __init init_pcmcia_module(void) {
+	init_pcmcia_bus();
+	return init_pcmcia_ds();
+}
+module_init(init_pcmcia_module);
+
+#else
+subsys_initcall(init_pcmcia_bus);
+late_initcall(init_pcmcia_ds);
 #endif
+
+module_exit(exit_pcmcia_ds);
+
+
+/* helpers for backwards-compatible functions */
+
+/* backwards-compatible accessing of driver --- by name! */
+
+struct cmp_data {
+	void *dev_info;
+	struct pcmcia_driver *drv;
+};
+
+static int cmp_drv_callback(struct device_driver *drv, void *data)
+{
+	struct cmp_data *cmp = data;
+	if (strncmp((char *)cmp->dev_info, (char *)drv->name,
+		    DEV_NAME_LEN) == 0) {
+		cmp->drv = container_of(drv, struct pcmcia_driver, drv);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info)
+{
+	int ret;
+	struct cmp_data cmp = {
+		.dev_info = dev_info,
+	};
+	
+	ret = bus_for_each_drv(&pcmcia_bus_type, NULL, &cmp, cmp_drv_callback);
+	if (ret)
+		return cmp.drv;
+	return NULL;
+}
+
+
diff -ruN linux-original/include/pcmcia/ds.h linux/include/pcmcia/ds.h
--- linux-original/include/pcmcia/ds.h	2003-03-01 21:49:10.000000000 +0100
+++ linux/include/pcmcia/ds.h	2003-03-01 22:13:19.000000000 +0100
@@ -32,6 +32,7 @@
 
 #include <pcmcia/driver_ops.h>
 #include <pcmcia/bulkmem.h>
+#include <linux/device.h>
 
 typedef struct tuple_parse_t {
     tuple_t		tuple;
@@ -143,6 +144,20 @@
 #define register_pcmcia_driver register_pccard_driver
 #define unregister_pcmcia_driver unregister_pccard_driver
 
+
+extern struct bus_type pcmcia_bus_type;
+
+struct pcmcia_driver {
+	int			use_count, status;
+	dev_link_t		*(*attach)(void);
+	void			(*detach)(dev_link_t *);
+	struct module		*owner;
+	struct device_driver	drv;
+};
+
+int pcmcia_register_driver(struct pcmcia_driver *driver);
+void pcmcia_unregister_driver(struct pcmcia_driver *driver);
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_DS_H */

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

* Re: [UPDATED PATCH] pcmcia: add bus_type pcmcia_bus_type, struct pcmcia_driver
  2003-03-01 21:33 [UPDATED PATCH] pcmcia: add bus_type pcmcia_bus_type, struct pcmcia_driver Dominik Brodowski
@ 2003-03-02 19:37 ` John Weber
  2003-03-02 21:06   ` Dominik Brodowski
  0 siblings, 1 reply; 4+ messages in thread
From: John Weber @ 2003-03-02 19:37 UTC (permalink / raw)
  To: Dominik Brodowski, linux-kernel

Dominik Brodowski wrote:
> This patch adds a new bus_type pcmcia_bus_type, and registers all pcmcia
> drivers with this bus within the old register_pccard_driver()
> function. 
> 
> Alternatively, a new registration function "pcmcia_register_driver()"
> (and its counterpart,  "pcmcia_unregister_driver()") can be used --
> the pcnet_cs.c driver is converted as an example.
> 
> This updated version fixes the compilation breakage seen with gcc-2.95.3
> because of incompatible C99 initializers (sorry, Russell). 

I've applied this patch, and have run the kernel for a few days without 
problems.

Do you have an example driver ported to this new api?  I can help 
convert drivers.


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

* Re: [UPDATED PATCH] pcmcia: add bus_type pcmcia_bus_type, struct pcmcia_driver
  2003-03-02 19:37 ` John Weber
@ 2003-03-02 21:06   ` Dominik Brodowski
  2003-03-02 21:18     ` Russell King
  0 siblings, 1 reply; 4+ messages in thread
From: Dominik Brodowski @ 2003-03-02 21:06 UTC (permalink / raw)
  To: linux-kernel, John Weber

On Sun, Mar 02, 2003 at 02:37:26PM -0500, John Weber wrote:
> Dominik Brodowski wrote:
> >This patch adds a new bus_type pcmcia_bus_type, and registers all pcmcia
> >drivers with this bus within the old register_pccard_driver()
> >function. 
> >
> >Alternatively, a new registration function "pcmcia_register_driver()"
> >(and its counterpart,  "pcmcia_unregister_driver()") can be used --
> >the pcnet_cs.c driver is converted as an example.
> >
> >This updated version fixes the compilation breakage seen with gcc-2.95.3
> >because of incompatible C99 initializers (sorry, Russell). 
> 
> I've applied this patch, and have run the kernel for a few days without 
> problems.

Thanks!

> Do you have an example driver ported to this new api?  I can help 
> convert drivers.
 
That's great. However, this depends on Linus merging my patch. And it may
well be (and I even suggest this) that he takes Russell King's pcmcia/cardbus 
patches first.

The actual changes (in this step of getting rid of cardmgr) are quite few,
the larger ones will follow later:

there's a register_pccard_driver() call and a register_pccard_driver
somewhere in the pcmcia drivers. forget the first parameter (&dev_info most
of the time), the second one becomes the .attach call, the third one the
.detach call in a 

static struct pcmcia_driver dummy_driver = {
	.drv = {
		.name	= "dummy_cs",
	},
	.attach		= dummy_attach,
	.detach		= dummy_detach,
	.owner		= THIS_MODULE,
};

Then replace the {un,}register_pccard_driver() with
pcmcia_{un,}register_driver(&dummy_driver), respectively.

A sample conversion for the drivers/net/pcmcia/pcnet_cs.c driver can be
found within the patch you replied to, btw.

	Dominik

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

* Re: [UPDATED PATCH] pcmcia: add bus_type pcmcia_bus_type, struct pcmcia_driver
  2003-03-02 21:06   ` Dominik Brodowski
@ 2003-03-02 21:18     ` Russell King
  0 siblings, 0 replies; 4+ messages in thread
From: Russell King @ 2003-03-02 21:18 UTC (permalink / raw)
  To: Dominik Brodowski; +Cc: linux-kernel, John Weber

On Sun, Mar 02, 2003 at 10:06:22PM +0100, Dominik Brodowski wrote:
> That's great. However, this depends on Linus merging my patch. And it may
> well be (and I even suggest this) that he takes Russell King's pcmcia/cardbus 
> patches first.

I doubt my patches will be affecting anything in the area of this
patch.

I'm going to try to get the stuff which doesn't touch the PCI related
code merged asap so the overall patch size is back down to something
managable.  Currently, it's extremely hairy trying to sort stuff out
into reasonably sized chunks...

-- 
Russell King (rmk@arm.linux.org.uk)                The developer of ARM Linux
             http://www.arm.linux.org.uk/personal/aboutme.html


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

end of thread, other threads:[~2003-03-02 21:08 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-03-01 21:33 [UPDATED PATCH] pcmcia: add bus_type pcmcia_bus_type, struct pcmcia_driver Dominik Brodowski
2003-03-02 19:37 ` John Weber
2003-03-02 21:06   ` Dominik Brodowski
2003-03-02 21:18     ` Russell King

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).