Skip to content

Commit

Permalink
hvc_vio: Improve registration of udbg backend
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Benjamin Herrenschmidt committed Sep 5, 2012
1 parent 92057a4 commit d1cfc0c
Showing 1 changed file with 70 additions and 53 deletions.
123 changes: 70 additions & 53 deletions drivers/tty/hvc/hvc_vio.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,69 @@ static const struct hv_ops hvterm_hvsi_ops = {
.tiocmset = hvterm_hvsi_tiocmset,
};

static void udbg_hvc_putc(char c)
{
int count = -1;

if (!hvterm_privs[0])
return;

if (c == '\n')
udbg_hvc_putc('\r');

do {
switch(hvterm_privs[0]->proto) {
case HV_PROTOCOL_RAW:
count = hvterm_raw_put_chars(0, &c, 1);
break;
case HV_PROTOCOL_HVSI:
count = hvterm_hvsi_put_chars(0, &c, 1);
break;
}
} while(count == 0);
}

static int udbg_hvc_getc_poll(void)
{
int rc = 0;
char c;

if (!hvterm_privs[0])
return -1;

switch(hvterm_privs[0]->proto) {
case HV_PROTOCOL_RAW:
rc = hvterm_raw_get_chars(0, &c, 1);
break;
case HV_PROTOCOL_HVSI:
rc = hvterm_hvsi_get_chars(0, &c, 1);
break;
}
if (!rc)
return -1;
return c;
}

static int udbg_hvc_getc(void)
{
int ch;

if (!hvterm_privs[0])
return -1;

for (;;) {
ch = udbg_hvc_getc_poll();
if (ch == -1) {
/* This shouldn't be needed...but... */
volatile unsigned long delay;
for (delay=0; delay < 2000000; delay++)
;
} else {
return ch;
}
}
}

static int __devinit hvc_vio_probe(struct vio_dev *vdev,
const struct vio_device_id *id)
{
Expand Down Expand Up @@ -289,6 +352,13 @@ static int __devinit hvc_vio_probe(struct vio_dev *vdev,
return PTR_ERR(hp);
dev_set_drvdata(&vdev->dev, hp);

/* register udbg if it's not there already for console 0 */
if (hp->index == 0 && !udbg_putc) {
udbg_putc = udbg_hvc_putc;
udbg_getc = udbg_hvc_getc;
udbg_getc_poll = udbg_hvc_getc_poll;
}

return 0;
}

Expand Down Expand Up @@ -331,59 +401,6 @@ static void __exit hvc_vio_exit(void)
}
module_exit(hvc_vio_exit);

static void udbg_hvc_putc(char c)
{
int count = -1;

if (c == '\n')
udbg_hvc_putc('\r');

do {
switch(hvterm_priv0.proto) {
case HV_PROTOCOL_RAW:
count = hvterm_raw_put_chars(0, &c, 1);
break;
case HV_PROTOCOL_HVSI:
count = hvterm_hvsi_put_chars(0, &c, 1);
break;
}
} while(count == 0);
}

static int udbg_hvc_getc_poll(void)
{
int rc = 0;
char c;

switch(hvterm_priv0.proto) {
case HV_PROTOCOL_RAW:
rc = hvterm_raw_get_chars(0, &c, 1);
break;
case HV_PROTOCOL_HVSI:
rc = hvterm_hvsi_get_chars(0, &c, 1);
break;
}
if (!rc)
return -1;
return c;
}

static int udbg_hvc_getc(void)
{
int ch;
for (;;) {
ch = udbg_hvc_getc_poll();
if (ch == -1) {
/* This shouldn't be needed...but... */
volatile unsigned long delay;
for (delay=0; delay < 2000000; delay++)
;
} else {
return ch;
}
}
}

void __init hvc_vio_init_early(void)
{
struct device_node *stdout_node;
Expand Down

0 comments on commit d1cfc0c

Please sign in to comment.