| From 254c904607a6c4bce6996accff51c8065e8612c6 Mon Sep 17 00:00:00 2001 |
| From: Feng Tang <feng.tang@intel.com> |
| Date: Wed, 3 Oct 2018 00:49:21 +0800 |
| Subject: x86/earlyprintk: Add a force option for pciserial device |
| |
| [ Upstream commit d2266bbfa9e3e32e3b642965088ca461bd24a94f ] |
| |
| The "pciserial" earlyprintk variant helps much on many modern x86 |
| platforms, but unfortunately there are still some platforms with PCI |
| UART devices which have the wrong PCI class code. In that case, the |
| current class code check does not allow for them to be used for logging. |
| |
| Add a sub-option "force" which overrides the class code check and thus |
| the use of such device can be enforced. |
| |
| [ bp: massage formulations. ] |
| |
| Suggested-by: Borislav Petkov <bp@alien8.de> |
| Signed-off-by: Feng Tang <feng.tang@intel.com> |
| Signed-off-by: Borislav Petkov <bp@suse.de> |
| Cc: "H. Peter Anvin" <hpa@zytor.com> |
| Cc: "Stuart R . Anderson" <stuart.r.anderson@intel.com> |
| Cc: Bjorn Helgaas <bhelgaas@google.com> |
| Cc: David Rientjes <rientjes@google.com> |
| Cc: Feng Tang <feng.tang@intel.com> |
| Cc: Frederic Weisbecker <frederic@kernel.org> |
| Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Cc: H Peter Anvin <hpa@linux.intel.com> |
| Cc: Ingo Molnar <mingo@kernel.org> |
| Cc: Jiri Kosina <jkosina@suse.cz> |
| Cc: Jonathan Corbet <corbet@lwn.net> |
| Cc: Kai-Heng Feng <kai.heng.feng@canonical.com> |
| Cc: Kate Stewart <kstewart@linuxfoundation.org> |
| Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> |
| Cc: Peter Zijlstra <peterz@infradead.org> |
| Cc: Philippe Ombredanne <pombredanne@nexb.com> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Cc: Thymo van Beers <thymovanbeers@gmail.com> |
| Cc: alan@linux.intel.com |
| Cc: linux-doc@vger.kernel.org |
| Link: http://lkml.kernel.org/r/20181002164921.25833-1-feng.tang@intel.com |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| .../admin-guide/kernel-parameters.txt | 6 +++- |
| arch/x86/kernel/early_printk.c | 29 ++++++++++++------- |
| 2 files changed, 24 insertions(+), 11 deletions(-) |
| |
| diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt |
| index 92eb1f42240d..34e6800dea0e 100644 |
| --- a/Documentation/admin-guide/kernel-parameters.txt |
| +++ b/Documentation/admin-guide/kernel-parameters.txt |
| @@ -1063,7 +1063,7 @@ |
| earlyprintk=serial[,0x...[,baudrate]] |
| earlyprintk=ttySn[,baudrate] |
| earlyprintk=dbgp[debugController#] |
| - earlyprintk=pciserial,bus:device.function[,baudrate] |
| + earlyprintk=pciserial[,force],bus:device.function[,baudrate] |
| earlyprintk=xdbc[xhciController#] |
| |
| earlyprintk is useful when the kernel crashes before |
| @@ -1095,6 +1095,10 @@ |
| |
| The sclp output can only be used on s390. |
| |
| + The optional "force" to "pciserial" enables use of a |
| + PCI device even when its classcode is not of the |
| + UART class. |
| + |
| edac_report= [HW,EDAC] Control how to report EDAC event |
| Format: {"on" | "off" | "force"} |
| on: enable EDAC to report H/W event. May be overridden |
| diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c |
| index 5e801c8c8ce7..374a52fa5296 100644 |
| --- a/arch/x86/kernel/early_printk.c |
| +++ b/arch/x86/kernel/early_printk.c |
| @@ -213,8 +213,9 @@ static unsigned int mem32_serial_in(unsigned long addr, int offset) |
| * early_pci_serial_init() |
| * |
| * This function is invoked when the early_printk param starts with "pciserial" |
| - * The rest of the param should be ",B:D.F,baud" where B, D & F describe the |
| - * location of a PCI device that must be a UART device. |
| + * The rest of the param should be "[force],B:D.F,baud", where B, D & F describe |
| + * the location of a PCI device that must be a UART device. "force" is optional |
| + * and overrides the use of an UART device with a wrong PCI class code. |
| */ |
| static __init void early_pci_serial_init(char *s) |
| { |
| @@ -224,17 +225,23 @@ static __init void early_pci_serial_init(char *s) |
| u32 classcode, bar0; |
| u16 cmdreg; |
| char *e; |
| + int force = 0; |
| |
| - |
| - /* |
| - * First, part the param to get the BDF values |
| - */ |
| if (*s == ',') |
| ++s; |
| |
| if (*s == 0) |
| return; |
| |
| + /* Force the use of an UART device with wrong class code */ |
| + if (!strncmp(s, "force,", 6)) { |
| + force = 1; |
| + s += 6; |
| + } |
| + |
| + /* |
| + * Part the param to get the BDF values |
| + */ |
| bus = (u8)simple_strtoul(s, &e, 16); |
| s = e; |
| if (*s != ':') |
| @@ -253,7 +260,7 @@ static __init void early_pci_serial_init(char *s) |
| s++; |
| |
| /* |
| - * Second, find the device from the BDF |
| + * Find the device from the BDF |
| */ |
| cmdreg = read_pci_config(bus, slot, func, PCI_COMMAND); |
| classcode = read_pci_config(bus, slot, func, PCI_CLASS_REVISION); |
| @@ -264,8 +271,10 @@ static __init void early_pci_serial_init(char *s) |
| */ |
| if (((classcode >> 16 != PCI_CLASS_COMMUNICATION_MODEM) && |
| (classcode >> 16 != PCI_CLASS_COMMUNICATION_SERIAL)) || |
| - (((classcode >> 8) & 0xff) != 0x02)) /* 16550 I/F at BAR0 */ |
| - return; |
| + (((classcode >> 8) & 0xff) != 0x02)) /* 16550 I/F at BAR0 */ { |
| + if (!force) |
| + return; |
| + } |
| |
| /* |
| * Determine if it is IO or memory mapped |
| @@ -289,7 +298,7 @@ static __init void early_pci_serial_init(char *s) |
| } |
| |
| /* |
| - * Lastly, initialize the hardware |
| + * Initialize the hardware |
| */ |
| if (*s) { |
| if (strcmp(s, "nocfg") == 0) |
| -- |
| 2.17.1 |
| |