mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-23 09:56:00 +00:00
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>
This commit is contained in:
parent
92057a493a
commit
d1cfc0ce5d
@ -230,6 +230,69 @@ static const struct hv_ops hvterm_hvsi_ops = {
|
|||||||
.tiocmset = hvterm_hvsi_tiocmset,
|
.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,
|
static int __devinit hvc_vio_probe(struct vio_dev *vdev,
|
||||||
const struct vio_device_id *id)
|
const struct vio_device_id *id)
|
||||||
{
|
{
|
||||||
@ -289,6 +352,13 @@ static int __devinit hvc_vio_probe(struct vio_dev *vdev,
|
|||||||
return PTR_ERR(hp);
|
return PTR_ERR(hp);
|
||||||
dev_set_drvdata(&vdev->dev, 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,59 +401,6 @@ static void __exit hvc_vio_exit(void)
|
|||||||
}
|
}
|
||||||
module_exit(hvc_vio_exit);
|
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)
|
void __init hvc_vio_init_early(void)
|
||||||
{
|
{
|
||||||
struct device_node *stdout_node;
|
struct device_node *stdout_node;
|
||||||
|
Loading…
Reference in New Issue
Block a user