aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-07-23 17:47:38 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-09-05 01:19:35 -0400
commitd1cfc0ce5d3196ccd88b9d868bb7cbcab61e0a31 (patch)
tree9fd474a14beb679b2e50776e33aeecae8a8740ff /drivers/tty
parent92057a493af4bb56928a762ad0423200b835d995 (diff)
hvc_vio: Improve registration of udbg backend
The pseries hvterm driver only registers a udbg backend (for xmon and other low level debugging mechanisms) when hvc0 is recognized as the firmware console at boot time, not if it's detected later on, for example because the firmware is using a graphics card. This can make debugging challenging especially under X11, and there's really no good reason for that limitation, so let's hookup udbg whenever hvc0 is detected instead. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/hvc/hvc_vio.c123
1 files changed, 70 insertions, 53 deletions
diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c
index ee307799271a..070c0ee68642 100644
--- a/drivers/tty/hvc/hvc_vio.c
+++ b/drivers/tty/hvc/hvc_vio.c
@@ -230,6 +230,69 @@ static const struct hv_ops hvterm_hvsi_ops = {
230 .tiocmset = hvterm_hvsi_tiocmset, 230 .tiocmset = hvterm_hvsi_tiocmset,
231}; 231};
232 232
233static void udbg_hvc_putc(char c)
234{
235 int count = -1;
236
237 if (!hvterm_privs[0])
238 return;
239
240 if (c == '\n')
241 udbg_hvc_putc('\r');
242
243 do {
244 switch(hvterm_privs[0]->proto) {
245 case HV_PROTOCOL_RAW:
246 count = hvterm_raw_put_chars(0, &c, 1);
247 break;
248 case HV_PROTOCOL_HVSI:
249 count = hvterm_hvsi_put_chars(0, &c, 1);
250 break;
251 }
252 } while(count == 0);
253}
254
255static int udbg_hvc_getc_poll(void)
256{
257 int rc = 0;
258 char c;
259
260 if (!hvterm_privs[0])
261 return -1;
262
263 switch(hvterm_privs[0]->proto) {
264 case HV_PROTOCOL_RAW:
265 rc = hvterm_raw_get_chars(0, &c, 1);
266 break;
267 case HV_PROTOCOL_HVSI:
268 rc = hvterm_hvsi_get_chars(0, &c, 1);
269 break;
270 }
271 if (!rc)
272 return -1;
273 return c;
274}
275
276static int udbg_hvc_getc(void)
277{
278 int ch;
279
280 if (!hvterm_privs[0])
281 return -1;
282
283 for (;;) {
284 ch = udbg_hvc_getc_poll();
285 if (ch == -1) {
286 /* This shouldn't be needed...but... */
287 volatile unsigned long delay;
288 for (delay=0; delay < 2000000; delay++)
289 ;
290 } else {
291 return ch;
292 }
293 }
294}
295
233static int __devinit hvc_vio_probe(struct vio_dev *vdev, 296static int __devinit hvc_vio_probe(struct vio_dev *vdev,
234 const struct vio_device_id *id) 297 const struct vio_device_id *id)
235{ 298{
@@ -289,6 +352,13 @@ static int __devinit hvc_vio_probe(struct vio_dev *vdev,
289 return PTR_ERR(hp); 352 return PTR_ERR(hp);
290 dev_set_drvdata(&vdev->dev, hp); 353 dev_set_drvdata(&vdev->dev, hp);
291 354
355 /* register udbg if it's not there already for console 0 */
356 if (hp->index == 0 && !udbg_putc) {
357 udbg_putc = udbg_hvc_putc;
358 udbg_getc = udbg_hvc_getc;
359 udbg_getc_poll = udbg_hvc_getc_poll;
360 }
361
292 return 0; 362 return 0;
293} 363}
294 364
@@ -331,59 +401,6 @@ static void __exit hvc_vio_exit(void)
331} 401}
332module_exit(hvc_vio_exit); 402module_exit(hvc_vio_exit);
333 403
334static void udbg_hvc_putc(char c)
335{
336 int count = -1;
337
338 if (c == '\n')
339 udbg_hvc_putc('\r');
340
341 do {
342 switch(hvterm_priv0.proto) {
343 case HV_PROTOCOL_RAW:
344 count = hvterm_raw_put_chars(0, &c, 1);
345 break;
346 case HV_PROTOCOL_HVSI:
347 count = hvterm_hvsi_put_chars(0, &c, 1);
348 break;
349 }
350 } while(count == 0);
351}
352
353static int udbg_hvc_getc_poll(void)
354{
355 int rc = 0;
356 char c;
357
358 switch(hvterm_priv0.proto) {
359 case HV_PROTOCOL_RAW:
360 rc = hvterm_raw_get_chars(0, &c, 1);
361 break;
362 case HV_PROTOCOL_HVSI:
363 rc = hvterm_hvsi_get_chars(0, &c, 1);
364 break;
365 }
366 if (!rc)
367 return -1;
368 return c;
369}
370
371static int udbg_hvc_getc(void)
372{
373 int ch;
374 for (;;) {
375 ch = udbg_hvc_getc_poll();
376 if (ch == -1) {
377 /* This shouldn't be needed...but... */
378 volatile unsigned long delay;
379 for (delay=0; delay < 2000000; delay++)
380 ;
381 } else {
382 return ch;
383 }
384 }
385}
386
387void __init hvc_vio_init_early(void) 404void __init hvc_vio_init_early(void)
388{ 405{
389 struct device_node *stdout_node; 406 struct device_node *stdout_node;