Merge branch 'linus' into core/objtool, to pick up dependent commits
[sfrench/cifs-2.6.git] / drivers / s390 / char / sclp_con.c
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 */
29 static spinlock_t sclp_con_lock;
30 /* List of free pages that can be used for console output buffering */
31 static struct list_head sclp_con_pages;
32 /* List of full struct sclp_buffer structures ready for output */
33 static struct list_head sclp_con_outqueue;
34 /* Pointer to current console buffer */
35 static struct sclp_buffer *sclp_conbuf;
36 /* Timer for delayed output of console messages */
37 static struct timer_list sclp_con_timer;
38 /* Suspend mode flag */
39 static int sclp_con_suspended;
40 /* Flag that output queue is currently running */
41 static int sclp_con_queue_running;
42
43 /* Output format for console messages */
44 static unsigned short sclp_con_columns;
45 static unsigned short sclp_con_width_htab;
46
47 static void
48 sclp_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  */
78 static 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;
101 out_unlock:
102         spin_unlock_irqrestore(&sclp_con_lock, flags);
103 }
104
105 /*
106  * Wait until out queue is empty
107  */
108 static 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  */
127 static void
128 sclp_console_timeout(unsigned long data)
129 {
130         sclp_conbuf_emit();
131 }
132
133 /*
134  * Drop oldest console buffer if sclp_con_drop is set
135  */
136 static int
137 sclp_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  */
161 static void
162 sclp_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                 setup_timer(&sclp_con_timer, sclp_console_timeout, 0UL);
215                 mod_timer(&sclp_con_timer, jiffies + HZ / 10);
216         }
217 out:
218         spin_unlock_irqrestore(&sclp_con_lock, flags);
219 }
220
221 static struct tty_driver *
222 sclp_console_device(struct console *c, int *index)
223 {
224         *index = c->index;
225         return sclp_tty_driver;
226 }
227
228 /*
229  * Make sure that all buffers will be flushed to the SCLP.
230  */
231 static void
232 sclp_console_flush(void)
233 {
234         sclp_conbuf_emit();
235         sclp_console_sync_queue();
236 }
237
238 /*
239  * Resume console: If there are cached messages, emit them.
240  */
241 static void sclp_console_resume(void)
242 {
243         unsigned long flags;
244
245         spin_lock_irqsave(&sclp_con_lock, flags);
246         sclp_con_suspended = 0;
247         spin_unlock_irqrestore(&sclp_con_lock, flags);
248         sclp_conbuf_emit();
249 }
250
251 /*
252  * Suspend console: Set suspend flag and flush console
253  */
254 static void sclp_console_suspend(void)
255 {
256         unsigned long flags;
257
258         spin_lock_irqsave(&sclp_con_lock, flags);
259         sclp_con_suspended = 1;
260         spin_unlock_irqrestore(&sclp_con_lock, flags);
261         sclp_console_flush();
262 }
263
264 static int sclp_console_notify(struct notifier_block *self,
265                                unsigned long event, void *data)
266 {
267         sclp_console_flush();
268         return NOTIFY_OK;
269 }
270
271 static struct notifier_block on_panic_nb = {
272         .notifier_call = sclp_console_notify,
273         .priority = SCLP_PANIC_PRIO_CLIENT,
274 };
275
276 static struct notifier_block on_reboot_nb = {
277         .notifier_call = sclp_console_notify,
278         .priority = 1,
279 };
280
281 /*
282  * used to register the SCLP console to the kernel and to
283  * give printk necessary information
284  */
285 static struct console sclp_console =
286 {
287         .name = sclp_console_name,
288         .write = sclp_console_write,
289         .device = sclp_console_device,
290         .flags = CON_PRINTBUFFER,
291         .index = 0 /* ttyS0 */
292 };
293
294 /*
295  * This function is called for SCLP suspend and resume events.
296  */
297 void sclp_console_pm_event(enum sclp_pm_event sclp_pm_event)
298 {
299         switch (sclp_pm_event) {
300         case SCLP_PM_EVENT_FREEZE:
301                 sclp_console_suspend();
302                 break;
303         case SCLP_PM_EVENT_RESTORE:
304         case SCLP_PM_EVENT_THAW:
305                 sclp_console_resume();
306                 break;
307         }
308 }
309
310 /*
311  * called by console_init() in drivers/char/tty_io.c at boot-time.
312  */
313 static int __init
314 sclp_console_init(void)
315 {
316         void *page;
317         int i;
318         int rc;
319
320         /* SCLP consoles are handled together */
321         if (!(CONSOLE_IS_SCLP || CONSOLE_IS_VT220))
322                 return 0;
323         rc = sclp_rw_init();
324         if (rc)
325                 return rc;
326         /* Allocate pages for output buffering */
327         INIT_LIST_HEAD(&sclp_con_pages);
328         for (i = 0; i < sclp_console_pages; i++) {
329                 page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
330                 list_add_tail(page, &sclp_con_pages);
331         }
332         INIT_LIST_HEAD(&sclp_con_outqueue);
333         spin_lock_init(&sclp_con_lock);
334         sclp_conbuf = NULL;
335         init_timer(&sclp_con_timer);
336
337         /* Set output format */
338         if (MACHINE_IS_VM)
339                 /*
340                  * save 4 characters for the CPU number
341                  * written at start of each line by VM/CP
342                  */
343                 sclp_con_columns = 76;
344         else
345                 sclp_con_columns = 80;
346         sclp_con_width_htab = 8;
347
348         /* enable printk-access to this driver */
349         atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
350         register_reboot_notifier(&on_reboot_nb);
351         register_console(&sclp_console);
352         return 0;
353 }
354
355 console_initcall(sclp_console_init);