[RFC] what to do next
Dominik Brodowski
linux at brodo.de
Fri Oct 3 00:50:33 BST 2003
Once the previous patchset consisting of these patches:
http://www.brodo.de/patches/2003-10-02/pcmcia-2.6.0-test6+-change-ds-license
http://www.brodo.de/patches/2003-10-02/pcmcia-2.6.0-test6+-pcmcia_device
http://www.brodo.de/patches/2003-10-02/pcmcia-2.6.0-test6+-remove_socket_bind_t
http://www.brodo.de/patches/2003-10-02/pcmcia-2.6.0-test6+-remove_internal_driver_use_count
is merged into the 2.6.-test kernel, I'd like to do the following changes:
http://www.brodo.de/patches/2003-10-02/pcmcia-2.6.0-test6+-attach_parameter
Add the corresponding "struct pcmcia_device" as argument to the
->attach() call. Update all drivers to do so.
[due to the size of this patch it is only available online]
http://www.brodo.de/patches/2003-10-02/pcmcia-2.6.0-test6+-new_driver_callbacks_core
Add new callbacks for PCMCIA drivers:
->probe(): called instead of the CS_EVENT_CARD_INSERTION
call. As a driver can only call
pcmcia_register_client once a corresponding
PCMCIA card had been inserted into a socket,
the CARD_INSERTION event is generated upon all
current calls to pcmcia_register_client. So it can
be put to after the ->attach() call as well.
->remove(): called when CS_EVENT_CARD_REMOVAL would have
been called.
->suspend(): called when CS_EVENT_PM_SUSPEND would have been
called. [Note: should be integrated into the PM
core soon].
->resume(): called when CS_EVENT_PM_RESUME would have been
called. [Note: should be integrated into the PM
core soon].
->pre_reset(): called when CS_EVENT_CARD_RESET would have been
called.
->post_reset(): called when CS_EVENT_RESET_PHYSICAL would have
been called.
->probe() and ->attach() will be merged into one function, same with
->remove() and ->detach(). And maybe pre_reset() and suspend(), and
post_reset() and resume() can be merged as well, as only very few
drivers do something different on suspension...
http://www.brodo.de/patches/2003-10-02/pcmcia-2.6.0-test6+-update_pcnet_cs_driver_as_example
Update the pcnet_cs driver to reflect the core changes as an example.
http://www.brodo.de/patches/2003-10-02/pcmcia-2.6.0-test6+-move_suspend_and_reset_to_callbacks_all
Move the suspend, resume, reset and reset_physical to the corresponding
callbacks for all in-kernel pcmcia drivers.
[due to the size of this patch it is only available online]
After this next step is done, the event callbacks should be removed
completely from the remaining in-kernel pcmcia drivers. Then, I intend to
move some PCMCIA-related code from ds.c and cs.c into a new
drivers/pcmcia/pcmcia.c, which is then linked into pcmcia_core.ko. Then both
bind_req_t and client_t can be merged into struct pcmcia_device, with
client_handle_t becoming a pointer to struct pcmcia_device *p_dev.
Dominik
-------------- next part --------------
Add new callbacks for PCMCIA drivers:
->probe(): called instead of the CS_EVENT_CARD_INSERTION
call. As a driver can only call
pcmcia_register_client once a corresponding
PCMCIA card had been inserted into a socket,
the CARD_INSERTION event is generated upon all
current calls to pcmcia_register_client. So it can
be put to after the ->attach() call as well.
->remove(): called when CS_EVENT_CARD_REMOVAL would have
been called.
->suspend(): called when CS_EVENT_PM_SUSPEND would have been
called. [Note: should be integrated into the PM
core soon].
->resume(): called when CS_EVENT_PM_RESUME would have been
called. [Note: should be integrated into the PM
core soon].
->pre_reset(): called when CS_EVENT_CARD_RESET would have been
called.
->post_reset(): called when CS_EVENT_RESET_PHYSICAL would have
been called.
->probe() and ->attach() will be merged into one function, same with
->remove() and ->detach(). And maybe pre_reset() and suspend(), and
post_reset() and resume() can be merged as well, as only very few
drivers do something different on suspension...
diff -ruN linux-original/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c
--- linux-original/drivers/pcmcia/ds.c 2003-10-02 23:19:14.717279728 +0200
+++ linux/drivers/pcmcia/ds.c 2003-10-02 23:21:12.561364704 +0200
@@ -246,6 +246,69 @@
======================================================================*/
+static void ds_call_driver_callbacks(struct pcmcia_bus_socket *s,
+ event_t event)
+{
+ struct pcmcia_device *p_dev, *tmp;
+ struct pcmcia_driver *p_drv;
+
+ /* TBD: properly assure that events are serialized, or at least
+ * safe against driver and device removal. This will be done once
+ * ds and cs are a) integrated and b) split up into core [pccard.ko],
+ * cardbus.ko and pcmcia.ko
+ */
+ list_for_each_entry_safe(p_dev, tmp, &s->devices_list, socket_device_list) {
+ struct device *dev;
+ struct device_driver *drv;
+
+ dev = get_device(&p_dev->dev);
+ if (!dev)
+ continue;
+ p_dev = to_pcmcia_dev(dev);
+
+ drv = get_driver(dev->driver);
+ if (!drv) {
+ put_device(dev);
+ continue;
+ }
+ p_drv = to_pcmcia_drv(drv);
+
+ switch(event) {
+ case CS_EVENT_CARD_INSERTION:
+ printk(KERN_DEBUG "stale CARD_INSERTION event detected. Please inform <linux at brodo.de>\n");
+ printk(KERN_DEBUG "of what you did just now with your PCMCIA card. Thanks.\n");
+ break;
+
+ case CS_EVENT_CARD_REMOVAL:
+ if (p_drv->remove)
+ p_drv->remove(p_dev);
+
+ case CS_EVENT_RESET_PHYSICAL:
+ if (p_drv->pre_reset)
+ p_drv->pre_reset(p_dev);
+ break;
+
+ case CS_EVENT_CARD_RESET:
+ if (p_drv->post_reset)
+ p_drv->post_reset(p_dev);
+ break;
+
+ case CS_EVENT_PM_SUSPEND:
+ if (p_drv->suspend)
+ p_drv->suspend(p_dev);
+ break;
+
+ case CS_EVENT_PM_RESUME:
+ if (p_drv->resume)
+ p_drv->resume(p_dev);
+ break;
+ }
+
+ put_driver(drv);
+ put_device(dev);
+ }
+}
+
static int ds_event(event_t event, int priority,
event_callback_args_t *args)
{
@@ -253,8 +316,16 @@
DEBUG(1, "ds: ds_event(0x%06x, %d, 0x%p)\n",
event, priority, args->client_handle);
+
s = args->client_data;
+ /* The CS core used a single linked list for the event queue,
+ which assured that the later a "client" is register, the
+ earlier it is informed of events. So call the drivers first,
+ and do our stuff later.
+ */
+ ds_call_driver_callbacks(s, event);
+
switch (event) {
case CS_EVENT_CARD_REMOVAL:
@@ -404,8 +475,14 @@
}
}
- return 0;
+ /* and now call the real "probe" function ... */
+ if (p_drv->probe) {
+ ret = p_drv->probe(p_dev);
+ if (ret)
+ goto err_unreg;
+ }
+ return 0;
err_unreg:
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
diff -ruN linux-original/include/pcmcia/ds.h linux/include/pcmcia/ds.h
--- linux-original/include/pcmcia/ds.h 2003-10-02 23:19:14.722278968 +0200
+++ linux/include/pcmcia/ds.h 2003-10-02 23:21:06.931220616 +0200
@@ -134,10 +134,20 @@
struct pcmcia_device;
struct pcmcia_driver {
- dev_link_t *(*attach)(struct pcmcia_device *);
- void (*detach)(dev_link_t *);
struct module *owner;
struct device_driver drv;
+
+ dev_link_t *(*attach) (struct pcmcia_device *);
+ void (*detach) (dev_link_t *);
+
+ int (*probe) (struct pcmcia_device *);
+ int (*remove) (struct pcmcia_device *);
+
+ int (*suspend) (struct pcmcia_device *);
+ int (*resume) (struct pcmcia_device *);
+
+ int (*pre_reset) (struct pcmcia_device *);
+ int (*post_reset) (struct pcmcia_device *);
};
/* driver registration */
-------------- next part --------------
Update the pcnet_cs driver to reflect the core changes as an example.
pcnet_cs.c | 117 ++++++++++++++++++++++++++++++++++++++++---------------------
1 files changed, 77 insertions(+), 40 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-10-02 23:19:14.701282160 +0200
+++ linux/drivers/net/pcmcia/pcnet_cs.c 2003-10-02 23:25:14.765544072 +0200
@@ -297,10 +297,7 @@
dev_list = link;
client_reg.dev_info = &dev_info;
client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
- client_reg.EventMask =
- CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
- CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
- CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+ client_reg.EventMask = 0;
client_reg.event_handler = &pcnet_event;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
@@ -814,53 +811,82 @@
======================================================================*/
-static int pcnet_event(event_t event, int priority,
- event_callback_args_t *args)
+static int pcnet_pre_reset(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
- pcnet_dev_t *info = link->priv;
+ dev_link_t *link = p_dev->instance;
+ pcnet_dev_t *info = link->priv;
+ if (link->state & DEV_CONFIG) {
+ if (link->open)
+ netif_device_detach(&info->dev);
+ CardServices(ReleaseConfiguration, link->handle);
+ }
+ return 0;
+}
- DEBUG(2, "pcnet_event(0x%06x)\n", event);
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
+static int pcnet_post_reset(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = p_dev->instance;
+ pcnet_dev_t *info = link->priv;
if (link->state & DEV_CONFIG) {
- netif_device_detach(&info->dev);
- pcnet_release(link);
+ CardServices(RequestConfiguration, link->handle, &link->conf);
+ if (link->open) {
+ pcnet_reset_8390(&info->dev);
+ NS8390_init(&info->dev, 1);
+ netif_device_attach(&info->dev);
+ }
}
- break;
- case CS_EVENT_CARD_INSERTION:
+ return 0;
+}
+
+
+static int pcnet_suspend(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = p_dev->instance;
+ link->state |= DEV_SUSPEND;
+ return pcnet_pre_reset(p_dev);
+}
+
+
+static int pcnet_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = p_dev->instance;
+ link->state &= ~DEV_SUSPEND;
+ return pcnet_post_reset(p_dev);
+}
+
+
+static int pcnet_probe(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = p_dev->instance;
+
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
pcnet_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
+ return 0;
+}
+
+
+static int pcnet_remove(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = p_dev->instance;
+ pcnet_dev_t *info = link->priv;
+
+ link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
- if (link->open)
netif_device_detach(&info->dev);
- CardServices(ReleaseConfiguration, link->handle);
- }
- break;
- case CS_EVENT_PM_RESUME:
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- if (link->state & DEV_CONFIG) {
- CardServices(RequestConfiguration, link->handle, &link->conf);
- if (link->open) {
- pcnet_reset_8390(&info->dev);
- NS8390_init(&info->dev, 1);
- netif_device_attach(&info->dev);
- }
+ pcnet_release(link);
}
- break;
- }
- return 0;
+ return 0;
+}
+
+
+static int pcnet_event(event_t event, int priority,
+ event_callback_args_t *args)
+{
+ return 0;
} /* pcnet_event */
+
/*======================================================================
MII interface support for DL10019 and DL10022 based cards
@@ -1566,12 +1592,23 @@
/*====================================================================*/
static struct pcmcia_driver pcnet_driver = {
+ .owner = THIS_MODULE,
+
.drv = {
.name = "pcnet_cs",
},
+
.attach = pcnet_attach,
.detach = pcnet_detach,
- .owner = THIS_MODULE,
+
+ .probe = pcnet_probe,
+ .remove = pcnet_remove,
+
+ .pre_reset = pcnet_pre_reset,
+ .post_reset = pcnet_post_reset,
+
+ .suspend = pcnet_suspend,
+ .resume = pcnet_resume,
};
static int __init init_pcnet_cs(void)
More information about the linux-pcmcia
mailing list