vserver 1.9.3
[linux-2.6.git] / drivers / pcmcia / cs.c
index 0646238..c33ac27 100644 (file)
@@ -264,7 +264,10 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
                goto err;
 
        wait_for_completion(&socket->thread_done);
-       BUG_ON(!socket->thread);
+       if(!socket->thread) {
+               printk(KERN_WARNING "PCMCIA: warning: socket thread for socket %p did not start\n", socket);
+               return -EIO;
+       }
        pcmcia_parse_events(socket, SS_DETECT);
 
        return 0;
@@ -424,8 +427,6 @@ static int send_event(struct pcmcia_socket *s, event_t event, int priority)
     return ret;
 } /* send_event */
 
-#define cs_to_timeout(cs) (((cs) * HZ + 99) / 100)
-
 static void socket_remove_drivers(struct pcmcia_socket *skt)
 {
        client_t *client;
@@ -445,8 +446,7 @@ static void socket_shutdown(struct pcmcia_socket *skt)
 
        socket_remove_drivers(skt);
        skt->state &= SOCKET_INUSE|SOCKET_PRESENT;
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(cs_to_timeout(shutdown_delay));
+       msleep(shutdown_delay * 10);
        skt->state &= SOCKET_INUSE;
        shutdown_socket(skt);
 }
@@ -464,8 +464,7 @@ static int socket_reset(struct pcmcia_socket *skt)
        skt->socket.flags &= ~SS_RESET;
        skt->ops->set_socket(skt, &skt->socket);
 
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(cs_to_timeout(unreset_delay));
+       msleep(unreset_delay * 10);
        for (i = 0; i < unreset_limit; i++) {
                skt->ops->get_status(skt, &status);
 
@@ -475,8 +474,7 @@ static int socket_reset(struct pcmcia_socket *skt)
                if (status & SS_READY)
                        return CS_SUCCESS;
 
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(cs_to_timeout(unreset_check));
+               msleep(unreset_check * 10);
        }
 
        cs_err(skt, "time out after reset.\n");
@@ -493,8 +491,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
        if (!(status & SS_DETECT))
                return CS_NO_CARD;
 
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(cs_to_timeout(initial_delay));
+       msleep(initial_delay * 10);
 
        for (i = 0; i < 100; i++) {
                skt->ops->get_status(skt, &status);
@@ -504,8 +501,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
                if (!(status & SS_PENDING))
                        break;
 
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(cs_to_timeout(10));
+               msleep(100);
        }
 
        if (status & SS_PENDING) {
@@ -538,8 +534,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
        /*
         * Wait "vcc_settle" for the supply to stabilise.
         */
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(cs_to_timeout(vcc_settle));
+       msleep(vcc_settle * 10);
 
        skt->ops->get_status(skt, &status);
        if (!(status & SS_POWERON)) {
@@ -656,10 +651,8 @@ static void socket_detect_change(struct pcmcia_socket *skt)
        if (!(skt->state & SOCKET_SUSPEND)) {
                int status;
 
-               if (!(skt->state & SOCKET_PRESENT)) {
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       schedule_timeout(cs_to_timeout(2));
-               }
+               if (!(skt->state & SOCKET_PRESENT))
+                       msleep(20);
 
                skt->ops->get_status(skt, &status);
                if ((skt->state & SOCKET_PRESENT) &&
@@ -678,9 +671,8 @@ static int pccardd(void *__skt)
        int ret;
 
        daemonize("pccardd");
-       skt->thread = current;
-       complete(&skt->thread_done);
 
+       skt->thread = current;
        skt->socket = dead_socket;
        skt->ops->init(skt);
        skt->ops->set_socket(skt, &skt->socket);
@@ -690,7 +682,10 @@ static int pccardd(void *__skt)
        if (ret) {
                printk(KERN_WARNING "PCMCIA: unable to register socket 0x%p\n",
                        skt);
+               skt->thread = NULL;
+               complete_and_exit(&skt->thread_done, 0);
        }
+       complete(&skt->thread_done);
 
        add_wait_queue(&skt->thread_wait, &wait);
        for (;;) {
@@ -1100,8 +1095,8 @@ int pcmcia_get_window(window_handle_t *handle, int idx, win_req_t *req)
     if (w == MAX_WIN)
        return CS_NO_MORE_ITEMS;
     win = &s->win[w];
-    req->Base = win->ctl.sys_start;
-    req->Size = win->ctl.sys_stop - win->ctl.sys_start + 1;
+    req->Base = win->ctl.res->start;
+    req->Size = win->ctl.res->end - win->ctl.res->start + 1;
     req->AccessSpeed = win->ctl.speed;
     req->Attributes = 0;
     if (win->ctl.flags & MAP_ATTRIB)
@@ -1548,8 +1543,11 @@ int pcmcia_release_window(window_handle_t win)
     s->state &= ~SOCKET_WIN_REQ(win->index);
 
     /* Release system memory */
-    if(!(s->features & SS_CAP_STATIC_MAP))
-       release_mem_region(win->base, win->size);
+    if (win->ctl.res) {
+       release_resource(win->ctl.res);
+       kfree(win->ctl.res);
+       win->ctl.res = NULL;
+    }
     win->handle->state &= ~CLIENT_WIN_REQ(win->index);
 
     win->magic = 0;
@@ -1871,14 +1869,14 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle
     win->index = w;
     win->handle = *handle;
     win->sock = s;
-    win->base = req->Base;
-    win->size = req->Size;
 
-    if (!(s->features & SS_CAP_STATIC_MAP) &&
-       find_mem_region(&win->base, win->size, align,
-                       (req->Attributes & WIN_MAP_BELOW_1MB),
-                       (*handle)->dev_info, s))
-       return CS_IN_USE;
+    if (!(s->features & SS_CAP_STATIC_MAP)) {
+       win->ctl.res = find_mem_region(req->Base, req->Size, align,
+                                      (req->Attributes & WIN_MAP_BELOW_1MB),
+                                      (*handle)->dev_info, s);
+       if (!win->ctl.res)
+           return CS_IN_USE;
+    }
     (*handle)->state |= CLIENT_WIN_REQ(w);
 
     /* Configure the socket controller */
@@ -1893,15 +1891,17 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle
        win->ctl.flags |= MAP_16BIT;
     if (req->Attributes & WIN_USE_WAIT)
        win->ctl.flags |= MAP_USE_WAIT;
-    win->ctl.sys_start = win->base;
-    win->ctl.sys_stop = win->base + win->size-1;
     win->ctl.card_start = 0;
     if (s->ops->set_mem_map(s, &win->ctl) != 0)
        return CS_BAD_ARGS;
     s->state |= SOCKET_WIN_REQ(w);
 
     /* Return window handle */
-    req->Base = win->ctl.sys_start;
+    if (s->features & SS_CAP_STATIC_MAP) {
+       req->Base = win->ctl.static_start;
+    } else {
+       req->Base = win->ctl.res->start;
+    }
     *wh = win;
     
     return CS_SUCCESS;
@@ -2025,16 +2025,18 @@ int pcmcia_eject_card(struct pcmcia_socket *skt)
        down(&skt->skt_sem);
        do {
                if (!(skt->state & SOCKET_PRESENT)) {
-                       ret = CS_NO_CARD;
+                       ret = -ENODEV;
                        break;
                }
 
                ret = send_event(skt, CS_EVENT_EJECTION_REQUEST, CS_EVENT_PRI_LOW);
-               if (ret != 0)
+               if (ret != 0) {
+                       ret = -EINVAL;
                        break;
+               }
 
                socket_remove(skt);
-               ret = CS_SUCCESS;
+               ret = 0;
        } while (0);
        up(&skt->skt_sem);
 
@@ -2050,14 +2052,14 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
        down(&skt->skt_sem);
        do {
                if (skt->state & SOCKET_PRESENT) {
-                       ret = CS_IN_USE;
+                       ret = -EBUSY;
                        break;
                }
                if (socket_insert(skt) == CS_NO_CARD) {
-                       ret = CS_NO_CARD;
+                       ret = -ENODEV;
                        break;
                }
-               ret = CS_SUCCESS;
+               ret = 0;
        } while (0);
        up(&skt->skt_sem);
 
@@ -2155,16 +2157,21 @@ EXPORT_SYMBOL(pcmcia_socket_class);
 
 static int __init init_pcmcia_cs(void)
 {
-    printk(KERN_INFO "%s\n", release);
-    printk(KERN_INFO "  %s\n", options);
+       int ret;
+       printk(KERN_INFO "%s\n", release);
+       printk(KERN_INFO "  %s\n", options);
 
-    return class_register(&pcmcia_socket_class);
+       ret = class_register(&pcmcia_socket_class);
+       if (ret)
+               return (ret);
+       return class_interface_register(&pccard_sysfs_interface);
 }
 
 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);
 }