Merge branches 'release', 'asus', 'sony-laptop' and 'thinkpad' into release
[pandora-kernel.git] / drivers / s390 / char / sclp_vt220.c
index f77dc33..6807162 100644 (file)
@@ -99,8 +99,8 @@ static void sclp_vt220_emit_current(void);
 
 /* Registration structure for our interest in SCLP event buffers */
 static struct sclp_register sclp_vt220_register = {
-       .send_mask              = EvTyp_VT220Msg_Mask,
-       .receive_mask           = EvTyp_VT220Msg_Mask,
+       .send_mask              = EVTYP_VT220MSG_MASK,
+       .receive_mask           = EVTYP_VT220MSG_MASK,
        .state_change_fn        = NULL,
        .receiver_fn            = sclp_vt220_receiver_fn
 };
@@ -202,7 +202,7 @@ sclp_vt220_callback(struct sclp_req *request, void *data)
 static int
 __sclp_vt220_emit(struct sclp_vt220_request *request)
 {
-       if (!(sclp_vt220_register.sclp_send_mask & EvTyp_VT220Msg_Mask)) {
+       if (!(sclp_vt220_register.sclp_send_mask & EVTYP_VT220MSG_MASK)) {
                request->sclp_req.status = SCLP_REQ_FAILED;
                return -EIO;
        }
@@ -284,7 +284,7 @@ sclp_vt220_initialize_page(void *page)
        sccb->header.length = sizeof(struct sclp_vt220_sccb);
        sccb->header.function_code = SCLP_NORMAL_WRITE;
        sccb->header.response_code = 0x0000;
-       sccb->evbuf.type = EvTyp_VT220Msg;
+       sccb->evbuf.type = EVTYP_VT220MSG;
        sccb->evbuf.length = sizeof(struct evbuf_header);
 
        return request;
@@ -400,7 +400,7 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
                        while (list_empty(&sclp_vt220_empty)) {
                                spin_unlock_irqrestore(&sclp_vt220_lock,
                                                       flags);
-                               if (in_interrupt())
+                               if (in_atomic())
                                        sclp_sync_wait();
                                else
                                        wait_event(sclp_vt220_waitq,
@@ -621,11 +621,24 @@ sclp_vt220_flush_buffer(struct tty_struct *tty)
 /*
  * Initialize all relevant components and register driver with system.
  */
-static int
-__sclp_vt220_init(int early)
+static void __init __sclp_vt220_cleanup(void)
+{
+       struct list_head *page, *p;
+
+       list_for_each_safe(page, p, &sclp_vt220_empty) {
+               list_del(page);
+               if (slab_is_available())
+                       free_page((unsigned long) page);
+               else
+                       free_bootmem((unsigned long) page, PAGE_SIZE);
+       }
+}
+
+static int __init __sclp_vt220_init(void)
 {
        void *page;
        int i;
+       int num_pages;
 
        if (sclp_vt220_initialized)
                return 0;
@@ -642,13 +655,16 @@ __sclp_vt220_init(int early)
        sclp_vt220_flush_later = 0;
 
        /* Allocate pages for output buffering */
-       for (i = 0; i < (early ? MAX_CONSOLE_PAGES : MAX_KMEM_PAGES); i++) {
-               if (early)
-                       page = alloc_bootmem_low_pages(PAGE_SIZE);
-               else
+       num_pages = slab_is_available() ? MAX_KMEM_PAGES : MAX_CONSOLE_PAGES;
+       for (i = 0; i < num_pages; i++) {
+               if (slab_is_available())
                        page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
-               if (!page)
+               else
+                       page = alloc_bootmem_low_pages(PAGE_SIZE);
+               if (!page) {
+                       __sclp_vt220_cleanup();
                        return -ENOMEM;
+               }
                list_add_tail((struct list_head *) page, &sclp_vt220_empty);
        }
        return 0;
@@ -662,14 +678,13 @@ static const struct tty_operations sclp_vt220_ops = {
        .flush_chars = sclp_vt220_flush_chars,
        .write_room = sclp_vt220_write_room,
        .chars_in_buffer = sclp_vt220_chars_in_buffer,
-       .flush_buffer = sclp_vt220_flush_buffer
+       .flush_buffer = sclp_vt220_flush_buffer,
 };
 
 /*
  * Register driver with SCLP and Linux and initialize internal tty structures.
  */
-static int __init
-sclp_vt220_tty_init(void)
+static int __init sclp_vt220_tty_init(void)
 {
        struct tty_driver *driver;
        int rc;
@@ -679,18 +694,15 @@ sclp_vt220_tty_init(void)
        driver = alloc_tty_driver(1);
        if (!driver)
                return -ENOMEM;
-       rc = __sclp_vt220_init(0);
-       if (rc) {
-               put_tty_driver(driver);
-               return rc;
-       }
+       rc = __sclp_vt220_init();
+       if (rc)
+               goto out_driver;
        rc = sclp_register(&sclp_vt220_register);
        if (rc) {
                printk(KERN_ERR SCLP_VT220_PRINT_HEADER
                       "could not register tty - "
                       "sclp_register returned %d\n", rc);
-               put_tty_driver(driver);
-               return rc;
+               goto out_init;
        }
 
        driver->owner = THIS_MODULE;
@@ -709,14 +721,20 @@ sclp_vt220_tty_init(void)
                printk(KERN_ERR SCLP_VT220_PRINT_HEADER
                       "could not register tty - "
                       "tty_register_driver returned %d\n", rc);
-               put_tty_driver(driver);
-               return rc;
+               goto out_sclp;
        }
        sclp_vt220_driver = driver;
        return 0;
-}
 
-module_init(sclp_vt220_tty_init);
+out_sclp:
+       sclp_unregister(&sclp_vt220_register);
+out_init:
+       __sclp_vt220_cleanup();
+out_driver:
+       put_tty_driver(driver);
+       return rc;
+}
+__initcall(sclp_vt220_tty_init);
 
 #ifdef CONFIG_SCLP_VT220_CONSOLE
 
@@ -762,7 +780,7 @@ sclp_vt220_con_init(void)
 
        if (!CONSOLE_IS_SCLP)
                return 0;
-       rc = __sclp_vt220_init(1);
+       rc = __sclp_vt220_init();
        if (rc)
                return rc;
        /* Attach linux console */