pcmcia: bus pcmcia_bus_type, driver_socket as interface
Subsystems (2)
RFC 1/1 pcmcia: bus pcmcia_bus_type, driver_socket as interface
Hi!
Patch #1: pcmcia-2.5.62-bus_drivers-3
These patches add a new bus_type pcmcia_bus_type, and registers all pcmcia drivers with this bus. This is still done using the "old" registration calls; but over the long term this will move -- so that the pcmcia core knows about module->owner, for example.
Patch #2: pcmcia-2.5.62-ds-1
This starts a change of "Driver Servies" to become a "interface" to pcmcia_socket-class devices. The interface_add_data call is commented out due to a driver model bug (deadlock) Patrick Mochel already knows about. Due to this, removing a driver services module or a socket won't currently work.
Dominik
drivers/pcmcia/cs.c +6 -0
@@ -2430,12 +2430,17 @@ };EXPORT_SYMBOL (pcmcia_socket_class); +struct bus_type pcmcia_bus_type = { + .name ="pcmcia" , +}; +EXPORT_SYMBOL (pcmcia_bus_type);static int __init init_pcmcia_cs (void ) {printk (KERN_INFO "%s\n" , release);printk (KERN_INFO " %s\n" , options);DEBUG (0 ,"%s\n" , version); +bus_register (&pcmcia_bus_type);devclass_register (&pcmcia_socket_class);if (do_apm)pm_register (PM_SYS_DEV ,PM_SYS_PCMCIA , handle_pm_event);
@@ -2458,6 +2463,7 @@pm_unregister_all (handle_pm_event);release_resource_db ();devclass_unregister (&pcmcia_socket_class); +bus_unregister (&pcmcia_bus_type); }subsys_initcall (init_pcmcia_cs);
drivers/pcmcia/ds.c +134 -96
315 lines not on this page · raw message
include/pcmcia/cs.h +4 -0
@@ -30,6 +30,10 @@ #ifndef _LINUX_CS_H #define _LINUX_CS_H +#include <linux/device.h> + +extern struct bus_type pcmcia_bus_type; + /* For AccessConfigurationRegister */ typedef struct conf_reg_t { u_char Function;
drivers/pcmcia/cs.c +2 -0
@@ -345,6 +345,7 @@ s->ss_entry = cls_d->ops; s->sock = i + cls_d->sock_offset; + s->s_dev = dev;/* base address = 0, map = 0 */ s->cis_mem.flags =0 ;
@@ -359,6 +360,7 @@ socket_table[j] = s;if (j == sockets) sockets++; + s->socket_table_entry = j;init_socket (s); s->ss_entry->inquire_socket (s->sock, &s->cap);#ifdef CONFIG_PROC_FS
drivers/pcmcia/cs_internal.h +5 -1
@@ -158,7 +158,11 @@#ifdef CONFIG_PROC_FS struct proc_dir_entry *proc;#endif -int use_bus_pm; +int use_bus_pm; +struct device *s_dev; +/* TBD: integrate the following contents fully into this struct */ +void *ds_info;/* ds_socket_info */ +int socket_table_entry; } socket_info_t;/* Flags in config state */
drivers/pcmcia/ds.c +240 -132
599 lines not on this page · raw message
include/pcmcia/ss.h +1 -0
@@ -152,6 +152,7 @@struct pccard_operations *ops;/* see above */ void *s_info;/* socket_info_t */ unsigned int use_bus_pm; +struct intf_data ds_intf;/* intf data for driver services */ };extern struct device_class pcmcia_socket_class;
Quoted 8 lines · Dominik Brodowski
Hi!
Patch #1: pcmcia-2.5.62-bus_drivers-3
These patches add a newbus_typepcmcia_bus_type, and registers all pcmcia drivers with this bus. This is still done using the "old" registration calls; but over the long term this will move -- so that the pcmcia core knows aboutmodule->owner, for example.
Quoted 5 lines
Patch #2: pcmcia-2.5.62-ds-1
This starts a change of "Driver Servies" to become a "interface" to pcmcia_socket-class devices. Theinterface_add_datacall is commented out due to a driver model bug (deadlock) Patrick Mochel already knows about. Due to this, removing a driver services module or a socket won't currently work.
This looks really nice! Could you post an example driver converted to use pcmcia_register_driver() and friends?
PATCH 1/1 pcmcia: pcmcia_bus and pcmcia_driver [Was: Re: [RFC] pcmcia: bus pcmcia_bus_type, driver_socket as interface]
Hi!
Quoted 7 lines · Christoph Hellwig
Quoted 6 lines · Dominik Brodowski
Patch #1: pcmcia-2.5.62-bus_drivers-3
These patches add a newbus_typepcmcia_bus_type, and registers all pcmcia drivers with this bus. This is still done using the "old" registration calls; but over the long term this will move -- so that the pcmcia core knows aboutmodule->owner, for example.
Quoted 8 lines
Quoted 5 lines
Patch #2: pcmcia-2.5.62-ds-1
This starts a change of "Driver Servies" to become a "interface" to pcmcia_socket-class devices. Theinterface_add_datacall is commented out due to a driver model bug (deadlock) Patrick Mochel already knows about. Due to this, removing a driver services module or a socket won't currently work.This looks really nice! Could you post an example driver converted to use
pcmcia_register_driver()and friends?
This patch adds a new bus_type pcmcia_bus_type, and registers all pcmcia drivers with this bus. Alternatively, new registration functions, "pcmcia_register_driver()" and "pcmcia_unregister_driver()", are offered. The pcnet_cs.c driver is converted as an example.
Please apply,
Dominik
drivers/pcmcia/ds.c +156 -102
@@ -77,19 +77,11 @@/*====================================================================*/ -typedef struct driver_info_t { -dev_info_t dev_info; -int use_count, status; -dev_link_t *(*attach)(void ); -void (*detach)(dev_link_t *); -struct driver_info_t *next; -}driver_info_t ; -typedef struct socket_bind_t { -driver_info_t *driver; -u_char function; -dev_link_t *instance; -struct socket_bind_t *next; +struct pcmcia_driver *driver; +u_char function; +dev_link_t *instance; +struct socket_bind_t *next; }socket_bind_t ;/* Device user information */
@@ -124,9 +116,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,6 +132,37 @@pcmcia_report_error (handle, &err); } +/* 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; + 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 ; +} + +/*====================================================================== Register_pccard_driver() and unregister_pccard_driver() are used
@@ -151,87 +171,110 @@======================================================================*/ -int register_pccard_driver (dev_info_t *dev_info, -dev_link_t *(*attach)(void ), -void (*detach)(dev_link_t *)) +int pcmcia_register_driver (struct pcmcia_driver *driver) { -driver_info_t *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 ; -if (!driver) { - driver =kmalloc (sizeof (driver_info_t),GFP_KERNEL ); -if (!driver)return -ENOMEM ; -strncpy (driver->dev_info, (char *)dev_info,DEV_NAME_LEN ); +if (!driver) +return -EINVAL ; driver->use_count =0 ; driver->status = init_status; - driver->next = root_driver; - root_driver = driver; - } + driver->drv.bus = &pcmcia_bus_type; - driver->attach = attach; - driver->detach = detach; -if (driver->use_count ==0 )return 0 ; - -/* Instantiate any already-bound devices */ -for (i =0 ; i < sockets; i++) -for (b = socket_table[i].bind; b; b = b->next) { -if (b->driver != driver)continue ; - b->instance = driver->attach (); -if (b->instance ==NULL ) -printk (KERN_NOTICE "ds: unable to create instance " -"of '%s'!\n" , driver->dev_info); +return driver_register (&driver->drv); +} +EXPORT_SYMBOL (pcmcia_register_driver); + +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 *)) +{ +struct pcmcia_driver *driver; +socket_bind_t *b; +int i; + +DEBUG (0 ,"ds: register_pccard_driver('%s')\n" , (char *)dev_info); + driver =get_pcmcia_driver (dev_info); +if (!driver) { + driver =kmalloc (sizeof (struct pcmcia_driver ),GFP_KERNEL ); +if (!driver) +return -ENOMEM ; +memset (driver,0 ,sizeof (struct pcmcia_driver )); + driver->drv.name = (char *)dev_info; +pcmcia_register_driver (driver); + } + + driver->attach = attach; + driver->detach = detach; +if (driver->use_count ==0 ) +return 0 ; -return 0 ; +/* Instantiate any already-bound devices */ +for (i =0 ; i < sockets; i++) +for (b = socket_table[i].bind; b; b = b->next) { +if (b->driver != driver) +continue ; + b->instance = driver->attach (); +if (b->instance ==NULL ) +printk (KERN_NOTICE "ds: unable to create instance " +"of '%s'!\n" , driver->drv.name); + } + +return 0 ; }/* register_pccard_driver */ /*====================================================================*/ int unregister_pccard_driver (dev_info_t *dev_info) { -driver_info_t *target, **d = &root_driver; -socket_bind_t *b; -int i; - -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 ) -return -ENODEV ; +struct pcmcia_driver *driver; - 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 ; - } -return 0 ; +DEBUG (0 ,"ds: unregister_pccard_driver('%s')\n" , + (char *)dev_info); + driver =get_pcmcia_driver (dev_info); +if (!driver) +return -ENODEV ; + +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); +bus_for_each_drv (&pcmcia_bus_type,NULL , (void *) &p, proc_read_drivers_callback);return (p - buf); }#endif
@@ -376,7 +419,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 +427,15 @@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 ); -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; + driver =kmalloc (sizeof (struct pcmcia_driver ),GFP_KERNEL ); +if (!driver) +return -ENOMEM ; +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 +449,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 +530,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 +564,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 +576,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,6 +913,17 @@/*====================================================================*/ +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 ; +} +int __init init_pcmcia_ds (void ) {client_reg_t client_reg;
@@ -967,11 +1010,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 +1023,21 @@pcmcia_deregister_client (socket_table[i].handle); sockets =0 ;kfree (socket_table); +bus_unregister (&pcmcia_bus_type); } +#ifdef MODULE + +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);
drivers/net/pcmcia/pcnet_cs.c +9 -2
@@ -1617,6 +1617,13 @@/*====================================================================*/ +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 +1634,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); }
include/pcmcia/ds.h +16 -0
@@ -143,6 +143,22 @@#define register_pcmcia_driver register_pccard_driver#define unregister_pcmcia_driver unregister_pccard_driver +#include <linux/device.h> + +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 */
PATCH 1/1 pcmcia: driver_socket as device_class interface [Was: Re: [RFC] pcmcia: bus pcmcia_bus_type, driver_socket as interface]
In reply to Christoph HellwigQuoted 11 lines · Christoph Hellwig
Quoted 7 lines · Dominik Brodowski
...
Patch #2: pcmcia-2.5.62-ds-1
This starts a change of "Driver Servies" to become a "interface" to pcmcia_socket-class devices. Theinterface_add_datacall is commented out due to a driver model bug (deadlock) Patrick Mochel already knows about. Due to this, removing a driver services module or a socket won't currently work.This looks really nice! Could you post an example driver converted to use
pcmcia_register_driver()and friends?
This is the 2nd patch -- "Driver Servies" will probably become the "bus driver" for PCMCIA (non-CardBus) cards. So register it as an interface to the device class pcmcia_socket_class. Unfortunately, due to a driver model bug the actual interface_add_data call is commented out. This only means that unloading pcmcia sockets won't currently work, loading/enabling pcmcia sockets should work fine (and does so here).
Dominik
drivers/pcmcia/cs.c +2 -0
@@ -345,6 +345,7 @@ s->ss_entry = cls_d->ops; s->sock = i + cls_d->sock_offset; + s->s_dev = dev;/* base address = 0, map = 0 */ s->cis_mem.flags =0 ;
@@ -359,6 +360,7 @@ socket_table[j] = s;if (j == sockets) sockets++; + s->socket_table_entry = j;init_socket (s); s->ss_entry->inquire_socket (s->sock, &s->cap);#ifdef CONFIG_PROC_FS
drivers/pcmcia/cs_internal.h +5 -1
@@ -158,7 +158,11 @@#ifdef CONFIG_PROC_FS struct proc_dir_entry *proc;#endif -int use_bus_pm; +int use_bus_pm; +struct device *s_dev; +/* TBD: integrate the following contents fully into this struct */ +void *ds_info;/* ds_socket_info */ +int socket_table_entry; } socket_info_t;/* Flags in config state */
drivers/pcmcia/ds.c +246 -135
608 lines not on this page · raw message
include/pcmcia/ss.h +1 -0
@@ -152,6 +152,7 @@struct pccard_operations *ops;/* see above */ void *s_info;/* socket_info_t */ unsigned int use_bus_pm; +struct intf_data ds_intf;/* intf data for driver services */ };extern struct device_class pcmcia_socket_class;