From: Russell King <rmk@arm.linux.org.uk>
To: Linux Kernel List <linux-kernel@vger.kernel.org>
Subject: Re: [CFT] 4/6 (5): Add some locking to rsrc_mgr.c
Date: Wed, 12 Mar 2003 21:01:13 +0000 [thread overview]
Message-ID: <20030312210113.G27656@flint.arm.linux.org.uk> (raw)
In-Reply-To: <20030312205659.C27656@flint.arm.linux.org.uk>; from rmk@arm.linux.org.uk on Wed, Mar 12, 2003 at 08:56:59PM +0000
pcmcia-5.diff
Add an element of locking to the resource manager - don't allow
the PCMCIA resource lists to be changed while the pcmcia code is
scanning them.
diff -ur orig/drivers/pcmcia/rsrc_mgr.c linux/drivers/pcmcia/rsrc_mgr.c
--- orig/drivers/pcmcia/rsrc_mgr.c Mon Nov 18 09:52:12 2002
+++ linux/drivers/pcmcia/rsrc_mgr.c Sat Mar 1 19:09:21 2003
@@ -85,6 +85,8 @@
/* IO port resource database */
static resource_map_t io_db = { 0, 0, &io_db };
+static DECLARE_MUTEX(rsrc_sem);
+
#ifdef CONFIG_ISA
typedef struct irq_info_t {
@@ -403,16 +405,20 @@
static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
static int hi = 0, lo = 0;
u_long b, i, ok = 0;
-
- if (!probe_mem) return;
+
+ if (!probe_mem)
+ return;
+
+ down(&rsrc_sem);
/* We do up to four passes through the list */
if (!force_low) {
if (hi++ || (inv_probe(is_valid, do_cksum, mem_db.next, s) > 0))
- return;
+ goto out;
printk(KERN_NOTICE "cs: warning: no high memory space "
"available!\n");
}
- if (lo++) return;
+ if (lo++)
+ goto out;
for (m = mem_db.next; m != &mem_db; m = n) {
n = m->next;
/* Only probe < 1 MB */
@@ -432,6 +438,8 @@
}
}
}
+ out:
+ up(&rsrc_sem);
}
#else /* CONFIG_ISA */
@@ -442,11 +450,13 @@
resource_map_t *m;
static int done = 0;
- if (!probe_mem || done++)
- return;
- for (m = mem_db.next; m != &mem_db; m = m->next)
- if (do_mem_probe(m->base, m->num, is_valid, do_cksum, s))
- return;
+ if (probe_mem && done++ == 0) {
+ down(&rsrc_sem);
+ for (m = mem_db.next; m != &mem_db; m = m->next)
+ if (do_mem_probe(m->base, m->num, is_valid, do_cksum, s))
+ break;
+ up(&rsrc_sem);
+ }
}
#endif /* CONFIG_ISA */
@@ -469,7 +479,9 @@
{
ioaddr_t try;
resource_map_t *m;
-
+ int ret = -1;
+
+ down(&rsrc_sem);
for (m = io_db.next; m != &io_db; m = m->next) {
try = (m->base & ~(align-1)) + *base;
for (try = (try >= m->base) ? try : try+align;
@@ -477,12 +489,16 @@
try += align) {
if (request_io_resource(try, num, name, s->cap.cb_dev) == 0) {
*base = try;
- return 0;
+ ret = 0;
+ goto out;
}
- if (!align) break;
+ if (!align)
+ break;
}
}
- return -1;
+ out:
+ up(&rsrc_sem);
+ return ret;
}
int find_mem_region(u_long *base, u_long num, u_long align,
@@ -490,26 +506,35 @@
{
u_long try;
resource_map_t *m;
+ int ret = -1;
+ down(&rsrc_sem);
while (1) {
for (m = mem_db.next; m != &mem_db; m = m->next) {
/* first pass >1MB, second pass <1MB */
- if ((force_low != 0) ^ (m->base < 0x100000)) continue;
+ if ((force_low != 0) ^ (m->base < 0x100000))
+ continue;
+
try = (m->base & ~(align-1)) + *base;
for (try = (try >= m->base) ? try : try+align;
(try >= m->base) && (try+num <= m->base+m->num);
try += align) {
if (request_mem_resource(try, num, name, s->cap.cb_dev) == 0) {
*base = try;
- return 0;
+ ret = 0;
+ goto out;
}
- if (!align) break;
+ if (!align)
+ break;
}
}
- if (force_low) break;
+ if (force_low)
+ break;
force_low++;
}
- return -1;
+ out:
+ up(&rsrc_sem);
+ return ret;
}
/*======================================================================
@@ -534,53 +559,75 @@
int try_irq(u_int Attributes, int irq, int specific)
{
irq_info_t *info = &irq_table[irq];
+ int ret = 0;
+
+ down(&rsrc_sem);
if (info->Attributes & RES_ALLOCATED) {
switch (Attributes & IRQ_TYPE) {
case IRQ_TYPE_EXCLUSIVE:
- return CS_IN_USE;
+ ret = CS_IN_USE;
+ break;
case IRQ_TYPE_TIME:
if ((info->Attributes & RES_IRQ_TYPE)
- != RES_IRQ_TYPE_TIME)
- return CS_IN_USE;
- if (Attributes & IRQ_FIRST_SHARED)
- return CS_BAD_ATTRIBUTE;
+ != RES_IRQ_TYPE_TIME) {
+ ret = CS_IN_USE;
+ break;
+ }
+ if (Attributes & IRQ_FIRST_SHARED) {
+ ret = CS_BAD_ATTRIBUTE;
+ break;
+ }
info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
info->time_share++;
break;
case IRQ_TYPE_DYNAMIC_SHARING:
if ((info->Attributes & RES_IRQ_TYPE)
- != RES_IRQ_TYPE_DYNAMIC)
- return CS_IN_USE;
- if (Attributes & IRQ_FIRST_SHARED)
- return CS_BAD_ATTRIBUTE;
+ != RES_IRQ_TYPE_DYNAMIC) {
+ ret = CS_IN_USE;
+ break;
+ }
+ if (Attributes & IRQ_FIRST_SHARED) {
+ ret = CS_BAD_ATTRIBUTE;
+ break;
+ }
info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
info->dyn_share++;
break;
}
} else {
- if ((info->Attributes & RES_RESERVED) && !specific)
- return CS_IN_USE;
- if (check_irq(irq) != 0)
- return CS_IN_USE;
+ if ((info->Attributes & RES_RESERVED) && !specific) {
+ ret = CS_IN_USE;
+ goto out;
+ }
+ if (check_irq(irq) != 0) {
+ ret = CS_IN_USE;
+ goto out;
+ }
switch (Attributes & IRQ_TYPE) {
case IRQ_TYPE_EXCLUSIVE:
info->Attributes |= RES_ALLOCATED;
break;
case IRQ_TYPE_TIME:
- if (!(Attributes & IRQ_FIRST_SHARED))
- return CS_BAD_ATTRIBUTE;
+ if (!(Attributes & IRQ_FIRST_SHARED)) {
+ ret = CS_BAD_ATTRIBUTE;
+ break;
+ }
info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
info->time_share = 1;
break;
case IRQ_TYPE_DYNAMIC_SHARING:
- if (!(Attributes & IRQ_FIRST_SHARED))
- return CS_BAD_ATTRIBUTE;
+ if (!(Attributes & IRQ_FIRST_SHARED)) {
+ ret = CS_BAD_ATTRIBUTE;
+ break;
+ }
info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
info->dyn_share = 1;
break;
}
}
- return 0;
+ out:
+ up(&rsrc_sem);
+ return ret;
}
#endif
@@ -594,6 +641,7 @@
irq_info_t *info;
info = &irq_table[irq];
+ down(&rsrc_sem);
switch (Attributes & IRQ_TYPE) {
case IRQ_TYPE_EXCLUSIVE:
info->Attributes &= RES_RESERVED;
@@ -609,6 +657,7 @@
info->Attributes &= RES_RESERVED;
break;
}
+ up(&rsrc_sem);
}
#endif
@@ -631,6 +680,8 @@
return CS_BAD_SIZE;
ret = CS_SUCCESS;
+
+ down(&rsrc_sem);
switch (adj->Action) {
case ADD_MANAGED_RESOURCE:
ret = add_interval(&mem_db, base, num);
@@ -649,6 +700,7 @@
default:
ret = CS_UNSUPPORTED_FUNCTION;
}
+ up(&rsrc_sem);
return ret;
}
@@ -657,7 +709,7 @@
static int adjust_io(adjust_t *adj)
{
- int base, num;
+ int base, num, ret = CS_SUCCESS;
base = adj->resource.io.BasePort;
num = adj->resource.io.NumPorts;
@@ -666,10 +718,13 @@
if ((num <= 0) || (base+num > 0x10000) || (base+num <= base))
return CS_BAD_SIZE;
+ down(&rsrc_sem);
switch (adj->Action) {
case ADD_MANAGED_RESOURCE:
- if (add_interval(&io_db, base, num) != 0)
- return CS_IN_USE;
+ if (add_interval(&io_db, base, num) != 0) {
+ ret = CS_IN_USE;
+ break;
+ }
#ifdef CONFIG_ISA
if (probe_io)
do_io_probe(base, num);
@@ -679,17 +734,19 @@
sub_interval(&io_db, base, num);
break;
default:
- return CS_UNSUPPORTED_FUNCTION;
+ ret = CS_UNSUPPORTED_FUNCTION;
break;
}
+ up(&rsrc_sem);
- return CS_SUCCESS;
+ return ret;
}
/*====================================================================*/
static int adjust_irq(adjust_t *adj)
{
+ int ret = CS_SUCCESS;
#ifdef CONFIG_ISA
int irq;
irq_info_t *info;
@@ -698,33 +755,41 @@
if ((irq < 0) || (irq > 15))
return CS_BAD_IRQ;
info = &irq_table[irq];
-
+
+ down(&rsrc_sem);
switch (adj->Action) {
case ADD_MANAGED_RESOURCE:
if (info->Attributes & RES_REMOVED)
info->Attributes &= ~(RES_REMOVED|RES_ALLOCATED);
else
- if (adj->Attributes & RES_ALLOCATED)
- return CS_IN_USE;
+ if (adj->Attributes & RES_ALLOCATED) {
+ ret = CS_IN_USE;
+ break;
+ }
if (adj->Attributes & RES_RESERVED)
info->Attributes |= RES_RESERVED;
else
info->Attributes &= ~RES_RESERVED;
break;
case REMOVE_MANAGED_RESOURCE:
- if (info->Attributes & RES_REMOVED)
- return 0;
- if (info->Attributes & RES_ALLOCATED)
- return CS_IN_USE;
+ if (info->Attributes & RES_REMOVED) {
+ ret = 0;
+ break;
+ }
+ if (info->Attributes & RES_ALLOCATED) {
+ ret = CS_IN_USE;
+ break;
+ }
info->Attributes |= RES_ALLOCATED|RES_REMOVED;
info->Attributes &= ~RES_RESERVED;
break;
default:
- return CS_UNSUPPORTED_FUNCTION;
+ ret = CS_UNSUPPORTED_FUNCTION;
break;
}
+ up(&rsrc_sem);
#endif
- return CS_SUCCESS;
+ return ret;
}
/*====================================================================*/
--
Russell King (rmk@arm.linux.org.uk) The developer of ARM Linux
http://www.arm.linux.org.uk/personal/aboutme.html
next prev parent reply other threads:[~2003-03-12 20:54 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-03-12 20:56 [CFT] PCMCIA patches Russell King
2003-03-12 20:58 ` [CFT] 1/6 (2) kill get_*_map Russell King
2003-03-12 20:59 ` [CFT] 2/6 (3): Remove bus_* abstractions Russell King
2003-03-12 21:00 ` [CFT] 3/6 (4): add SOCKET_CARDBUS_CONFIG flag Russell King
2003-03-12 21:01 ` Russell King [this message]
2003-03-12 21:02 ` [CFT] 5/6 (6): Introduce CONFIG_PCMCIA_PROBE Russell King
2003-03-12 21:03 ` [CFT] 6/6 (7): Remove support for old cardbus clients Russell King
2003-03-24 11:30 ` [CFT] PCMCIA patches Paul Mackerras
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20030312210113.G27656@flint.arm.linux.org.uk \
--to=rmk@arm.linux.org.uk \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox