[patches 5/12] pcmcia: mark resource setup as done
Dominik Brodowski
linux at dominikbrodowski.net
Thu Feb 10 14:47:31 EST 2005
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 at dominikbrodowski.net>
---
drivers/pcmcia/cs.c | 3 ++-
drivers/pcmcia/rsrc_mgr.c | 41 ++++++++++++++++++++++++++++++++++++++++-
drivers/pcmcia/socket_sysfs.c | 30 ++++++++++++++++++++++++++++++
include/pcmcia/ss.h | 11 +++++++++++
4 files changed, 83 insertions(+), 2 deletions(-)
Index: 2.6.11-rc3+/drivers/pcmcia/cs.c
===================================================================
--- 2.6.11-rc3+.orig/drivers/pcmcia/cs.c 2005-02-09 21:47:36.000000000 +0100
+++ 2.6.11-rc3+/drivers/pcmcia/cs.c 2005-02-10 20:14:06.000000000 +0100
@@ -221,6 +221,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)
@@ -261,7 +263,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);
Index: 2.6.11-rc3+/drivers/pcmcia/rsrc_mgr.c
===================================================================
--- 2.6.11-rc3+.orig/drivers/pcmcia/rsrc_mgr.c 2005-02-09 21:47:36.000000000 +0100
+++ 2.6.11-rc3+/drivers/pcmcia/rsrc_mgr.c 2005-02-10 20:14:06.000000000 +0100
@@ -59,6 +59,7 @@
{
struct pcmcia_socket *s;
int ret = CS_UNSUPPORTED_FUNCTION;
+ unsigned long flags;
down_read(&pcmcia_socket_list_rwsem);
list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
@@ -66,8 +67,30 @@
if (adj->Resource == RES_IRQ)
ret = adjust_irq(s, adj);
- else if (s->resource_ops->adjust_resource)
+ else if (s->resource_ops->adjust_resource) {
+
+ /* you can't use the old interface if the new
+ * one was used before */
+ spin_lock_irqsave(&s->lock, flags);
+ if ((s->resource_setup_done) &&
+ !(s->resource_setup_old)) {
+ spin_unlock_irqrestore(&s->lock, flags);
+ continue;
+ } else if (!(s->resource_setup_old))
+ s->resource_setup_old = 1;
+ spin_unlock_irqrestore(&s->lock, flags);
+
ret = s->resource_ops->adjust_resource(s, adj);
+ if (!ret) {
+ /* 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... */
+ spin_lock_irqsave(&s->lock, flags);
+ s->resource_setup_done = 1;
+ spin_unlock_irqrestore(&s->lock, flags);
+ }
+ }
}
up_read(&pcmcia_socket_list_rwsem);
@@ -113,12 +136,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);
Index: 2.6.11-rc3+/drivers/pcmcia/socket_sysfs.c
===================================================================
--- 2.6.11-rc3+.orig/drivers/pcmcia/socket_sysfs.c 2005-02-09 21:47:36.000000000 +0100
+++ 2.6.11-rc3+/drivers/pcmcia/socket_sysfs.c 2005-02-10 20:14:06.000000000 +0100
@@ -148,6 +148,35 @@
static CLASS_DEVICE_ATTR(card_irq_mask, 0600, pccard_show_irq_mask, pccard_store_irq_mask);
+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 ? "yes" : "no");
+}
+
+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 */
+ return count;
+ }
+ spin_unlock_irqrestore(&s->lock, flags);
+
+ return count;
+}
+static CLASS_DEVICE_ATTR(available_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,
@@ -156,6 +185,7 @@
&class_device_attr_card_insert,
&class_device_attr_card_eject,
&class_device_attr_card_irq_mask,
+ &class_device_attr_available_resources_setup_done,
NULL,
};
Index: 2.6.11-rc3+/include/pcmcia/ss.h
===================================================================
--- 2.6.11-rc3+.orig/include/pcmcia/ss.h 2005-02-09 21:47:44.000000000 +0100
+++ 2.6.11-rc3+/include/pcmcia/ss.h 2005-02-10 20:14:06.000000000 +0100
@@ -203,6 +203,17 @@
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:6;
+
/* socket operations */
struct pccard_operations * ops;
struct pccard_resource_ops * resource_ops;
More information about the linux-pcmcia
mailing list