Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * SCLP line mode console driver
0004  *
0005  * Copyright IBM Corp. 1999, 2009
0006  * Author(s): Martin Peschke <mpeschke@de.ibm.com>
0007  *        Martin Schwidefsky <schwidefsky@de.ibm.com>
0008  */
0009 
0010 #include <linux/kmod.h>
0011 #include <linux/console.h>
0012 #include <linux/init.h>
0013 #include <linux/panic_notifier.h>
0014 #include <linux/timer.h>
0015 #include <linux/jiffies.h>
0016 #include <linux/termios.h>
0017 #include <linux/err.h>
0018 #include <linux/reboot.h>
0019 #include <linux/gfp.h>
0020 
0021 #include "sclp.h"
0022 #include "sclp_rw.h"
0023 #include "sclp_tty.h"
0024 
0025 #define sclp_console_major 4        /* TTYAUX_MAJOR */
0026 #define sclp_console_minor 64
0027 #define sclp_console_name  "ttyS"
0028 
0029 /* Lock to guard over changes to global variables */
0030 static DEFINE_SPINLOCK(sclp_con_lock);
0031 /* List of free pages that can be used for console output buffering */
0032 static LIST_HEAD(sclp_con_pages);
0033 /* List of full struct sclp_buffer structures ready for output */
0034 static LIST_HEAD(sclp_con_outqueue);
0035 /* Pointer to current console buffer */
0036 static struct sclp_buffer *sclp_conbuf;
0037 /* Timer for delayed output of console messages */
0038 static struct timer_list sclp_con_timer;
0039 /* Flag that output queue is currently running */
0040 static int sclp_con_queue_running;
0041 
0042 /* Output format for console messages */
0043 #define SCLP_CON_COLUMNS    320
0044 #define SPACES_PER_TAB      8
0045 
0046 static void
0047 sclp_conbuf_callback(struct sclp_buffer *buffer, int rc)
0048 {
0049     unsigned long flags;
0050     void *page;
0051 
0052     do {
0053         page = sclp_unmake_buffer(buffer);
0054         spin_lock_irqsave(&sclp_con_lock, flags);
0055 
0056         /* Remove buffer from outqueue */
0057         list_del(&buffer->list);
0058         list_add_tail((struct list_head *) page, &sclp_con_pages);
0059 
0060         /* Check if there is a pending buffer on the out queue. */
0061         buffer = NULL;
0062         if (!list_empty(&sclp_con_outqueue))
0063             buffer = list_first_entry(&sclp_con_outqueue,
0064                           struct sclp_buffer, list);
0065         if (!buffer) {
0066             sclp_con_queue_running = 0;
0067             spin_unlock_irqrestore(&sclp_con_lock, flags);
0068             break;
0069         }
0070         spin_unlock_irqrestore(&sclp_con_lock, flags);
0071     } while (sclp_emit_buffer(buffer, sclp_conbuf_callback));
0072 }
0073 
0074 /*
0075  * Finalize and emit first pending buffer.
0076  */
0077 static void sclp_conbuf_emit(void)
0078 {
0079     struct sclp_buffer* buffer;
0080     unsigned long flags;
0081     int rc;
0082 
0083     spin_lock_irqsave(&sclp_con_lock, flags);
0084     if (sclp_conbuf)
0085         list_add_tail(&sclp_conbuf->list, &sclp_con_outqueue);
0086     sclp_conbuf = NULL;
0087     if (sclp_con_queue_running)
0088         goto out_unlock;
0089     if (list_empty(&sclp_con_outqueue))
0090         goto out_unlock;
0091     buffer = list_first_entry(&sclp_con_outqueue, struct sclp_buffer,
0092                   list);
0093     sclp_con_queue_running = 1;
0094     spin_unlock_irqrestore(&sclp_con_lock, flags);
0095 
0096     rc = sclp_emit_buffer(buffer, sclp_conbuf_callback);
0097     if (rc)
0098         sclp_conbuf_callback(buffer, rc);
0099     return;
0100 out_unlock:
0101     spin_unlock_irqrestore(&sclp_con_lock, flags);
0102 }
0103 
0104 /*
0105  * Wait until out queue is empty
0106  */
0107 static void sclp_console_sync_queue(void)
0108 {
0109     unsigned long flags;
0110 
0111     spin_lock_irqsave(&sclp_con_lock, flags);
0112     del_timer(&sclp_con_timer);
0113     while (sclp_con_queue_running) {
0114         spin_unlock_irqrestore(&sclp_con_lock, flags);
0115         sclp_sync_wait();
0116         spin_lock_irqsave(&sclp_con_lock, flags);
0117     }
0118     spin_unlock_irqrestore(&sclp_con_lock, flags);
0119 }
0120 
0121 /*
0122  * When this routine is called from the timer then we flush the
0123  * temporary write buffer without further waiting on a final new line.
0124  */
0125 static void
0126 sclp_console_timeout(struct timer_list *unused)
0127 {
0128     sclp_conbuf_emit();
0129 }
0130 
0131 /*
0132  * Drop oldest console buffer if sclp_con_drop is set
0133  */
0134 static int
0135 sclp_console_drop_buffer(void)
0136 {
0137     struct list_head *list;
0138     struct sclp_buffer *buffer;
0139     void *page;
0140 
0141     if (!sclp_console_drop)
0142         return 0;
0143     list = sclp_con_outqueue.next;
0144     if (sclp_con_queue_running)
0145         /* The first element is in I/O */
0146         list = list->next;
0147     if (list == &sclp_con_outqueue)
0148         return 0;
0149     list_del(list);
0150     buffer = list_entry(list, struct sclp_buffer, list);
0151     page = sclp_unmake_buffer(buffer);
0152     list_add_tail((struct list_head *) page, &sclp_con_pages);
0153     return 1;
0154 }
0155 
0156 /*
0157  * Writes the given message to S390 system console
0158  */
0159 static void
0160 sclp_console_write(struct console *console, const char *message,
0161            unsigned int count)
0162 {
0163     unsigned long flags;
0164     void *page;
0165     int written;
0166 
0167     if (count == 0)
0168         return;
0169     spin_lock_irqsave(&sclp_con_lock, flags);
0170     /*
0171      * process escape characters, write message into buffer,
0172      * send buffer to SCLP
0173      */
0174     do {
0175         /* make sure we have a console output buffer */
0176         if (sclp_conbuf == NULL) {
0177             if (list_empty(&sclp_con_pages))
0178                 sclp_console_full++;
0179             while (list_empty(&sclp_con_pages)) {
0180                 if (sclp_console_drop_buffer())
0181                     break;
0182                 spin_unlock_irqrestore(&sclp_con_lock, flags);
0183                 sclp_sync_wait();
0184                 spin_lock_irqsave(&sclp_con_lock, flags);
0185             }
0186             page = sclp_con_pages.next;
0187             list_del((struct list_head *) page);
0188             sclp_conbuf = sclp_make_buffer(page, SCLP_CON_COLUMNS,
0189                                SPACES_PER_TAB);
0190         }
0191         /* try to write the string to the current output buffer */
0192         written = sclp_write(sclp_conbuf, (const unsigned char *)
0193                      message, count);
0194         if (written == count)
0195             break;
0196         /*
0197          * Not all characters could be written to the current
0198          * output buffer. Emit the buffer, create a new buffer
0199          * and then output the rest of the string.
0200          */
0201         spin_unlock_irqrestore(&sclp_con_lock, flags);
0202         sclp_conbuf_emit();
0203         spin_lock_irqsave(&sclp_con_lock, flags);
0204         message += written;
0205         count -= written;
0206     } while (count > 0);
0207     /* Setup timer to output current console buffer after 1/10 second */
0208     if (sclp_conbuf != NULL && sclp_chars_in_buffer(sclp_conbuf) != 0 &&
0209         !timer_pending(&sclp_con_timer)) {
0210         mod_timer(&sclp_con_timer, jiffies + HZ / 10);
0211     }
0212     spin_unlock_irqrestore(&sclp_con_lock, flags);
0213 }
0214 
0215 static struct tty_driver *
0216 sclp_console_device(struct console *c, int *index)
0217 {
0218     *index = c->index;
0219     return sclp_tty_driver;
0220 }
0221 
0222 /*
0223  * This panic/reboot notifier makes sure that all buffers
0224  * will be flushed to the SCLP.
0225  */
0226 static int sclp_console_notify(struct notifier_block *self,
0227                    unsigned long event, void *data)
0228 {
0229     /*
0230      * Perform the lock check before effectively getting the
0231      * lock on sclp_conbuf_emit() / sclp_console_sync_queue()
0232      * to prevent potential lockups in atomic context.
0233      */
0234     if (spin_is_locked(&sclp_con_lock))
0235         return NOTIFY_DONE;
0236 
0237     sclp_conbuf_emit();
0238     sclp_console_sync_queue();
0239 
0240     return NOTIFY_DONE;
0241 }
0242 
0243 static struct notifier_block on_panic_nb = {
0244     .notifier_call = sclp_console_notify,
0245     .priority = INT_MIN + 1, /* run the callback late */
0246 };
0247 
0248 static struct notifier_block on_reboot_nb = {
0249     .notifier_call = sclp_console_notify,
0250     .priority = INT_MIN + 1, /* run the callback late */
0251 };
0252 
0253 /*
0254  * used to register the SCLP console to the kernel and to
0255  * give printk necessary information
0256  */
0257 static struct console sclp_console =
0258 {
0259     .name = sclp_console_name,
0260     .write = sclp_console_write,
0261     .device = sclp_console_device,
0262     .flags = CON_PRINTBUFFER,
0263     .index = 0 /* ttyS0 */
0264 };
0265 
0266 /*
0267  * called by console_init() in drivers/char/tty_io.c at boot-time.
0268  */
0269 static int __init
0270 sclp_console_init(void)
0271 {
0272     void *page;
0273     int i;
0274     int rc;
0275 
0276     /* SCLP consoles are handled together */
0277     if (!(CONSOLE_IS_SCLP || CONSOLE_IS_VT220))
0278         return 0;
0279     rc = sclp_rw_init();
0280     if (rc)
0281         return rc;
0282     /* Allocate pages for output buffering */
0283     for (i = 0; i < sclp_console_pages; i++) {
0284         page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
0285         list_add_tail(page, &sclp_con_pages);
0286     }
0287     sclp_conbuf = NULL;
0288     timer_setup(&sclp_con_timer, sclp_console_timeout, 0);
0289 
0290     /* enable printk-access to this driver */
0291     atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
0292     register_reboot_notifier(&on_reboot_nb);
0293     register_console(&sclp_console);
0294     return 0;
0295 }
0296 
0297 console_initcall(sclp_console_init);