* (C) 1999 David A. Hinds
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
unsigned int rsrc_mem_probe;
};
-static DECLARE_MUTEX(rsrc_sem);
+static DEFINE_MUTEX(rsrc_mutex);
#define MEM_PROBE_LOW (1 << 0)
#define MEM_PROBE_HIGH (1 << 1)
======================================================================*/
static struct resource *
-make_resource(unsigned long b, unsigned long n, int flags, char *name)
+make_resource(resource_size_t b, resource_size_t n, int flags, char *name)
{
- struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
+ struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
if (res) {
- memset(res, 0, sizeof(*res));
res->name = name;
res->start = b;
res->end = b + n - 1;
}
static struct resource *
-claim_region(struct pcmcia_socket *s, unsigned long base, unsigned long size,
- int type, char *name)
+claim_region(struct pcmcia_socket *s, resource_size_t base,
+ resource_size_t size, int type, char *name)
{
struct resource *res, *parent;
base, base+num-1);
/* First, what does a floating port look like? */
- b = kmalloc(256, GFP_KERNEL);
+ b = kzalloc(256, GFP_KERNEL);
if (!b) {
printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
return;
}
- memset(b, 0, 256);
for (i = base, most = 0; i < base+num; i += 8) {
res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
if (!res)
static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
{
- struct socket_data *s_data = s->resource_data;
- u_long ok;
- if (m == &s_data->mem_db)
- return 0;
- ok = inv_probe(m->next, s);
- if (ok) {
- if (m->base >= 0x100000)
- sub_interval(&s_data->mem_db, m->base, m->num);
- return ok;
- }
- if (m->base < 0x100000)
- return 0;
- return do_mem_probe(m->base, m->num, s);
+ struct socket_data *s_data = s->resource_data;
+ u_long ok;
+ if (m == &s_data->mem_db)
+ return 0;
+ ok = inv_probe(m->next, s);
+ if (ok) {
+ if (m->base >= 0x100000)
+ sub_interval(&s_data->mem_db, m->base, m->num);
+ return ok;
+ }
+ if (m->base < 0x100000)
+ return 0;
+ return do_mem_probe(m->base, m->num, s);
}
-static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
+static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
{
- struct resource_map *m, mm;
- static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
- u_long b, i, ok = 0;
- struct socket_data *s_data = s->resource_data;
+ struct resource_map *m, mm;
+ static unsigned char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
+ unsigned long b, i, ok = 0;
+ struct socket_data *s_data = s->resource_data;
- /* We do up to four passes through the list */
- if (probe_mask & MEM_PROBE_HIGH) {
- if (inv_probe(s_data->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 = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
- mm = *m;
- /* Only probe < 1 MB */
- if (mm.base >= 0x100000) continue;
- if ((mm.base | mm.num) & 0xffff) {
- ok += do_mem_probe(mm.base, mm.num, s);
- continue;
+ /* We do up to four passes through the list */
+ if (probe_mask & MEM_PROBE_HIGH) {
+ if (inv_probe(s_data->mem_db.next, s) > 0)
+ return 0;
+ printk(KERN_NOTICE "cs: warning: no high memory space "
+ "available!\n");
+ return -ENODEV;
}
- /* Special probe for 64K-aligned block */
- for (i = 0; i < 4; i++) {
- b = order[i] << 12;
- if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
- if (ok >= mem_limit)
- sub_interval(&s_data->mem_db, b, 0x10000);
- else
- ok += do_mem_probe(b, 0x10000, s);
- }
+
+ for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
+ mm = *m;
+ /* Only probe < 1 MB */
+ if (mm.base >= 0x100000)
+ continue;
+ if ((mm.base | mm.num) & 0xffff) {
+ ok += do_mem_probe(mm.base, mm.num, s);
+ continue;
+ }
+ /* Special probe for 64K-aligned block */
+ for (i = 0; i < 4; i++) {
+ b = order[i] << 12;
+ if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
+ if (ok >= mem_limit)
+ sub_interval(&s_data->mem_db, b, 0x10000);
+ else
+ ok += do_mem_probe(b, 0x10000, s);
+ }
+ }
}
- }
+
+ if (ok > 0)
+ return 0;
+
+ return -ENODEV;
}
#else /* CONFIG_PCMCIA_PROBE */
-static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
+static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
{
struct resource_map *m, mm;
struct socket_data *s_data = s->resource_data;
+ unsigned long ok = 0;
for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
mm = *m;
- do_mem_probe(mm.base, mm.num, s);
+ ok += do_mem_probe(mm.base, mm.num, s);
}
+ if (ok > 0)
+ return 0;
+ return -ENODEV;
}
#endif /* CONFIG_PCMCIA_PROBE */
/*
- * Locking note: Must be called with skt_sem held!
+ * Locking note: Must be called with skt_mutex held!
*/
-static void pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
+static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
{
struct socket_data *s_data = s->resource_data;
- if (probe_mem) {
- unsigned int probe_mask;
+ unsigned int probe_mask = MEM_PROBE_LOW;
+ int ret = 0;
+
+ if (!probe_mem)
+ return 0;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
- probe_mask = MEM_PROBE_LOW;
- if (s->features & SS_CAP_PAGE_REGS)
- probe_mask = MEM_PROBE_HIGH;
+ if (s->features & SS_CAP_PAGE_REGS)
+ probe_mask = MEM_PROBE_HIGH;
- if (probe_mask & ~s_data->rsrc_mem_probe) {
+ if (probe_mask & ~s_data->rsrc_mem_probe) {
+ if (s->state & SOCKET_PRESENT)
+ ret = validate_mem(s, probe_mask);
+ if (!ret)
s_data->rsrc_mem_probe |= probe_mask;
+ }
- if (s->state & SOCKET_PRESENT)
- validate_mem(s, probe_mask);
- }
+ mutex_unlock(&rsrc_mutex);
- up(&rsrc_sem);
- }
+ return ret;
}
struct pcmcia_align_data {
static void
pcmcia_common_align(void *align_data, struct resource *res,
- unsigned long size, unsigned long align)
+ resource_size_t size, resource_size_t align)
{
struct pcmcia_align_data *data = align_data;
- unsigned long start;
+ resource_size_t start;
/*
* Ensure that we have the correct start address
*/
}
static void
-pcmcia_align(void *align_data, struct resource *res,
- unsigned long size, unsigned long align)
+pcmcia_align(void *align_data, struct resource *res, resource_size_t size,
+ resource_size_t align)
{
struct pcmcia_align_data *data = align_data;
struct resource_map *m;
struct socket_data *s_data = s->resource_data;
int ret = -ENOMEM;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) {
unsigned long start = m->base;
unsigned long end = m->base + m->num - 1;
ret = adjust_resource(res, r_start, r_end - r_start + 1);
break;
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
return ret;
}
data.offset = base & data.mask;
data.map = &s_data->io_db;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
#ifdef CONFIG_PCI
if (s->cb_dev) {
ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
#endif
ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
1, pcmcia_align, &data);
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
if (ret != 0) {
kfree(res);
min = 0x100000UL + base;
}
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
#ifdef CONFIG_PCI
if (s->cb_dev) {
ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
#endif
ret = allocate_resource(&iomem_resource, res, num, min,
max, 1, pcmcia_align, &data);
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
if (ret == 0 || low)
break;
low = 1;
if (end < start)
return -EINVAL;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
switch (action) {
case ADD_MANAGED_RESOURCE:
ret = add_interval(&data->mem_db, start, size);
default:
ret = -EINVAL;
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
return ret;
}
if (end > IO_SPACE_LIMIT)
return -EINVAL;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
switch (action) {
case ADD_MANAGED_RESOURCE:
if (add_interval(&data->io_db, start, size) != 0) {
ret = -EINVAL;
break;
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
return ret;
}
if (res->flags & IORESOURCE_IO) {
if (res == &ioport_resource)
continue;
- printk(KERN_INFO "pcmcia: parent PCI bridge I/O window: 0x%lx - 0x%lx\n",
- res->start, res->end);
+ printk(KERN_INFO "pcmcia: parent PCI bridge I/O "
+ "window: 0x%llx - 0x%llx\n",
+ (unsigned long long)res->start,
+ (unsigned long long)res->end);
if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end))
done |= IORESOURCE_IO;
if (res->flags & IORESOURCE_MEM) {
if (res == &iomem_resource)
continue;
- printk(KERN_INFO "pcmcia: parent PCI bridge Memory window: 0x%lx - 0x%lx\n",
- res->start, res->end);
+ printk(KERN_INFO "pcmcia: parent PCI bridge Memory "
+ "window: 0x%llx - 0x%llx\n",
+ (unsigned long long)res->start,
+ (unsigned long long)res->end);
if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end))
done |= IORESOURCE_MEM;
}
{
struct socket_data *data;
- data = kmalloc(sizeof(struct socket_data), GFP_KERNEL);
+ data = kzalloc(sizeof(struct socket_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- memset(data, 0, sizeof(struct socket_data));
data->mem_db.next = &data->mem_db;
data->io_db.next = &data->io_db;
struct socket_data *data = s->resource_data;
struct resource_map *p, *q;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
for (p = data->mem_db.next; p != &data->mem_db; p = q) {
q = p->next;
kfree(p);
q = p->next;
kfree(p);
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
}
struct resource_map *p;
ssize_t ret = 0;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
data = s->resource_data;
for (p = data->io_db.next; p != &data->io_db; p = p->next) {
((unsigned long) p->base + p->num - 1));
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
return (ret);
}
struct resource_map *p;
ssize_t ret = 0;
- down(&rsrc_sem);
+ mutex_lock(&rsrc_mutex);
data = s->resource_data;
for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
((unsigned long) p->base + p->num - 1));
}
- up(&rsrc_sem);
+ mutex_unlock(&rsrc_mutex);
return (ret);
}