* [PATCH 0/7] sparc64: add Fujitsu M3000 support @ 2026-10-02 16:14 Magnus Lindholm 2026-10-02 16:14 ` [PATCH 7/7] hvc: add an M3000 firmware console backend Magnus Lindholm 0 siblings, 1 reply; 5+ messages in thread From: Magnus Lindholm @ 2026-10-02 16:14 UTC (permalink / raw) To: sparclinux, David S . Miller, Andreas Larsson Cc: linux-kernel, Magnus Lindholm, netdev, linux-serial Several years ago I salvaged an M3000 SPARC Enterprise box being decommissioned at work. The box has been sitting ever since, it did not run Linux. It did not seem impossible to get Linux running but my earlier attempts failed. I recently found some documentation; "SPARC JPS2: Common Specification" and the "Fujitsu SPARC64 II Extensions", which gave me some of the missingpieces. Getting this up and running required extensive testing, some kernel instrumentation, debug printouts and many reboot iterations. For thisi, Codex proved very helpful. Along the way, I stumbled upon some generic sparc and driver bugs that this series addresses as well. This series adds support for the Fujitsu SPARC Enterprise M3000, with SPARC64 VII+, Oberon PCIe, BCM5718 networking and a firmware hvc console. It applies to Linux v7.3-rc1, base cee9395acd8043be0644b25c34bfa86623f2b935. Patches 1-3 fix existing sparc64 defects in generic clear_page, secondary queued-spinlock acquisition and sun4u kernel huge-PUD mappings. Each has a Fixes tag. Patches 4-7 add the CPU/MMU/SMP path, PCIe bridge, narrowly matched tg3 firmware-state correction and console. They form one series so the complete port can be built without collecting prerequisites. VII context-write and demap synchronization follows the cited JPS2 and SPARC64 VII manual sections. Existing Cheetah routines are unchanged: similar assembly does not establish the same hardware requirement there. The final tree includes the demap-all instruction synchronization in the CPU/MMU patch. All seven cumulative prefixes build. The exact final image boots Gentoo/OpenRC and SSH with eight threads; kernel taint is zero. HugeTLB/THP, CPU offlining, Oberon MSI and complete RAS recovery remain unsupported. Firmware console calls cannot be bounded if firmware stalls. SPARC64 VII/VII+ support is currently opt-in through Kconfig while the new CPU/MMU/SMP paths receive broader testing. The option also excludes HugeTLB and THP configurations, which this implementation does not yet support. The longer-term aim is to rely on runtime CPU detection once unsupported huge-page configurations can be handled safely. Magnus Lindholm (7): sparc64: return from the generic clear_page implementation sparc64: honor queued spinlock layout in secondary startup sparc64: avoid huge kernel PUD mappings on sun4u sparc64: add SPARC64 VII CPU, MMU and SMP support sparc64: add M3000 Oberon PCIe support tg3: normalize inherited M3000 register byte order hvc: add an M3000 firmware console backend MAINTAINERS | 6 + arch/sparc/Kconfig | 19 +++ arch/sparc/include/asm/head_64.h | 15 ++ arch/sparc/include/asm/iommu_64.h | 1 + arch/sparc/include/asm/irq_64.h | 1 + arch/sparc/include/asm/setup.h | 5 + arch/sparc/include/asm/smp_64.h | 4 + arch/sparc/include/asm/spitfire.h | 1 + arch/sparc/include/asm/trap_block.h | 6 + arch/sparc/kernel/cpu.c | 3 + arch/sparc/kernel/entry.h | 2 + arch/sparc/kernel/head_64.S | 18 +++ arch/sparc/kernel/helpers.S | 41 +++++ arch/sparc/kernel/iommu.c | 44 ++++++ arch/sparc/kernel/irq_64.c | 50 ++++-- arch/sparc/kernel/pci_fire.c | 31 +++- arch/sparc/kernel/pci_impl.h | 1 + arch/sparc/kernel/prom_64.c | 6 + arch/sparc/kernel/prom_irqtrans.c | 7 + arch/sparc/kernel/ptrace_64.c | 7 + arch/sparc/kernel/setup_64.c | 55 +++++++ arch/sparc/kernel/smp_64.c | 82 +++++++++- arch/sparc/kernel/trampoline_64.S | 53 ++++++- arch/sparc/kernel/traps_64.c | 27 ++++ arch/sparc/lib/GENpage.S | 3 + arch/sparc/mm/init_64.c | 110 ++++++++++++- arch/sparc/mm/tsb.c | 19 ++- arch/sparc/mm/ultra.S | 236 ++++++++++++++++++++++++++++ drivers/net/ethernet/broadcom/tg3.c | 91 ++++++++++- drivers/tty/hvc/Kconfig | 10 ++ drivers/tty/hvc/Makefile | 2 + drivers/tty/hvc/hvc_m3000.c | 167 ++++++++++++++++++++ 32 files changed, 1088 insertions(+), 35 deletions(-) create mode 100644 drivers/tty/hvc/hvc_m3000.c base-commit: cee9395acd8043be0644b25c34bfa86623f2b935 -- 2.43.0 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 7/7] hvc: add an M3000 firmware console backend 2026-10-02 16:14 [PATCH 0/7] sparc64: add Fujitsu M3000 support Magnus Lindholm @ 2026-10-02 16:14 ` Magnus Lindholm 2026-10-03 17:56 ` sashiko-bot 2026-10-04 12:50 ` Greg Kroah-Hartman 0 siblings, 2 replies; 5+ messages in thread From: Magnus Lindholm @ 2026-10-02 16:14 UTC (permalink / raw) To: sparclinux, David S . Miller, Andreas Larsson Cc: linux-kernel, Magnus Lindholm, Greg Kroah-Hartman, Jiri Slaby, linuxppc-dev, linux-serial Provide hvc0 through the IKKAKU Open Firmware pseudo-console, validating model and console properties before matching. Serialize firmware calls, keep the bounce buffer in locked mappings and poll input each open tick. Keep output buffers const and bound no-progress retries because HVC retries EAGAIN indefinitely. A stalled firmware call remains unbounded. Use the existing SPARC p1275 interface and HVC output contract. Signed-off-by: Magnus Lindholm <linmag7@gmail.com> --- MAINTAINERS | 6 ++ drivers/tty/hvc/Kconfig | 10 +++ drivers/tty/hvc/Makefile | 2 + drivers/tty/hvc/hvc_m3000.c | 167 ++++++++++++++++++++++++++++++++++++ 4 files changed, 185 insertions(+) create mode 100644 drivers/tty/hvc/hvc_m3000.c diff --git a/MAINTAINERS b/MAINTAINERS index 3a19da74d00c..5bc9b1cabd0a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10728,6 +10728,12 @@ L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/fujitsu-laptop.c +FUJITSU M3000 FIRMWARE CONSOLE +M: Magnus Lindholm <linmag7@gmail.com> +L: linux-serial@vger.kernel.org +S: Maintained +F: drivers/tty/hvc/hvc_m3000.c + FUJITSU TABLET EXTRAS M: Robert Gerlach <khnz@gmx.de> L: platform-driver-x86@vger.kernel.org diff --git a/drivers/tty/hvc/Kconfig b/drivers/tty/hvc/Kconfig index 5866195de26a..0feb7ec98f4f 100644 --- a/drivers/tty/hvc/Kconfig +++ b/drivers/tty/hvc/Kconfig @@ -134,3 +134,13 @@ config HVCS will depend on arch specific APIs exported from hvcserver.ko which will also be compiled when this driver is built as a module. + +config HVC_M3000 + bool "M3000 firmware pseudo-console" + depends on SPARC64_VII + select HVC_DRIVER + help + Provide hvc0 using Open Firmware stdin/stdout on IKKAKU only. + Input is polled; no native UART registers are accessed. + Firmware calls are serialized and use a locked-image bounce buffer. + Say Y to use the M3000 firmware pseudo-console as hvc0. diff --git a/drivers/tty/hvc/Makefile b/drivers/tty/hvc/Makefile index 98880e357941..5b0277deb7c9 100644 --- a/drivers/tty/hvc/Makefile +++ b/drivers/tty/hvc/Makefile @@ -11,3 +11,5 @@ obj-$(CONFIG_HVC_IUCV) += hvc_iucv.o obj-$(CONFIG_HVC_UDBG) += hvc_udbg.o obj-$(CONFIG_HVC_RISCV_SBI) += hvc_riscv_sbi.o obj-$(CONFIG_HVCS) += hvcs.o + +obj-$(CONFIG_HVC_M3000) += hvc_m3000.o diff --git a/drivers/tty/hvc/hvc_m3000.c b/drivers/tty/hvc/hvc_m3000.c new file mode 100644 index 000000000000..0ef4c888a6a2 --- /dev/null +++ b/drivers/tty/hvc/hvc_m3000.c @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Experimental M3000 Open Firmware pseudo-console backend. */ +#include <linux/console.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/irqflags.h> +#include <linux/string.h> +#include <linux/spinlock.h> +#include <linux/timer.h> +#include <asm/oplib.h> +#include <asm/spitfire.h> +#include "hvc_console.h" + +#define M3000_WRITE_ATTEMPTS 8 + +static int m3000_stdin; +static bool m3000_ready; +/* Keep firmware buffers within the locked kernel image mappings. */ +static u8 m3000_buffer[256]; +static DEFINE_RAW_SPINLOCK(m3000_buffer_lock); +static struct timer_list m3000_poll_timer; +static bool m3000_poll_active; + +/* + * HVC's idle backoff can exceed the firmware input FIFO's capacity. + * Wake its worker each tick while open; keep PROM calls out of the timer. + */ +static void m3000_poll_tick(struct timer_list *timer) +{ + if (!READ_ONCE(m3000_poll_active)) + return; + hvc_kick(); + mod_timer(&m3000_poll_timer, jiffies + 1); +} + +static int m3000_open(struct hvc_struct *hp, int data) +{ + WRITE_ONCE(m3000_poll_active, true); + mod_timer(&m3000_poll_timer, jiffies + 1); + return 0; +} + +static void m3000_close(struct hvc_struct *hp, int data) +{ + WRITE_ONCE(m3000_poll_active, false); + timer_delete_sync(&m3000_poll_timer); +} + +static ssize_t m3000_io(u8 *in, const u8 *out, size_t count) +{ + unsigned long args[7], flags; + bool input = in != NULL; + int ret; + + if (!count) + return 0; + count = min_t(size_t, count, input ? 1 : sizeof(m3000_buffer)); + /* Serialize the bounce buffer; p1275 separately serializes firmware. */ + raw_spin_lock_irqsave(&m3000_buffer_lock, flags); + if (!input) + memcpy(m3000_buffer, out, count); + args[0] = (unsigned long)(input ? "read" : "write"); + args[1] = 3; + args[2] = 1; + args[3] = (unsigned int)(input ? m3000_stdin : prom_stdout); + args[4] = (unsigned long)m3000_buffer; + args[5] = count; + args[6] = (unsigned long)-1; + p1275_cmd_direct(args); + ret = (int)args[6]; + if (ret > 0 && ret <= count && input) + memcpy(in, m3000_buffer, ret); + raw_spin_unlock_irqrestore(&m3000_buffer_lock, flags); + if (ret == -2 || ret == 0) + return input ? 0 : -EAGAIN; + if (ret < 0 || ret > count) + return -EIO; + return ret; +} + +static ssize_t m3000_get(u32 termno, u8 *buf, size_t count) +{ + return m3000_io(buf, NULL, count); +} + +static ssize_t m3000_put(u32 termno, const u8 *buf, size_t count) +{ + ssize_t ret; + int attempt; + + /* + * HVC retries -EAGAIN forever, so drop this chunk without logging when + * the no-progress budget expires. This cannot bound a stalled firmware + * call or lock acquisition. + */ + for (attempt = 0; attempt < M3000_WRITE_ATTEMPTS; attempt++) { + ret = m3000_io(NULL, buf, count); + if (ret != -EAGAIN) + return ret; + cpu_relax(); + } + return -EIO; +} + +static const struct hv_ops m3000_ops = { + .get_chars = m3000_get, + .put_chars = m3000_put, + .notifier_add = m3000_open, + .notifier_del = m3000_close, + .notifier_hangup = m3000_close, +}; + +static bool __init m3000_property_matches(phandle node, const char *prop, + const char *expected) +{ + char value[64]; + int len; + + len = prom_getproperty(node, prop, value, sizeof(value) - 1); + if (len <= 0) + return false; + value[len] = '\0'; + return !strcmp(value, expected); +} + +static int __init m3000_console_init(void) +{ + phandle node; + int ret; + + if (tlb_type != sparc64_vii) + return -ENODEV; + if (!m3000_property_matches(prom_finddevice("/"), "model", "IKKAKU")) + return -ENODEV; + m3000_stdin = prom_getint(prom_chosen_node, "stdin"); + if (!m3000_stdin || m3000_stdin == -1 || !prom_stdout || prom_stdout == -1) + return -ENODEV; + node = prom_inst2pkg(prom_stdout); + if (!m3000_property_matches(node, "name", "pseudo-console")) + return -ENODEV; + node = prom_inst2pkg(m3000_stdin); + if (!m3000_property_matches(node, "name", "pseudo-console")) + return -ENODEV; + ret = hvc_instantiate(0, 0, &m3000_ops); + if (ret < 0) + return ret; + m3000_ready = true; + return 0; +} +console_initcall(m3000_console_init); + +static int __init m3000_tty_init(void) +{ + struct hvc_struct *hp; + + if (!m3000_ready) + return -ENODEV; + timer_setup(&m3000_poll_timer, m3000_poll_tick, 0); + hp = hvc_alloc(0, 0, &m3000_ops, sizeof(m3000_buffer)); + if (IS_ERR(hp)) + return PTR_ERR(hp); + hp->ws.ws_row = 24; + hp->ws.ws_col = 80; + pr_info("M3000: firmware-backed hvc0 tty ready (serialized, polled input)\n"); + return 0; +} +device_initcall(m3000_tty_init); -- 2.43.0 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 7/7] hvc: add an M3000 firmware console backend 2026-10-02 16:14 ` [PATCH 7/7] hvc: add an M3000 firmware console backend Magnus Lindholm @ 2026-10-03 17:56 ` sashiko-bot 2026-10-04 12:50 ` Greg Kroah-Hartman 1 sibling, 0 replies; 5+ messages in thread From: sashiko-bot @ 2026-10-03 17:56 UTC (permalink / raw) To: Magnus Lindholm; +Cc: linux-serial > Provide hvc0 through the IKKAKU Open Firmware pseudo-console, validating > model and console properties before matching. Serialize firmware calls, > keep the bounce buffer in locked mappings and poll input each open tick. > > Keep output buffers const and bound no-progress retries because HVC > retries EAGAIN indefinitely. A stalled firmware call remains unbounded. > Use the existing SPARC p1275 interface and HVC output contract. > > Signed-off-by: Magnus Lindholm <linmag7@gmail.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20261002161515.932316-1-linmag7@gmail.com?part=7 ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 7/7] hvc: add an M3000 firmware console backend 2026-10-02 16:14 ` [PATCH 7/7] hvc: add an M3000 firmware console backend Magnus Lindholm 2026-10-03 17:56 ` sashiko-bot @ 2026-10-04 12:50 ` Greg Kroah-Hartman 2026-10-04 15:24 ` Magnus Lindholm 1 sibling, 1 reply; 5+ messages in thread From: Greg Kroah-Hartman @ 2026-10-04 12:50 UTC (permalink / raw) To: Magnus Lindholm Cc: sparclinux, David S . Miller, Andreas Larsson, linux-kernel, Jiri Slaby, linuxppc-dev, linux-serial On Fri, Oct 02, 2026 at 06:14:29PM +0200, Magnus Lindholm wrote: > Provide hvc0 through the IKKAKU Open Firmware pseudo-console, validating > model and console properties before matching. Serialize firmware calls, > keep the bounce buffer in locked mappings and poll input each open tick. > > Keep output buffers const and bound no-progress retries because HVC > retries EAGAIN indefinitely. A stalled firmware call remains unbounded. > Use the existing SPARC p1275 interface and HVC output contract. > > Signed-off-by: Magnus Lindholm <linmag7@gmail.com> > --- > MAINTAINERS | 6 ++ > drivers/tty/hvc/Kconfig | 10 +++ > drivers/tty/hvc/Makefile | 2 + > drivers/tty/hvc/hvc_m3000.c | 167 ++++++++++++++++++++++++++++++++++++ > 4 files changed, 185 insertions(+) > create mode 100644 drivers/tty/hvc/hvc_m3000.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index 3a19da74d00c..5bc9b1cabd0a 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -10728,6 +10728,12 @@ L: platform-driver-x86@vger.kernel.org > S: Maintained > F: drivers/platform/x86/fujitsu-laptop.c > > +FUJITSU M3000 FIRMWARE CONSOLE > +M: Magnus Lindholm <linmag7@gmail.com> > +L: linux-serial@vger.kernel.org > +S: Maintained > +F: drivers/tty/hvc/hvc_m3000.c > + > FUJITSU TABLET EXTRAS > M: Robert Gerlach <khnz@gmx.de> > L: platform-driver-x86@vger.kernel.org > diff --git a/drivers/tty/hvc/Kconfig b/drivers/tty/hvc/Kconfig > index 5866195de26a..0feb7ec98f4f 100644 > --- a/drivers/tty/hvc/Kconfig > +++ b/drivers/tty/hvc/Kconfig > @@ -134,3 +134,13 @@ config HVCS > will depend on arch specific APIs exported from hvcserver.ko > which will also be compiled when this driver is built as a > module. > + > +config HVC_M3000 > + bool "M3000 firmware pseudo-console" > + depends on SPARC64_VII > + select HVC_DRIVER > + help > + Provide hvc0 using Open Firmware stdin/stdout on IKKAKU only. > + Input is polled; no native UART registers are accessed. > + Firmware calls are serialized and use a locked-image bounce buffer. > + Say Y to use the M3000 firmware pseudo-console as hvc0. > diff --git a/drivers/tty/hvc/Makefile b/drivers/tty/hvc/Makefile > index 98880e357941..5b0277deb7c9 100644 > --- a/drivers/tty/hvc/Makefile > +++ b/drivers/tty/hvc/Makefile > @@ -11,3 +11,5 @@ obj-$(CONFIG_HVC_IUCV) += hvc_iucv.o > obj-$(CONFIG_HVC_UDBG) += hvc_udbg.o > obj-$(CONFIG_HVC_RISCV_SBI) += hvc_riscv_sbi.o > obj-$(CONFIG_HVCS) += hvcs.o > + > +obj-$(CONFIG_HVC_M3000) += hvc_m3000.o No need for a blank line, right? And why no tab used here? > diff --git a/drivers/tty/hvc/hvc_m3000.c b/drivers/tty/hvc/hvc_m3000.c > new file mode 100644 > index 000000000000..0ef4c888a6a2 > --- /dev/null > +++ b/drivers/tty/hvc/hvc_m3000.c > @@ -0,0 +1,167 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* Experimental M3000 Open Firmware pseudo-console backend. */ What will make it not "experimental"? And no copyright? > +#include <linux/console.h> > +#include <linux/err.h> > +#include <linux/init.h> > +#include <linux/irqflags.h> > +#include <linux/string.h> > +#include <linux/spinlock.h> > +#include <linux/timer.h> > +#include <asm/oplib.h> > +#include <asm/spitfire.h> > +#include "hvc_console.h" > + > +#define M3000_WRITE_ATTEMPTS 8 why 8? > + > +static int m3000_stdin; > +static bool m3000_ready; > +/* Keep firmware buffers within the locked kernel image mappings. */ > +static u8 m3000_buffer[256]; > +static DEFINE_RAW_SPINLOCK(m3000_buffer_lock); > +static struct timer_list m3000_poll_timer; > +static bool m3000_poll_active; Shouldn't these be in a structure attached to the console somewhere? Otherwise you have limited yourself to just one of these. > + > +/* > + * HVC's idle backoff can exceed the firmware input FIFO's capacity. > + * Wake its worker each tick while open; keep PROM calls out of the timer. > + */ > +static void m3000_poll_tick(struct timer_list *timer) > +{ > + if (!READ_ONCE(m3000_poll_active)) > + return; Why are you accessing m3000_poll_active like this in an attempt to not use a real lock? Are you _sure_ a bool will work this way properly? > + hvc_kick(); > + mod_timer(&m3000_poll_timer, jiffies + 1); > +} > + > +static int m3000_open(struct hvc_struct *hp, int data) > +{ > + WRITE_ONCE(m3000_poll_active, true); > + mod_timer(&m3000_poll_timer, jiffies + 1); > + return 0; > +} > + > +static void m3000_close(struct hvc_struct *hp, int data) > +{ > + WRITE_ONCE(m3000_poll_active, false); > + timer_delete_sync(&m3000_poll_timer); > +} > + > +static ssize_t m3000_io(u8 *in, const u8 *out, size_t count) > +{ > + unsigned long args[7], flags; > + bool input = in != NULL; > + int ret; > + > + if (!count) > + return 0; > + count = min_t(size_t, count, input ? 1 : sizeof(m3000_buffer)); No need for min_t(), why not just min()? > + /* Serialize the bounce buffer; p1275 separately serializes firmware. */ > + raw_spin_lock_irqsave(&m3000_buffer_lock, flags); why is this a "raw" spinlock? > + if (!input) > + memcpy(m3000_buffer, out, count); > + args[0] = (unsigned long)(input ? "read" : "write"); A string being cast to an unsigned long? Are you _sure_? > + args[1] = 3; > + args[2] = 1; > + args[3] = (unsigned int)(input ? m3000_stdin : prom_stdout); > + args[4] = (unsigned long)m3000_buffer; > + args[5] = count; > + args[6] = (unsigned long)-1; > + p1275_cmd_direct(args); > + ret = (int)args[6]; > + if (ret > 0 && ret <= count && input) > + memcpy(in, m3000_buffer, ret); > + raw_spin_unlock_irqrestore(&m3000_buffer_lock, flags); > + if (ret == -2 || ret == 0) > + return input ? 0 : -EAGAIN; > + if (ret < 0 || ret > count) > + return -EIO; > + return ret; > +} > + > +static ssize_t m3000_get(u32 termno, u8 *buf, size_t count) > +{ > + return m3000_io(buf, NULL, count); > +} > + > +static ssize_t m3000_put(u32 termno, const u8 *buf, size_t count) > +{ > + ssize_t ret; > + int attempt; > + > + /* > + * HVC retries -EAGAIN forever, so drop this chunk without logging when > + * the no-progress budget expires. This cannot bound a stalled firmware > + * call or lock acquisition. > + */ > + for (attempt = 0; attempt < M3000_WRITE_ATTEMPTS; attempt++) { > + ret = m3000_io(NULL, buf, count); > + if (ret != -EAGAIN) > + return ret; > + cpu_relax(); > + } > + return -EIO; > +} > + > +static const struct hv_ops m3000_ops = { > + .get_chars = m3000_get, > + .put_chars = m3000_put, > + .notifier_add = m3000_open, > + .notifier_del = m3000_close, > + .notifier_hangup = m3000_close, > +}; > + > +static bool __init m3000_property_matches(phandle node, const char *prop, > + const char *expected) > +{ > + char value[64]; > + int len; > + > + len = prom_getproperty(node, prop, value, sizeof(value) - 1); > + if (len <= 0) > + return false; > + value[len] = '\0'; > + return !strcmp(value, expected); > +} > + > +static int __init m3000_console_init(void) > +{ > + phandle node; > + int ret; > + > + if (tlb_type != sparc64_vii) > + return -ENODEV; > + if (!m3000_property_matches(prom_finddevice("/"), "model", "IKKAKU")) > + return -ENODEV; > + m3000_stdin = prom_getint(prom_chosen_node, "stdin"); > + if (!m3000_stdin || m3000_stdin == -1 || !prom_stdout || prom_stdout == -1) > + return -ENODEV; > + node = prom_inst2pkg(prom_stdout); > + if (!m3000_property_matches(node, "name", "pseudo-console")) > + return -ENODEV; > + node = prom_inst2pkg(m3000_stdin); > + if (!m3000_property_matches(node, "name", "pseudo-console")) > + return -ENODEV; > + ret = hvc_instantiate(0, 0, &m3000_ops); > + if (ret < 0) > + return ret; > + m3000_ready = true; > + return 0; > +} > +console_initcall(m3000_console_init); > + > +static int __init m3000_tty_init(void) > +{ > + struct hvc_struct *hp; > + > + if (!m3000_ready) > + return -ENODEV; > + timer_setup(&m3000_poll_timer, m3000_poll_tick, 0); > + hp = hvc_alloc(0, 0, &m3000_ops, sizeof(m3000_buffer)); > + if (IS_ERR(hp)) > + return PTR_ERR(hp); > + hp->ws.ws_row = 24; > + hp->ws.ws_col = 80; > + pr_info("M3000: firmware-backed hvc0 tty ready (serialized, polled input)\n"); When drivers work properly, they are quiet. thanks, greg k-h ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 7/7] hvc: add an M3000 firmware console backend 2026-10-04 12:50 ` Greg Kroah-Hartman @ 2026-10-04 15:24 ` Magnus Lindholm 0 siblings, 0 replies; 5+ messages in thread From: Magnus Lindholm @ 2026-10-04 15:24 UTC (permalink / raw) To: Greg Kroah-Hartman Cc: sparclinux, David S . Miller, Andreas Larsson, linux-kernel, Jiri Slaby, linuxppc-dev, linux-serial Hi Greg, Thanks alot for taking the time to review this. On Sun, Oct 4, 2026 at 2:50 PM Greg Kroah-Hartman <gregkh@linuxfoundation.org> wrote: > > @@ -11,3 +11,5 @@ obj-$(CONFIG_HVC_IUCV) += hvc_iucv.o > > obj-$(CONFIG_HVC_UDBG) += hvc_udbg.o > > obj-$(CONFIG_HVC_RISCV_SBI) += hvc_riscv_sbi.o > > obj-$(CONFIG_HVCS) += hvcs.o > > + > > +obj-$(CONFIG_HVC_M3000) += hvc_m3000.o > > No need for a blank line, right? And why no tab used here? > Agreed; I have removed the blank line and matched the Makefile's tab alignment. > > diff --git a/drivers/tty/hvc/hvc_m3000.c b/drivers/tty/hvc/hvc_m3000.c > > new file mode 100644 > > index 000000000000..0ef4c888a6a2 > > --- /dev/null > > +++ b/drivers/tty/hvc/hvc_m3000.c > > @@ -0,0 +1,167 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* Experimental M3000 Open Firmware pseudo-console backend. */ > > What will make it not "experimental"? > That was stale wording from bring-up, rather than a defined support status. I have removed it. > And no copyright? > > I'll add a copyright notice for the v2. > > + > > +#define M3000_WRITE_ATTEMPTS 8 > > why 8? > There is no hardware requirement for eight. The intent was to bound no-progress retries because HVC's console write path retries -EAGAIN indefinitely; I will revisit the retry policy before sending v2. > > + > > +static int m3000_stdin; > > +static bool m3000_ready; > > +/* Keep firmware buffers within the locked kernel image mappings. */ > > +static u8 m3000_buffer[256]; > > +static DEFINE_RAW_SPINLOCK(m3000_buffer_lock); > > +static struct timer_list m3000_poll_timer; > > +static bool m3000_poll_active; > > Shouldn't these be in a structure attached to the console somewhere? > Otherwise you have limited yourself to just one of these. > I can group the state into a structure. This backend uses the single /chosen stdin/stdout pair, and the buffer must remain in the locked kernel image mappings for firmware access. I will also review how the state is associated with HVC before finalizing a v2 > > + > > +/* > > + * HVC's idle backoff can exceed the firmware input FIFO's capacity. > > + * Wake its worker each tick while open; keep PROM calls out of the timer. > > + */ > > +static void m3000_poll_tick(struct timer_list *timer) > > +{ > > + if (!READ_ONCE(m3000_poll_active)) > > + return; > > Why are you accessing m3000_poll_active like this in an attempt to not > use a real lock? Are you _sure_ a bool will work this way properly? > Agreed that READ_ONCE/WRITE_ONCE alone do not explain the timer lifecycle. I will review synchronization between open, close and timer rearming, and make that protocol explicit in v2. > > + hvc_kick(); > > + mod_timer(&m3000_poll_timer, jiffies + 1); > > +} > > + > > +static int m3000_open(struct hvc_struct *hp, int data) > > +{ > > + WRITE_ONCE(m3000_poll_active, true); > > + mod_timer(&m3000_poll_timer, jiffies + 1); > > + return 0; > > +} > > + > > +static void m3000_close(struct hvc_struct *hp, int data) > > +{ > > + WRITE_ONCE(m3000_poll_active, false); > > + timer_delete_sync(&m3000_poll_timer); > > +} > > + > > +static ssize_t m3000_io(u8 *in, const u8 *out, size_t count) > > +{ > > + unsigned long args[7], flags; > > + bool input = in != NULL; > > + int ret; > > + > > + if (!count) > > + return 0; > > + count = min_t(size_t, count, input ? 1 : sizeof(m3000_buffer)); > > No need for min_t(), why not just min()? > Agreed, will change it to min(). > > + /* Serialize the bounce buffer; p1275 separately serializes firmware. */ > > + raw_spin_lock_irqsave(&m3000_buffer_lock, flags); > > why is this a "raw" spinlock? > The intent is to protect the shared firmware buffer in console output contexts where sleeping is not allowed. I will check the precise HVC calling contexts and lock ordering before deciding whether the raw lock is necessary and documenting that choice. > > + if (!input) > > + memcpy(m3000_buffer, out, count); > > + args[0] = (unsigned long)(input ? "read" : "write"); > > A string being cast to an unsigned long? Are you _sure_? > Yes: p1275_cmd_direct() takes unsigned long firmware argument cells, and the first cell carries the service-name pointer. The existing SPARC prom_console_write_buf() uses the same cast for "write". > > + if (!m3000_ready) > > + return -ENODEV; > > + timer_setup(&m3000_poll_timer, m3000_poll_tick, 0); > > + hp = hvc_alloc(0, 0, &m3000_ops, sizeof(m3000_buffer)); > > + if (IS_ERR(hp)) > > + return PTR_ERR(hp); > > + hp->ws.ws_row = 24; > > + hp->ws.ws_col = 80; > > + pr_info("M3000: firmware-backed hvc0 tty ready (serialized, polled input)\n"); > > When drivers work properly, they are quiet. > Agreed; I have removed the initialization message. Thanks again for the review. I'll prepare a v2 addressing your comments and explain the reasoning behind any design choices that remain. Regards Magnus ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-10-04 15:24 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-10-02 16:14 [PATCH 0/7] sparc64: add Fujitsu M3000 support Magnus Lindholm 2026-10-02 16:14 ` [PATCH 7/7] hvc: add an M3000 firmware console backend Magnus Lindholm 2026-10-03 17:56 ` sashiko-bot 2026-10-04 12:50 ` Greg Kroah-Hartman 2026-10-04 15:24 ` Magnus Lindholm
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox