git: 949670f8f466 - main - dev/uart: Use a linker set to find uart classes

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Tue, 13 Feb 2024 11:51:50 UTC
The branch main has been updated by andrew:

URL: https://cgit.FreeBSD.org/src/commit/?id=949670f8f46656a30ffbd22c9ae2cc645bda8533

commit 949670f8f46656a30ffbd22c9ae2cc645bda8533
Author:     Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2024-01-08 15:02:29 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2024-02-13 11:48:52 +0000

    dev/uart: Use a linker set to find uart classes
    
    When the uart is configured via the environment we need to find the
    uart class with a specified name. Currently to do this with an
    incomplete list of uarts. As we may not have included all uarts in the
    kernel each class is defined as weak.
    
    Switch to a linker set so the list is always up to date based on what
    is included in the kernel, and the class can be static.
    
    Reviewed by:    imp
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D43361
---
 sys/dev/uart/uart.h            |  4 ++++
 sys/dev/uart/uart_dev_ns8250.c |  1 +
 sys/dev/uart/uart_dev_z8530.c  |  1 +
 sys/dev/uart/uart_subr.c       | 12 +++---------
 4 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/sys/dev/uart/uart.h b/sys/dev/uart/uart.h
index 5eae06ceba6f..987152283c81 100644
--- a/sys/dev/uart/uart.h
+++ b/sys/dev/uart/uart.h
@@ -29,6 +29,8 @@
 #ifndef _DEV_UART_H_
 #define _DEV_UART_H_
 
+#include <sys/linker_set.h>
+
 /*
  * Bus access structure. This structure holds the minimum information needed
  * to access the UART. The rclk field, although not important to actually
@@ -99,6 +101,8 @@ uart_setreg(struct uart_bas *bas, int reg, int value)
  */
 struct uart_class;
 
+SET_DECLARE(uart_class_set, struct uart_class);
+
 extern struct uart_class uart_ns8250_class __attribute__((weak));
 extern struct uart_class uart_quicc_class __attribute__((weak));
 extern struct uart_class uart_z8530_class __attribute__((weak));
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index 090909fdf8d2..f660639862ff 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -451,6 +451,7 @@ struct uart_class uart_ns8250_class = {
 	.uc_rclk = DEFAULT_RCLK,
 	.uc_rshift = 0
 };
+DATA_SET(uart_class_set, uart_ns8250_class);
 
 /*
  * XXX -- refactor out ACPI and FDT ifdefs
diff --git a/sys/dev/uart/uart_dev_z8530.c b/sys/dev/uart/uart_dev_z8530.c
index 8e1adac0aec2..107fcb1eb4ba 100644
--- a/sys/dev/uart/uart_dev_z8530.c
+++ b/sys/dev/uart/uart_dev_z8530.c
@@ -309,6 +309,7 @@ struct uart_class uart_z8530_class = {
 	.uc_rclk = DEFAULT_RCLK,
 	.uc_rshift = 0
 };
+DATA_SET(uart_class_set, uart_z8530_class);
 
 #define	SIGCHG(c, i, s, d)				\
 	if (c) {					\
diff --git a/sys/dev/uart/uart_subr.c b/sys/dev/uart/uart_subr.c
index d10084cfa6d8..e7570e173358 100644
--- a/sys/dev/uart/uart_subr.c
+++ b/sys/dev/uart/uart_subr.c
@@ -48,11 +48,6 @@
 #define	UART_TAG_XO	9
 #define	UART_TAG_BD	10
 
-static struct uart_class *uart_classes[] = {
-	&uart_ns8250_class,
-	&uart_z8530_class,
-};
-
 static bus_addr_t
 uart_parse_addr(const char **p)
 {
@@ -62,13 +57,12 @@ uart_parse_addr(const char **p)
 static struct uart_class *
 uart_parse_class(struct uart_class *class, const char **p)
 {
-	struct uart_class *uc;
+	struct uart_class **puc, *uc;
 	const char *nm;
 	size_t len;
-	u_int i;
 
-	for (i = 0; i < nitems(uart_classes); i++) {
-		uc = uart_classes[i];
+	SET_FOREACH(puc, uart_class_set) {
+		uc = *puc;
 		nm = uart_getname(uc);
 		if (nm == NULL || *nm == '\0')
 			continue;