
From: Dominik Brodowski <linux@dominikbrodowski.de>

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 <linux@brodo.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 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	2004-12-03 18:44:38.110989448 -0800
+++ 25-akpm/drivers/pcmcia/cs.c	2004-12-03 18:44:38.117988384 -0800
@@ -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	2004-12-03 18:44:38.112989144 -0800
+++ 25-akpm/drivers/pcmcia/ds.c	2004-12-03 18:44:38.119988080 -0800
@@ -533,20 +533,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);
 
-	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;
-		}
-	}
+	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);
+
+	pcmcia_put_bus_socket(skt);
 	return ret;
 } /* send_event */
 
_
