[patch 11/21] pcmcia: per-socket resource database
Dominik Brodowski
linux at dominikbrodowski.de
Fri Dec 17 05:08:46 EST 2004
Make the io and mem db per-socket, as different sockets may have different
requirements or may not even need the resource db at all (SS_CAP_STATIC_MAP).
Updated to make rsrc_mem_probe per-socket and to remove unnecessary and even
broken check for empty list as per Russell King's suggestions.
Signed-off-by: Dominik Brodowski <linux at brodo.de>
---
drivers/pcmcia/cs.c | 6 ++
drivers/pcmcia/cs_internal.h | 2
drivers/pcmcia/rsrc_mgr.c | 99 ++++++++++++++++++++-----------------------
include/pcmcia/ss.h | 10 ++++
4 files changed, 63 insertions(+), 54 deletions(-)
Index: 2.6.10-rc3/drivers/pcmcia/cs.c
===================================================================
--- 2.6.10-rc3.orig/drivers/pcmcia/cs.c 2004-12-05 10:26:06.529611552 +0100
+++ 2.6.10-rc3/drivers/pcmcia/cs.c 2004-12-05 10:26:06.911553488 +0100
@@ -250,6 +250,10 @@
socket->cis_mem.flags = 0;
socket->cis_mem.speed = cis_speed;
+ /* init resource database */
+ socket->mem_db.next = &socket->mem_db;
+ socket->io_db.next = &socket->io_db;
+
INIT_LIST_HEAD(&socket->cis_cache);
spin_lock_init(&socket->lock);
@@ -305,6 +309,7 @@
up_write(&pcmcia_socket_list_rwsem);
/* wait for sysfs to drop all references */
+ release_resource_db(socket);
wait_for_completion(&socket->socket_released);
} /* pcmcia_unregister_socket */
EXPORT_SYMBOL(pcmcia_unregister_socket);
@@ -1879,7 +1884,6 @@
static void __exit exit_pcmcia_cs(void)
{
printk(KERN_INFO "unloading Kernel Card Services\n");
- release_resource_db();
class_interface_unregister(&pccard_sysfs_interface);
class_unregister(&pcmcia_socket_class);
}
Index: 2.6.10-rc3/drivers/pcmcia/cs_internal.h
===================================================================
--- 2.6.10-rc3.orig/drivers/pcmcia/cs_internal.h 2004-12-05 10:26:06.319643472 +0100
+++ 2.6.10-rc3/drivers/pcmcia/cs_internal.h 2004-12-05 10:26:06.912553336 +0100
@@ -143,7 +143,7 @@
int try_irq(u_int Attributes, int irq, int specific);
void undo_irq(u_int Attributes, int irq);
int adjust_resource_info(client_handle_t handle, adjust_t *adj);
-void release_resource_db(void);
+void release_resource_db(struct pcmcia_socket *s);
/* In socket_sysfs.c */
extern struct class_interface pccard_sysfs_interface;
Index: 2.6.10-rc3/drivers/pcmcia/rsrc_mgr.c
===================================================================
--- 2.6.10-rc3.orig/drivers/pcmcia/rsrc_mgr.c 2004-12-05 10:26:06.320643320 +0100
+++ 2.6.10-rc3/drivers/pcmcia/rsrc_mgr.c 2004-12-05 10:26:06.913553184 +0100
@@ -53,23 +53,10 @@
======================================================================*/
-typedef struct resource_map_t {
- u_long base, num;
- struct resource_map_t *next;
-} resource_map_t;
-
-/* Memory resource database */
-static resource_map_t mem_db = {
- .next = &mem_db,
-};
-
-/* IO port resource database */
-static resource_map_t io_db = {
- .next = &io_db,
-};
+typedef struct resource_map_t resource_map_t;
static DECLARE_MUTEX(rsrc_sem);
-static unsigned int rsrc_mem_probe;
+
#define MEM_PROBE_LOW (1 << 0)
#define MEM_PROBE_HIGH (1 << 1)
@@ -208,7 +195,7 @@
======================================================================*/
#ifdef CONFIG_PCMCIA_PROBE
-static void do_io_probe(ioaddr_t base, ioaddr_t num)
+static void do_io_probe(struct pcmcia_socket *s, ioaddr_t base, ioaddr_t num)
{
struct resource *res;
ioaddr_t i, j, bad, any;
@@ -253,7 +240,7 @@
bad = any = i;
} else {
if (bad) {
- sub_interval(&io_db, bad, i-bad);
+ sub_interval(&s->io_db, bad, i-bad);
printk(" %#04x-%#04x", bad, i-1);
bad = 0;
}
@@ -264,7 +251,7 @@
printk(" nothing: probe failed.\n");
return;
} else {
- sub_interval(&io_db, bad, i-bad);
+ sub_interval(&s->io_db, bad, i-bad);
printk(" %#04x-%#04x", bad, i-1);
}
}
@@ -409,7 +396,7 @@
if (i != j) {
if (!bad) printk(" excluding");
printk(" %#05lx-%#05lx", i, j-1);
- sub_interval(&mem_db, i, j-i);
+ sub_interval(&s->mem_db, i, j-i);
bad += j-i;
}
}
@@ -422,12 +409,12 @@
static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s)
{
u_long ok;
- if (m == &mem_db)
+ if (m == &s->mem_db)
return 0;
ok = inv_probe(m->next, s);
if (ok) {
if (m->base >= 0x100000)
- sub_interval(&mem_db, m->base, m->num);
+ sub_interval(&s->mem_db, m->base, m->num);
return ok;
}
if (m->base < 0x100000)
@@ -443,14 +430,14 @@
/* We do up to four passes through the list */
if (probe_mask & MEM_PROBE_HIGH) {
- if (inv_probe(mem_db.next, s) > 0)
+ if (inv_probe(s->mem_db.next, s) > 0)
return;
printk(KERN_NOTICE "cs: warning: no high memory space "
"available!\n");
}
if ((probe_mask & MEM_PROBE_LOW) == 0)
return;
- for (m = mem_db.next; m != &mem_db; m = mm.next) {
+ for (m = s->mem_db.next; m != &s->mem_db; m = mm.next) {
mm = *m;
/* Only probe < 1 MB */
if (mm.base >= 0x100000) continue;
@@ -463,7 +450,7 @@
b = order[i] << 12;
if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
if (ok >= mem_limit)
- sub_interval(&mem_db, b, 0x10000);
+ sub_interval(&s->mem_db, b, 0x10000);
else
ok += do_mem_probe(b, 0x10000, s);
}
@@ -477,7 +464,7 @@
{
resource_map_t *m, mm;
- for (m = mem_db.next; m != &mem_db; m = mm.next) {
+ for (m = s->mem_db.next; m != &s->mem_db; m = mm.next) {
mm = *m;
if (do_mem_probe(mm.base, mm.num, s))
break;
@@ -501,8 +488,8 @@
if (s->features & SS_CAP_PAGE_REGS)
probe_mask = MEM_PROBE_HIGH;
- if (probe_mask & ~rsrc_mem_probe) {
- rsrc_mem_probe |= probe_mask;
+ if (probe_mask & ~s->rsrc_mem_probe) {
+ s->rsrc_mem_probe |= probe_mask;
down(&s->skt_sem);
@@ -591,7 +578,7 @@
int ret = -ENOMEM;
down(&rsrc_sem);
- for (m = io_db.next; m != &io_db; m = m->next) {
+ for (m = s->io_db.next; m != &s->io_db; m = m->next) {
unsigned long start = m->base;
unsigned long end = m->base + m->num - 1;
@@ -632,7 +619,7 @@
data.mask = align - 1;
data.offset = base & data.mask;
- data.map = &io_db;
+ data.map = &s->io_db;
down(&rsrc_sem);
#ifdef CONFIG_PCI
@@ -664,7 +651,7 @@
data.mask = align - 1;
data.offset = base & data.mask;
- data.map = &mem_db;
+ data.map = &s->mem_db;
for (i = 0; i < 2; i++) {
if (low) {
@@ -830,7 +817,7 @@
======================================================================*/
-static int adjust_memory(adjust_t *adj)
+static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj)
{
u_long base, num;
int ret;
@@ -845,10 +832,10 @@
down(&rsrc_sem);
switch (adj->Action) {
case ADD_MANAGED_RESOURCE:
- ret = add_interval(&mem_db, base, num);
+ ret = add_interval(&s->mem_db, base, num);
break;
case REMOVE_MANAGED_RESOURCE:
- ret = sub_interval(&mem_db, base, num);
+ ret = sub_interval(&s->mem_db, base, num);
if (ret == CS_SUCCESS) {
struct pcmcia_socket *socket;
down_read(&pcmcia_socket_list_rwsem);
@@ -867,7 +854,7 @@
/*====================================================================*/
-static int adjust_io(adjust_t *adj)
+static int adjust_io(struct pcmcia_socket *s, adjust_t *adj)
{
int base, num, ret = CS_SUCCESS;
@@ -881,17 +868,17 @@
down(&rsrc_sem);
switch (adj->Action) {
case ADD_MANAGED_RESOURCE:
- if (add_interval(&io_db, base, num) != 0) {
+ if (add_interval(&s->io_db, base, num) != 0) {
ret = CS_IN_USE;
break;
}
#ifdef CONFIG_PCMCIA_PROBE
if (probe_io)
- do_io_probe(base, num);
+ do_io_probe(s, base, num);
#endif
break;
case REMOVE_MANAGED_RESOURCE:
- sub_interval(&io_db, base, num);
+ sub_interval(&s->io_db, base, num);
break;
default:
ret = CS_UNSUPPORTED_FUNCTION;
@@ -956,32 +943,40 @@
int pcmcia_adjust_resource_info(adjust_t *adj)
{
- switch (adj->Resource) {
- case RES_MEMORY_RANGE:
- return adjust_memory(adj);
- break;
- case RES_IO_RANGE:
- return adjust_io(adj);
- break;
- case RES_IRQ:
- return adjust_irq(adj);
- break;
- }
- return CS_UNSUPPORTED_FUNCTION;
+ struct pcmcia_socket *s;
+ int ret = CS_UNSUPPORTED_FUNCTION;
+
+ if (adj->Resource == RES_IRQ)
+ return adjust_irq(adj);
+
+ down_read(&pcmcia_socket_list_rwsem);
+ list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
+ switch (adj->Resource) {
+ case RES_MEMORY_RANGE:
+ ret = adjust_memory(s, adj);
+ break;
+ case RES_IO_RANGE:
+ ret = adjust_io(s, adj);
+ break;
+ }
+ }
+ up_read(&pcmcia_socket_list_rwsem);
+
+ return (ret);
}
EXPORT_SYMBOL(pcmcia_adjust_resource_info);
/*====================================================================*/
-void release_resource_db(void)
+void release_resource_db(struct pcmcia_socket *s)
{
resource_map_t *p, *q;
- for (p = mem_db.next; p != &mem_db; p = q) {
+ for (p = s->mem_db.next; p != &s->mem_db; p = q) {
q = p->next;
kfree(p);
}
- for (p = io_db.next; p != &io_db; p = q) {
+ for (p = s->io_db.next; p != &s->io_db; p = q) {
q = p->next;
kfree(p);
}
Index: 2.6.10-rc3/include/pcmcia/ss.h
===================================================================
--- 2.6.10-rc3.orig/include/pcmcia/ss.h 2004-12-05 10:26:03.917008728 +0100
+++ 2.6.10-rc3/include/pcmcia/ss.h 2004-12-05 10:26:06.914553032 +0100
@@ -146,6 +146,12 @@
struct region_t;
struct pcmcia_callback;
+/* for io_db and mem_db */
+struct resource_map_t {
+ u_long base, num;
+ struct resource_map_t *next;
+};
+
struct pcmcia_socket {
struct module *owner;
spinlock_t lock;
@@ -170,6 +176,10 @@
struct list_head socket_list;
struct completion socket_released;
+ struct resource_map_t mem_db;
+ struct resource_map_t io_db;
+ unsigned int rsrc_mem_probe;
+
/* deprecated */
unsigned int sock; /* socket number */
More information about the linux-pcmcia
mailing list