From: Dominik Brodowski Use a struct pcmcia_device-based approach to inform "clients" of events. It needs to be done using bus_for_each_device() so that we don't need to take the device_list spinlock. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton --- 25-akpm/drivers/pcmcia/cs.c | 5 ++-- 25-akpm/drivers/pcmcia/ds.c | 47 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 12 deletions(-) diff -puN drivers/pcmcia/cs.c~pcmcia-use-pcmcia_device-in-send_event drivers/pcmcia/cs.c --- 25/drivers/pcmcia/cs.c~pcmcia-use-pcmcia_device-in-send_event Mon Dec 13 14:38:52 2004 +++ 25-akpm/drivers/pcmcia/cs.c Mon Dec 13 14:38:52 2004 @@ -399,8 +399,9 @@ static void shutdown_socket(struct pcmci /*====================================================================== - The central event handler. Send_event() sends an event to all - valid clients. Parse_events() interprets the event bits from + The central event handler. Send_event() sends an event to the + 16-bit subsystem, which then calls the relevant device drivers. + Parse_events() interprets the event bits from a card status change report. Do_shutdown() handles the high priority stuff associated with a card removal. diff -puN drivers/pcmcia/ds.c~pcmcia-use-pcmcia_device-in-send_event drivers/pcmcia/ds.c --- 25/drivers/pcmcia/ds.c~pcmcia-use-pcmcia_device-in-send_event Mon Dec 13 14:38:52 2004 +++ 25-akpm/drivers/pcmcia/ds.c Mon Dec 13 14:38:52 2004 @@ -537,20 +537,47 @@ static int handle_request(struct pcmcia_ ======================================================================*/ +struct send_event_data { + struct pcmcia_socket *skt; + event_t event; + int priority; +}; + +static int send_event_callback(struct device *dev, void * _data) +{ + struct pcmcia_device *p_dev = to_pcmcia_dev(dev); + struct send_event_data *data = _data; + + /* we get called for all sockets, but may only pass the event + * for drivers _on the affected socket_ */ + if (p_dev->socket != data->skt) + return 0; + + if (p_dev->client->state & (CLIENT_UNBOUND|CLIENT_STALE)) + return 0; + + if (p_dev->client->EventMask & data->event) + return EVENT(p_dev->client, data->event, data->priority); + + return 0; +} + static int send_event(struct pcmcia_socket *s, event_t event, int priority) { int ret = 0; - client_t *client; + struct send_event_data private; + struct pcmcia_bus_socket *skt = pcmcia_get_bus_socket(s->pcmcia); + + if (!skt) + return 0; + + private.skt = s; + private.event = event; + private.priority = priority; + + ret = bus_for_each_dev(&pcmcia_bus_type, NULL, &private, send_event_callback); - for (client = s->clients; client; client = client->next) { - if (client->state & (CLIENT_UNBOUND|CLIENT_STALE)) - continue; - if (client->EventMask & event) { - ret = EVENT(client, event, priority); - if (ret != 0) - return ret; - } - } + pcmcia_put_bus_socket(skt); return ret; } /* send_event */ _