PCMCIA device registration should only happen if we're quite confident
there are resources available to at least map the CIS space -- else we can't
determine manfid/cardid, whether it is a multifunction card, etc. So,
add a flag to struct pcmcia_socket which denotes that -- and also whether
resources were added the "old" adjust_resource_info way. On static sockets,
it is activated upon registration, on non-static sockets, it is set upon an
echo'ing of anything into 
/sys/class/pcmcia_socket/pcmcia_socket%n/device_possible_resources_setup_done

Signed-off-by: Dominik Brodowski <linux@brodo.de>

 drivers/pcmcia/cs.c           |    3 ++-
 drivers/pcmcia/rsrc_mgr.c     |   28 ++++++++++++++++++++++++++++
 drivers/pcmcia/socket_sysfs.c |   30 ++++++++++++++++++++++++++++++
 include/pcmcia/ss.h           |   13 +++++++++++++
 4 files changed, 73 insertions(+), 1 deletion(-)

diff -ruN linux-original/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c
--- linux-original/drivers/pcmcia/cs.c	2004-11-09 23:31:23.553568376 +0100
+++ linux/drivers/pcmcia/cs.c	2004-11-09 23:32:26.869942824 +0100
@@ -217,6 +217,8 @@
 
 	cs_dbg(socket, 0, "pcmcia_register_socket(0x%p)\n", socket->ops);
 
+	spin_lock_init(&socket->lock);
+
 	if (socket->resource_ops->init) {
 		ret = socket->resource_ops->init(socket);
 		if (ret)
@@ -257,7 +259,6 @@
 	socket->cis_mem.speed = cis_speed;
 
 	INIT_LIST_HEAD(&socket->cis_cache);
-	spin_lock_init(&socket->lock);
 
 	init_completion(&socket->socket_released);
 	init_completion(&socket->thread_done);
diff -ruN linux-original/drivers/pcmcia/rsrc_mgr.c linux/drivers/pcmcia/rsrc_mgr.c
--- linux-original/drivers/pcmcia/rsrc_mgr.c	2004-11-09 23:30:43.732622080 +0100
+++ linux/drivers/pcmcia/rsrc_mgr.c	2004-11-09 23:30:24.044615112 +0100
@@ -240,6 +240,18 @@
 	}
 	up_read(&pcmcia_socket_list_rwsem);
 
+	/* as there's no way we know this is the last call to 
+	 * adjust_resource_info, we always need to assume this is the latest
+	 * one... */
+	if (ret != CS_UNSUPPORTED_FUNCTION) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&s->lock, flags);
+		s->resource_setup_old = 1;
+		s->resource_setup_done = 1;
+		spin_unlock_irqrestore(&s->lock, flags);
+	}
+	
 	return (ret);
 }
 EXPORT_SYMBOL(pcmcia_adjust_resource_info);
@@ -282,12 +294,28 @@
 }
 
 
+static int static_init(struct pcmcia_socket *s)
+{
+	unsigned long flags;
+
+	/* the good thing about SS_CAP_STATIC_MAP sockets is
+	 * that they don't need a resource database */
+
+	spin_lock_irqsave(&s->lock, flags);
+	s->resource_setup_done = 1;
+	spin_unlock_irqrestore(&s->lock, flags);
+
+	return 0;
+}
+
+
 struct pccard_resource_ops pccard_static_ops = {
 	.validate_mem = NULL,
 	.adjust_io_region = NULL,
 	.find_io = NULL,
 	.find_mem = NULL,
 	.adjust_resource = NULL,
+	.init = static_init,
 	.exit = NULL,
 };
 EXPORT_SYMBOL(pccard_static_ops);
diff -ruN linux-original/drivers/pcmcia/socket_sysfs.c linux/drivers/pcmcia/socket_sysfs.c
--- linux-original/drivers/pcmcia/socket_sysfs.c	2004-11-09 23:30:43.733621928 +0100
+++ linux/drivers/pcmcia/socket_sysfs.c	2004-11-09 23:30:24.045614960 +0100
@@ -122,6 +122,35 @@
 static CLASS_DEVICE_ATTR(card_eject, 0200, NULL, pccard_store_eject);
 
 
+static ssize_t pccard_show_resource(struct class_device *dev, char *buf)
+{
+	struct pcmcia_socket *s = to_socket(dev);
+	return sprintf(buf, "%s\n", s->resource_setup_done ? "no" : "yes");
+}
+
+static ssize_t pccard_store_resource(struct class_device *dev, const char *buf, size_t count)
+{
+	unsigned long flags;
+	struct pcmcia_socket *s = to_socket(dev);
+
+	if (!count)
+		return -EINVAL;
+
+	spin_lock_irqsave(&s->lock, flags);
+	if (!s->resource_setup_done) {
+		s->resource_setup_done = 1;
+		spin_unlock_irqrestore(&s->lock, flags);
+
+		/* later on, a call which starts PCMCIA device registration
+		 * will be added here */
+	}
+	spin_unlock_irqrestore(&s->lock, flags);
+
+	return count;
+}
+static CLASS_DEVICE_ATTR(device_possible_resources_setup_done, 0600, pccard_show_resource, pccard_store_resource);
+
+
 static struct class_device_attribute *pccard_socket_attributes[] = {
 	&class_device_attr_card_type,
 	&class_device_attr_card_voltage,
@@ -129,6 +158,7 @@
 	&class_device_attr_card_vcc,
 	&class_device_attr_card_insert,
 	&class_device_attr_card_eject,
+	&class_device_attr_device_possible_resources_setup_done,
 	NULL,
 };
 
diff -ruN linux-original/include/pcmcia/ss.h linux/include/pcmcia/ss.h
--- linux-original/include/pcmcia/ss.h	2004-11-09 23:31:23.555568072 +0100
+++ linux/include/pcmcia/ss.h	2004-11-09 23:30:24.045614960 +0100
@@ -164,6 +164,7 @@
 /* Maximum number of memory windows per socket */
 #define MAX_WIN 4
 
+
 struct config_t;
 struct region_t;
 struct pcmcia_callback;
@@ -205,6 +206,18 @@
 	u_char				pci_irq;
 	struct pci_dev *		cb_dev;
 
+
+	/* socket setup is done so resources should be able to be allocated. Only
+	 * if set to 1, calls to find_{io,mem}_region are handled, and insertion
+	 * events are actually managed by the PCMCIA layer.*/
+	u8				resource_setup_done:1;
+
+	/* is set to one if resource setup is done using adjust_resource_info() */
+	u8				resource_setup_old:1;
+
+	u8				reserved:7;
+								  
+
 	/* socket operations */
 	struct pccard_operations *	ops;
 	struct pccard_resource_ops *	resource_ops;