1// SPDX-License-Identifier: GPL-2.0 2/* 3 * SCLP line mode console driver 4 * 5 * Copyright IBM Corp. 1999, 2009 6 * Author(s): Martin Peschke <mpeschke@de.ibm.com> 7 * Martin Schwidefsky <schwidefsky@de.ibm.com> 8 */ 9 10#include <linux/kmod.h> 11#include <linux/console.h> 12#include <linux/init.h> 13#include <linux/timer.h> 14#include <linux/jiffies.h> 15#include <linux/termios.h> 16#include <linux/err.h> 17#include <linux/reboot.h> 18#include <linux/gfp.h> 19 20#include "sclp.h" 21#include "sclp_rw.h" 22#include "sclp_tty.h" 23 24#define sclp_console_major 4 /* TTYAUX_MAJOR */ 25#define sclp_console_minor 64 26#define sclp_console_name "ttyS" 27 28/* Lock to guard over changes to global variables */ 29static spinlock_t sclp_con_lock; 30/* List of free pages that can be used for console output buffering */ 31static struct list_head sclp_con_pages; 32/* List of full struct sclp_buffer structures ready for output */ 33static struct list_head sclp_con_outqueue; 34/* Pointer to current console buffer */ 35static struct sclp_buffer *sclp_conbuf; 36/* Timer for delayed output of console messages */ 37static struct timer_list sclp_con_timer; 38/* Suspend mode flag */ 39static int sclp_con_suspended; 40/* Flag that output queue is currently running */ 41static int sclp_con_queue_running; 42 43/* Output format for console messages */ 44static unsigned short sclp_con_columns; 45static unsigned short sclp_con_width_htab; 46 47static void 48sclp_conbuf_callback(struct sclp_buffer *buffer, int rc) 49{ 50 unsigned long flags; 51 void *page; 52 53 do { 54 page = sclp_unmake_buffer(buffer); 55 spin_lock_irqsave(&sclp_con_lock, flags); 56 57 /* Remove buffer from outqueue */ 58 list_del(&buffer->list); 59 list_add_tail((struct list_head *) page, &sclp_con_pages); 60 61 /* Check if there is a pending buffer on the out queue. */ 62 buffer = NULL; 63 if (!list_empty(&sclp_con_outqueue)) 64 buffer = list_first_entry(&sclp_con_outqueue, 65 struct sclp_buffer, list); 66 if (!buffer || sclp_con_suspended) { 67 sclp_con_queue_running = 0; 68 spin_unlock_irqrestore(&sclp_con_lock, flags); 69 break; 70 } 71 spin_unlock_irqrestore(&sclp_con_lock, flags); 72 } while (sclp_emit_buffer(buffer, sclp_conbuf_callback)); 73} 74 75/* 76 * Finalize and emit first pending buffer. 77 */ 78static void sclp_conbuf_emit(void) 79{ 80 struct sclp_buffer* buffer; 81 unsigned long flags; 82 int rc; 83 84 spin_lock_irqsave(&sclp_con_lock, flags); 85 if (sclp_conbuf) 86 list_add_tail(&sclp_conbuf->list, &sclp_con_outqueue); 87 sclp_conbuf = NULL; 88 if (sclp_con_queue_running || sclp_con_suspended) 89 goto out_unlock; 90 if (list_empty(&sclp_con_outqueue)) 91 goto out_unlock; 92 buffer = list_first_entry(&sclp_con_outqueue, struct sclp_buffer, 93 list); 94 sclp_con_queue_running = 1; 95 spin_unlock_irqrestore(&sclp_con_lock, flags); 96 97 rc = sclp_emit_buffer(buffer, sclp_conbuf_callback); 98 if (rc) 99 sclp_conbuf_callback(buffer, rc); 100 return; 101out_unlock: 102 spin_unlock_irqrestore(&sclp_con_lock, flags); 103} 104 105/* 106 * Wait until out queue is empty 107 */ 108static void sclp_console_sync_queue(void) 109{ 110 unsigned long flags; 111 112 spin_lock_irqsave(&sclp_con_lock, flags); 113 if (timer_pending(&sclp_con_timer)) 114 del_timer(&sclp_con_timer); 115 while (sclp_con_queue_running) { 116 spin_unlock_irqrestore(&sclp_con_lock, flags); 117 sclp_sync_wait(); 118 spin_lock_irqsave(&sclp_con_lock, flags); 119 } 120 spin_unlock_irqrestore(&sclp_con_lock, flags); 121} 122 123/* 124 * When this routine is called from the timer then we flush the 125 * temporary write buffer without further waiting on a final new line. 126 */ 127static void 128sclp_console_timeout(struct timer_list *unused) 129{ 130 sclp_conbuf_emit(); 131} 132 133/* 134 * Drop oldest console buffer if sclp_con_drop is set 135 */ 136static int 137sclp_console_drop_buffer(void) 138{ 139 struct list_head *list; 140 struct sclp_buffer *buffer; 141 void *page; 142 143 if (!sclp_console_drop) 144 return 0; 145 list = sclp_con_outqueue.next; 146 if (sclp_con_queue_running) 147 /* The first element is in I/O */ 148 list = list->next; 149 if (list == &sclp_con_outqueue) 150 return 0; 151 list_del(list); 152 buffer = list_entry(list, struct sclp_buffer, list); 153 page = sclp_unmake_buffer(buffer); 154 list_add_tail((struct list_head *) page, &sclp_con_pages); 155 return 1; 156} 157 158/* 159 * Writes the given message to S390 system console 160 */ 161static void 162sclp_console_write(struct console *console, const char *message, 163 unsigned int count) 164{ 165 unsigned long flags; 166 void *page; 167 int written; 168 169 if (count == 0) 170 return; 171 spin_lock_irqsave(&sclp_con_lock, flags); 172 /* 173 * process escape characters, write message into buffer, 174 * send buffer to SCLP 175 */ 176 do { 177 /* make sure we have a console output buffer */ 178 if (sclp_conbuf == NULL) { 179 if (list_empty(&sclp_con_pages)) 180 sclp_console_full++; 181 while (list_empty(&sclp_con_pages)) { 182 if (sclp_con_suspended) 183 goto out; 184 if (sclp_console_drop_buffer()) 185 break; 186 spin_unlock_irqrestore(&sclp_con_lock, flags); 187 sclp_sync_wait(); 188 spin_lock_irqsave(&sclp_con_lock, flags); 189 } 190 page = sclp_con_pages.next; 191 list_del((struct list_head *) page); 192 sclp_conbuf = sclp_make_buffer(page, sclp_con_columns, 193 sclp_con_width_htab); 194 } 195 /* try to write the string to the current output buffer */ 196 written = sclp_write(sclp_conbuf, (const unsigned char *) 197 message, count); 198 if (written == count) 199 break; 200 /* 201 * Not all characters could be written to the current 202 * output buffer. Emit the buffer, create a new buffer 203 * and then output the rest of the string. 204 */ 205 spin_unlock_irqrestore(&sclp_con_lock, flags); 206 sclp_conbuf_emit(); 207 spin_lock_irqsave(&sclp_con_lock, flags); 208 message += written; 209 count -= written; 210 } while (count > 0); 211 /* Setup timer to output current console buffer after 1/10 second */ 212 if (sclp_conbuf != NULL && sclp_chars_in_buffer(sclp_conbuf) != 0 && 213 !timer_pending(&sclp_con_timer)) { 214 mod_timer(&sclp_con_timer, jiffies + HZ / 10); 215 } 216out: 217 spin_unlock_irqrestore(&sclp_con_lock, flags); 218} 219 220static struct tty_driver * 221sclp_console_device(struct console *c, int *index) 222{ 223 *index = c->index; 224 return sclp_tty_driver; 225} 226 227/* 228 * Make sure that all buffers will be flushed to the SCLP. 229 */ 230static void 231sclp_console_flush(void) 232{ 233 sclp_conbuf_emit(); 234 sclp_console_sync_queue(); 235} 236 237/* 238 * Resume console: If there are cached messages, emit them. 239 */ 240static void sclp_console_resume(void) 241{ 242 unsigned long flags; 243 244 spin_lock_irqsave(&sclp_con_lock, flags); 245 sclp_con_suspended = 0; 246 spin_unlock_irqrestore(&sclp_con_lock, flags); 247 sclp_conbuf_emit(); 248} 249 250/* 251 * Suspend console: Set suspend flag and flush console 252 */ 253static void sclp_console_suspend(void) 254{ 255 unsigned long flags; 256 257 spin_lock_irqsave(&sclp_con_lock, flags); 258 sclp_con_suspended = 1; 259 spin_unlock_irqrestore(&sclp_con_lock, flags); 260 sclp_console_flush(); 261} 262 263static int sclp_console_notify(struct notifier_block *self, 264 unsigned long event, void *data) 265{ 266 sclp_console_flush(); 267 return NOTIFY_OK; 268} 269 270static struct notifier_block on_panic_nb = { 271 .notifier_call = sclp_console_notify, 272 .priority = SCLP_PANIC_PRIO_CLIENT, 273}; 274 275static struct notifier_block on_reboot_nb = { 276 .notifier_call = sclp_console_notify, 277 .priority = 1, 278}; 279 280/* 281 * used to register the SCLP console to the kernel and to 282 * give printk necessary information 283 */ 284static struct console sclp_console = 285{ 286 .name = sclp_console_name, 287 .write = sclp_console_write, 288 .device = sclp_console_device, 289 .flags = CON_PRINTBUFFER, 290 .index = 0 /* ttyS0 */ 291}; 292 293/* 294 * This function is called for SCLP suspend and resume events. 295 */ 296void sclp_console_pm_event(enum sclp_pm_event sclp_pm_event) 297{ 298 switch (sclp_pm_event) { 299 case SCLP_PM_EVENT_FREEZE: 300 sclp_console_suspend(); 301 break; 302 case SCLP_PM_EVENT_RESTORE: 303 case SCLP_PM_EVENT_THAW: 304 sclp_console_resume(); 305 break; 306 } 307} 308 309/* 310 * called by console_init() in drivers/char/tty_io.c at boot-time. 311 */ 312static int __init 313sclp_console_init(void) 314{ 315 void *page; 316 int i; 317 int rc; 318 319 /* SCLP consoles are handled together */ 320 if (!(CONSOLE_IS_SCLP || CONSOLE_IS_VT220)) 321 return 0; 322 rc = sclp_rw_init(); 323 if (rc) 324 return rc; 325 /* Allocate pages for output buffering */ 326 INIT_LIST_HEAD(&sclp_con_pages); 327 for (i = 0; i < sclp_console_pages; i++) { 328 page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); 329 list_add_tail(page, &sclp_con_pages); 330 } 331 INIT_LIST_HEAD(&sclp_con_outqueue); 332 spin_lock_init(&sclp_con_lock); 333 sclp_conbuf = NULL; 334 timer_setup(&sclp_con_timer, sclp_console_timeout, 0); 335 336 /* Set output format */ 337 if (MACHINE_IS_VM) 338 /* 339 * save 4 characters for the CPU number 340 * written at start of each line by VM/CP 341 */ 342 sclp_con_columns = 76; 343 else 344 sclp_con_columns = 80; 345 sclp_con_width_htab = 8; 346 347 /* enable printk-access to this driver */ 348 atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb); 349 register_reboot_notifier(&on_reboot_nb); 350 register_console(&sclp_console); 351 return 0; 352} 353 354console_initcall(sclp_console_init); 355