Commit 05ea2914 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bk.arm.linux.org.uk/linux-2.6-pcmcia

into home.osdl.org:/home/torvalds/v2.5/linux
parents ba8a0415 1d921834
...@@ -281,72 +281,29 @@ int pcmcia_socket_dev_resume(struct device *dev) ...@@ -281,72 +281,29 @@ int pcmcia_socket_dev_resume(struct device *dev)
EXPORT_SYMBOL(pcmcia_socket_dev_resume); EXPORT_SYMBOL(pcmcia_socket_dev_resume);
static int pccardd(void *__skt); static void pcmcia_release_socket(struct class_device *class_dev)
#define to_class_data(dev) dev->class_data
static int pcmcia_add_socket(struct class_device *class_dev)
{
struct pcmcia_socket *socket = class_get_devdata(class_dev);
int ret = 0;
/* base address = 0, map = 0 */
socket->cis_mem.flags = 0;
socket->cis_mem.speed = cis_speed;
socket->erase_busy.next = socket->erase_busy.prev = &socket->erase_busy;
INIT_LIST_HEAD(&socket->cis_cache);
spin_lock_init(&socket->lock);
init_completion(&socket->thread_done);
init_waitqueue_head(&socket->thread_wait);
init_MUTEX(&socket->skt_sem);
spin_lock_init(&socket->thread_lock);
socket->socket = dead_socket;
socket->ops->init(socket);
ret = kernel_thread(pccardd, socket, CLONE_KERNEL);
if (ret < 0)
return ret;
wait_for_completion(&socket->thread_done);
BUG_ON(!socket->thread);
pcmcia_parse_events(socket, SS_DETECT);
return 0;
}
static void pcmcia_remove_socket(struct class_device *class_dev)
{ {
struct pcmcia_socket *socket = class_get_devdata(class_dev); struct pcmcia_socket *socket = class_get_devdata(class_dev);
client_t *client; client_t *client;
if (socket->thread) {
init_completion(&socket->thread_done);
socket->thread = NULL;
wake_up(&socket->thread_wait);
wait_for_completion(&socket->thread_done);
}
release_cis_mem(socket);
while (socket->clients) { while (socket->clients) {
client = socket->clients; client = socket->clients;
socket->clients = socket->clients->next; socket->clients = socket->clients->next;
kfree(client); kfree(client);
} }
socket->ops = NULL;
}
static void pcmcia_release_socket(struct class_device *class_dev)
{
struct pcmcia_socket *socket = class_get_devdata(class_dev);
complete(&socket->socket_released); complete(&socket->socket_released);
} }
static int pccardd(void *__skt);
/** /**
* pcmcia_register_socket - add a new pcmcia socket device * pcmcia_register_socket - add a new pcmcia socket device
*/ */
int pcmcia_register_socket(struct pcmcia_socket *socket) int pcmcia_register_socket(struct pcmcia_socket *socket)
{ {
int ret;
if (!socket || !socket->ops || !socket->dev.dev) if (!socket || !socket->ops || !socket->dev.dev)
return -EINVAL; return -EINVAL;
...@@ -381,15 +338,34 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) ...@@ -381,15 +338,34 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
socket->dev.class = &pcmcia_socket_class; socket->dev.class = &pcmcia_socket_class;
snprintf(socket->dev.class_id, BUS_ID_SIZE, "pcmcia_socket%u", socket->sock); snprintf(socket->dev.class_id, BUS_ID_SIZE, "pcmcia_socket%u", socket->sock);
/* register with the device core */ /* base address = 0, map = 0 */
if (class_device_register(&socket->dev)) { socket->cis_mem.flags = 0;
down_write(&pcmcia_socket_list_rwsem); socket->cis_mem.speed = cis_speed;
list_del(&socket->socket_list); socket->erase_busy.next = socket->erase_busy.prev = &socket->erase_busy;
up_write(&pcmcia_socket_list_rwsem); INIT_LIST_HEAD(&socket->cis_cache);
return -EINVAL; spin_lock_init(&socket->lock);
}
init_completion(&socket->socket_released);
init_completion(&socket->thread_done);
init_waitqueue_head(&socket->thread_wait);
init_MUTEX(&socket->skt_sem);
spin_lock_init(&socket->thread_lock);
ret = kernel_thread(pccardd, socket, CLONE_KERNEL);
if (ret < 0)
goto err;
wait_for_completion(&socket->thread_done);
BUG_ON(!socket->thread);
pcmcia_parse_events(socket, SS_DETECT);
return 0; return 0;
err:
down_write(&pcmcia_socket_list_rwsem);
list_del(&socket->socket_list);
up_write(&pcmcia_socket_list_rwsem);
return ret;
} /* pcmcia_register_socket */ } /* pcmcia_register_socket */
EXPORT_SYMBOL(pcmcia_register_socket); EXPORT_SYMBOL(pcmcia_register_socket);
...@@ -404,10 +380,13 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket) ...@@ -404,10 +380,13 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket)
DEBUG(0, "cs: pcmcia_unregister_socket(0x%p)\n", socket->ops); DEBUG(0, "cs: pcmcia_unregister_socket(0x%p)\n", socket->ops);
init_completion(&socket->socket_released); if (socket->thread) {
init_completion(&socket->thread_done);
/* remove from the device core */ socket->thread = NULL;
class_device_unregister(&socket->dev); wake_up(&socket->thread_wait);
wait_for_completion(&socket->thread_done);
}
release_cis_mem(socket);
/* remove from our own list */ /* remove from our own list */
down_write(&pcmcia_socket_list_rwsem); down_write(&pcmcia_socket_list_rwsem);
...@@ -783,11 +762,22 @@ static int pccardd(void *__skt) ...@@ -783,11 +762,22 @@ static int pccardd(void *__skt)
{ {
struct pcmcia_socket *skt = __skt; struct pcmcia_socket *skt = __skt;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
int ret;
daemonize("pccardd"); daemonize("pccardd");
skt->thread = current; skt->thread = current;
complete(&skt->thread_done); complete(&skt->thread_done);
skt->socket = dead_socket;
skt->ops->init(skt);
/* register with the device core */
ret = class_device_register(&skt->dev);
if (ret) {
printk(KERN_WARNING "PCMCIA: unable to register socket 0x%p\n",
skt);
}
add_wait_queue(&skt->thread_wait, &wait); add_wait_queue(&skt->thread_wait, &wait);
for (;;) { for (;;) {
unsigned long flags; unsigned long flags;
...@@ -823,6 +813,9 @@ static int pccardd(void *__skt) ...@@ -823,6 +813,9 @@ static int pccardd(void *__skt)
} }
remove_wait_queue(&skt->thread_wait, &wait); remove_wait_queue(&skt->thread_wait, &wait);
/* remove from the device core */
class_device_unregister(&skt->dev);
complete_and_exit(&skt->thread_done, 0); complete_and_exit(&skt->thread_done, 0);
} }
...@@ -2501,12 +2494,6 @@ struct class pcmcia_socket_class = { ...@@ -2501,12 +2494,6 @@ struct class pcmcia_socket_class = {
}; };
EXPORT_SYMBOL(pcmcia_socket_class); EXPORT_SYMBOL(pcmcia_socket_class);
static struct class_interface pcmcia_socket = {
.class = &pcmcia_socket_class,
.add = &pcmcia_add_socket,
.remove = &pcmcia_remove_socket,
};
static int __init init_pcmcia_cs(void) static int __init init_pcmcia_cs(void)
{ {
...@@ -2514,7 +2501,6 @@ static int __init init_pcmcia_cs(void) ...@@ -2514,7 +2501,6 @@ static int __init init_pcmcia_cs(void)
printk(KERN_INFO " %s\n", options); printk(KERN_INFO " %s\n", options);
DEBUG(0, "%s\n", version); DEBUG(0, "%s\n", version);
class_register(&pcmcia_socket_class); class_register(&pcmcia_socket_class);
class_interface_register(&pcmcia_socket);
return 0; return 0;
} }
...@@ -2523,7 +2509,6 @@ static void __exit exit_pcmcia_cs(void) ...@@ -2523,7 +2509,6 @@ static void __exit exit_pcmcia_cs(void)
{ {
printk(KERN_INFO "unloading Kernel Card Services\n"); printk(KERN_INFO "unloading Kernel Card Services\n");
release_resource_db(); release_resource_db();
class_interface_unregister(&pcmcia_socket);
class_unregister(&pcmcia_socket_class); class_unregister(&pcmcia_socket_class);
} }
......
...@@ -491,7 +491,7 @@ static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s) ...@@ -491,7 +491,7 @@ static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s)
void validate_mem(struct pcmcia_socket *s) void validate_mem(struct pcmcia_socket *s)
{ {
resource_map_t *m, *n; resource_map_t *m, mm;
static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 }; static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
static int hi = 0, lo = 0; static int hi = 0, lo = 0;
u_long b, i, ok = 0; u_long b, i, ok = 0;
...@@ -510,18 +510,18 @@ void validate_mem(struct pcmcia_socket *s) ...@@ -510,18 +510,18 @@ void validate_mem(struct pcmcia_socket *s)
} }
if (lo++) if (lo++)
goto out; goto out;
for (m = mem_db.next; m != &mem_db; m = n) { for (m = mem_db.next; m != &mem_db; m = mm.next) {
n = m->next; mm = *m;
/* Only probe < 1 MB */ /* Only probe < 1 MB */
if (m->base >= 0x100000) continue; if (mm.base >= 0x100000) continue;
if ((m->base | m->num) & 0xffff) { if ((mm.base | mm.num) & 0xffff) {
ok += do_mem_probe(m->base, m->num, s); ok += do_mem_probe(mm.base, mm.num, s);
continue; continue;
} }
/* Special probe for 64K-aligned block */ /* Special probe for 64K-aligned block */
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
b = order[i] << 12; b = order[i] << 12;
if ((b >= m->base) && (b+0x10000 <= m->base+m->num)) { if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
if (ok >= mem_limit) if (ok >= mem_limit)
sub_interval(&mem_db, b, 0x10000); sub_interval(&mem_db, b, 0x10000);
else else
...@@ -537,14 +537,14 @@ void validate_mem(struct pcmcia_socket *s) ...@@ -537,14 +537,14 @@ void validate_mem(struct pcmcia_socket *s)
void validate_mem(struct pcmcia_socket *s) void validate_mem(struct pcmcia_socket *s)
{ {
resource_map_t *m, *n; resource_map_t *m, mm;
static int done = 0; static int done = 0;
if (probe_mem && done++ == 0) { if (probe_mem && done++ == 0) {
down(&rsrc_sem); down(&rsrc_sem);
for (m = mem_db.next; m != &mem_db; m = n) { for (m = mem_db.next; m != &mem_db; m = mm.next) {
n = m->next; mm = *m;
if (do_mem_probe(m->base, m->num, s)) if (do_mem_probe(mm.base, mm.num, s))
break; break;
} }
up(&rsrc_sem); up(&rsrc_sem);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment