Tested-by: Wolfram Sang <w.sang@pengutronix.de>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
socket_reset()
socket_setup()
socket_reset()
socket_setup()
- struct pccard_operations *ops
+ struct pccard_operations *ops
+ struct pccard_resource_ops *resource_ops;
Note that send_event() and struct pcmcia_callback *callback must not be
called with "ops_mutex" held.
Note that send_event() and struct pcmcia_callback *callback must not be
called with "ops_mutex" held.
2. Per-Socket Data:
-------------------
2. Per-Socket Data:
-------------------
-The resource_ops are on their own to provide proper locking.
+The resource_ops and their data are protected by ops_mutex.
The "main" struct pcmcia_socket is protected as follows (read-only fields
or single-use fields not mentioned):
The "main" struct pcmcia_socket is protected as follows (read-only fields
or single-use fields not mentioned):
spin_lock_init(&socket->thread_lock);
if (socket->resource_ops->init) {
spin_lock_init(&socket->thread_lock);
if (socket->resource_ops->init) {
+ mutex_lock(&socket->ops_mutex);
ret = socket->resource_ops->init(socket);
ret = socket->resource_ops->init(socket);
+ mutex_unlock(&socket->ops_mutex);
up_write(&pcmcia_socket_list_rwsem);
/* wait for sysfs to drop all references */
up_write(&pcmcia_socket_list_rwsem);
/* wait for sysfs to drop all references */
- if (socket->resource_ops->exit)
+ if (socket->resource_ops->exit) {
+ mutex_lock(&socket->ops_mutex);
socket->resource_ops->exit(socket);
socket->resource_ops->exit(socket);
+ mutex_unlock(&socket->ops_mutex);
+ }
wait_for_completion(&socket->socket_released);
} /* pcmcia_unregister_socket */
EXPORT_SYMBOL(pcmcia_unregister_socket);
wait_for_completion(&socket->socket_released);
} /* pcmcia_unregister_socket */
EXPORT_SYMBOL(pcmcia_unregister_socket);
{
cistpl_longlink_mfc_t mfc;
unsigned int no_funcs, i, no_chains;
{
cistpl_longlink_mfc_t mfc;
unsigned int no_funcs, i, no_chains;
+ mutex_lock(&s->ops_mutex);
if (!(s->resource_setup_done)) {
dev_dbg(&s->dev,
"no resources available, delaying card_add\n");
if (!(s->resource_setup_done)) {
dev_dbg(&s->dev,
"no resources available, delaying card_add\n");
+ mutex_unlock(&s->ops_mutex);
return -EAGAIN; /* try again, but later... */
}
if (pcmcia_validate_mem(s)) {
dev_dbg(&s->dev, "validating mem resources failed, "
"delaying card_add\n");
return -EAGAIN; /* try again, but later... */
}
if (pcmcia_validate_mem(s)) {
dev_dbg(&s->dev, "validating mem resources failed, "
"delaying card_add\n");
+ mutex_unlock(&s->ops_mutex);
return -EAGAIN; /* try again, but later... */
}
return -EAGAIN; /* try again, but later... */
}
+ mutex_unlock(&s->ops_mutex);
ret = pccard_validate_cis(s, &no_chains);
if (ret || !no_chains) {
ret = pccard_validate_cis(s, &no_chains);
if (ret || !no_chains) {
continue;
} else if (!(s->resource_setup_old))
s->resource_setup_old = 1;
continue;
} else if (!(s->resource_setup_old))
s->resource_setup_old = 1;
- mutex_unlock(&s->ops_mutex);
switch (adj->Resource) {
case RES_MEMORY_RANGE:
switch (adj->Resource) {
case RES_MEMORY_RANGE:
* last call to adjust_resource_info, we
* always need to assume this is the latest
* one... */
* last call to adjust_resource_info, we
* always need to assume this is the latest
* one... */
- mutex_lock(&s->ops_mutex);
s->resource_setup_done = 1;
s->resource_setup_done = 1;
- mutex_unlock(&s->ops_mutex);
+ mutex_unlock(&s->ops_mutex);
}
}
up_read(&pcmcia_socket_list_rwsem);
}
}
up_read(&pcmcia_socket_list_rwsem);
/* the good thing about SS_CAP_STATIC_MAP sockets is
* that they don't need a resource database */
/* the good thing about SS_CAP_STATIC_MAP sockets is
* that they don't need a resource database */
- mutex_lock(&s->ops_mutex);
s->resource_setup_done = 1;
s->resource_setup_done = 1;
- mutex_unlock(&s->ops_mutex);
unsigned int rsrc_mem_probe;
};
unsigned int rsrc_mem_probe;
};
-static DEFINE_MUTEX(rsrc_mutex);
#define MEM_PROBE_LOW (1 << 0)
#define MEM_PROBE_HIGH (1 << 1)
#define MEM_PROBE_LOW (1 << 0)
#define MEM_PROBE_HIGH (1 << 1)
- mutex_lock(&s->ops_mutex);
s->cis_mem.res = res;
s->cis_virt = ioremap(res->start, s->map_size);
if (s->cis_virt) {
s->cis_mem.res = res;
s->cis_virt = ioremap(res->start, s->map_size);
if (s->cis_virt) {
s->cis_virt = NULL;
}
s->cis_mem.res = NULL;
s->cis_virt = NULL;
}
s->cis_mem.res = NULL;
- mutex_unlock(&s->ops_mutex);
if ((ret) || (*count == 0))
return -EINVAL;
return 0;
if ((ret) || (*count == 0))
return -EINVAL;
return 0;
int i, a = 0, b = -1, d;
void __iomem *virt;
int i, a = 0, b = -1, d;
void __iomem *virt;
- mutex_lock(&s->ops_mutex);
-
virt = ioremap(res->start, s->map_size);
if (virt) {
map.map = 0;
virt = ioremap(res->start, s->map_size);
if (virt) {
map.map = 0;
- mutex_unlock(&s->ops_mutex);
-
if (b == -1)
return -EINVAL;
if (b == -1)
return -EINVAL;
if (!probe_mem)
return 0;
if (!probe_mem)
return 0;
- mutex_lock(&rsrc_mutex);
-
if (s->features & SS_CAP_PAGE_REGS)
probe_mask = MEM_PROBE_HIGH;
if (s->features & SS_CAP_PAGE_REGS)
probe_mask = MEM_PROBE_HIGH;
- mutex_unlock(&rsrc_mutex);
-
struct socket_data *s_data = s->resource_data;
int ret = -ENOMEM;
struct socket_data *s_data = s->resource_data;
int ret = -ENOMEM;
- 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;
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;
}
ret = adjust_resource(res, r_start, r_end - r_start + 1);
break;
}
- mutex_unlock(&rsrc_mutex);
data.offset = base & data.mask;
data.map = &s_data->io_db;
data.offset = base & data.mask;
data.map = &s_data->io_db;
- mutex_lock(&rsrc_mutex);
#ifdef CONFIG_PCI
if (s->cb_dev) {
ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
#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);
#endif
ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
1, pcmcia_align, &data);
- mutex_unlock(&rsrc_mutex);
if (ret != 0) {
kfree(res);
if (ret != 0) {
kfree(res);
min = 0x100000UL + base;
}
min = 0x100000UL + base;
}
- mutex_lock(&rsrc_mutex);
#ifdef CONFIG_PCI
if (s->cb_dev) {
ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
#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);
#endif
ret = allocate_resource(&iomem_resource, res, num, min,
max, 1, pcmcia_align, &data);
- mutex_unlock(&rsrc_mutex);
if (ret == 0 || low)
break;
low = 1;
if (ret == 0 || low)
break;
low = 1;
if (end < start)
return -EINVAL;
if (end < start)
return -EINVAL;
- mutex_lock(&rsrc_mutex);
switch (action) {
case ADD_MANAGED_RESOURCE:
ret = add_interval(&data->mem_db, start, size);
switch (action) {
case ADD_MANAGED_RESOURCE:
ret = add_interval(&data->mem_db, start, size);
default:
ret = -EINVAL;
}
default:
ret = -EINVAL;
}
- mutex_unlock(&rsrc_mutex);
if (end > IO_SPACE_LIMIT)
return -EINVAL;
if (end > IO_SPACE_LIMIT)
return -EINVAL;
- mutex_lock(&rsrc_mutex);
switch (action) {
case ADD_MANAGED_RESOURCE:
if (add_interval(&data->io_db, start, size) != 0) {
switch (action) {
case ADD_MANAGED_RESOURCE:
if (add_interval(&data->io_db, start, size) != 0) {
- mutex_unlock(&rsrc_mutex);
struct socket_data *data = s->resource_data;
struct resource_map *p, *q;
struct socket_data *data = s->resource_data;
struct resource_map *p, *q;
- mutex_lock(&rsrc_mutex);
for (p = data->mem_db.next; p != &data->mem_db; p = q) {
q = p->next;
kfree(p);
for (p = data->mem_db.next; p != &data->mem_db; p = q) {
q = p->next;
kfree(p);
- mutex_unlock(&rsrc_mutex);
struct resource_map *p;
ssize_t ret = 0;
struct resource_map *p;
ssize_t ret = 0;
- mutex_lock(&rsrc_mutex);
+ mutex_lock(&s->ops_mutex);
data = s->resource_data;
for (p = data->io_db.next; p != &data->io_db; p = p->next) {
data = s->resource_data;
for (p = data->io_db.next; p != &data->io_db; p = p->next) {
((unsigned long) p->base + p->num - 1));
}
((unsigned long) p->base + p->num - 1));
}
- mutex_unlock(&rsrc_mutex);
+ mutex_unlock(&s->ops_mutex);
if (end_addr < start_addr)
return -EINVAL;
if (end_addr < start_addr)
return -EINVAL;
+ mutex_lock(&s->ops_mutex);
ret = adjust_io(s, add, start_addr, end_addr);
if (!ret)
s->resource_setup_new = 1;
ret = adjust_io(s, add, start_addr, end_addr);
if (!ret)
s->resource_setup_new = 1;
+ mutex_unlock(&s->ops_mutex);
return ret ? ret : count;
}
return ret ? ret : count;
}
struct resource_map *p;
ssize_t ret = 0;
struct resource_map *p;
ssize_t ret = 0;
- mutex_lock(&rsrc_mutex);
+ mutex_lock(&s->ops_mutex);
data = s->resource_data;
for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
data = s->resource_data;
for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
((unsigned long) p->base + p->num - 1));
}
((unsigned long) p->base + p->num - 1));
}
- mutex_unlock(&rsrc_mutex);
+ mutex_unlock(&s->ops_mutex);
if (end_addr < start_addr)
return -EINVAL;
if (end_addr < start_addr)
return -EINVAL;
+ mutex_lock(&s->ops_mutex);
ret = adjust_memory(s, add, start_addr, end_addr);
if (!ret)
s->resource_setup_new = 1;
ret = adjust_memory(s, add, start_addr, end_addr);
if (!ret)
s->resource_setup_new = 1;
+ mutex_unlock(&s->ops_mutex);
return ret ? ret : count;
}
return ret ? ret : count;
}