ChangeSet 1.2065.3.14, 2005/03/12 08:24:26-08:00, [EMAIL PROTECTED]
[PATCH] pcmcia: mark resource setup as done
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 <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
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(-)
diff -Nru a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
--- a/drivers/pcmcia/cs.c 2005-03-12 21:27:27 -08:00
+++ b/drivers/pcmcia/cs.c 2005-03-12 21:27:27 -08:00
@@ -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);
diff -Nru a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
--- a/drivers/pcmcia/rsrc_mgr.c 2005-03-12 21:27:27 -08:00
+++ b/drivers/pcmcia/rsrc_mgr.c 2005-03-12 21:27:27 -08:00
@@ -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);
diff -Nru a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
--- a/drivers/pcmcia/socket_sysfs.c 2005-03-12 21:27:27 -08:00
+++ b/drivers/pcmcia/socket_sysfs.c 2005-03-12 21:27:27 -08:00
@@ -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,
};
diff -Nru a/include/pcmcia/ss.h b/include/pcmcia/ss.h
--- a/include/pcmcia/ss.h 2005-03-12 21:27:27 -08:00
+++ b/include/pcmcia/ss.h 2005-03-12 21:27:27 -08:00
@@ -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;
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html