[Concept,v2,05/16] serial: Cache the terminal size

Message ID 20250825162727.3185381-6-sjg@u-boot.org
State New
Headers
Series console: Refactor in preparation for the pager |

Commit Message

Simon Glass Aug. 25, 2025, 4:27 p.m. UTC
  From: Simon Glass <sjg@chromium.org>

Add serial_priv structure to serial uclass to cache terminal dimensions.
When serial_query_size() successfully queries the terminal, store the
results in the uclass-private data for later retrieval.

This avoids repeated terminal queries and improves performance when
different subsystems need the terminal size.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

(no changes since v1)

 drivers/serial/serial-uclass.c | 38 ++++++++++++++++++++++++++++++++++
 include/serial.h               | 24 +++++++++++++++++++++
 2 files changed, 62 insertions(+)
  

Patch

diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index 1204fb5d4c4..27de461d196 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -24,6 +24,8 @@ 
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#define ESC "\x1b"
+
 /*
  * Table with supported baudrates (defined in config_xyz.h)
  */
@@ -666,8 +668,18 @@  int serial_query_size(int *rowsp, int *colsp)
 	/* Read {rows,cols} */
 	ret = term_read_reply(n, 2, 'R');
 	if (!ret) {
+		struct serial_priv *priv;
+		struct uclass *uc;
+
 		*colsp = n[1];
 		*rowsp = n[0];
+
+		/* Store in serial uclass private data if available */
+		if (!uclass_get(UCLASS_SERIAL, &uc)) {
+			priv = uclass_get_priv(uc);
+			priv->rows = n[0];
+			priv->cols = n[1];
+		}
 	}
 
 	printf(ESC "8");	/* Restore cursor position */
@@ -675,6 +687,31 @@  int serial_query_size(int *rowsp, int *colsp)
 	return ret;
 }
 
+int serial_get_size(struct udevice *dev, int *rowsp, int *colsp)
+{
+	struct serial_priv *priv;
+	struct uclass *uc;
+	int ret;
+
+	ret = uclass_get(UCLASS_SERIAL, &uc);
+	if (ret)
+		return ret;
+
+	priv = uclass_get_priv(uc);
+
+	/* Check if we have cached values */
+	if (priv->rows && priv->cols) {
+		*rowsp = priv->rows;
+		*colsp = priv->cols;
+		return 0;
+	}
+
+	/* No cached values, query the terminal */
+	ret = serial_query_size(rowsp, colsp);
+
+	return ret;
+}
+
 #if CONFIG_IS_ENABLED(SERIAL_PRESENT)
 static int serial_post_probe(struct udevice *dev)
 {
@@ -730,5 +767,6 @@  UCLASS_DRIVER(serial) = {
 	.post_probe	= serial_post_probe,
 	.pre_remove	= serial_pre_remove,
 	.per_device_auto	= sizeof(struct serial_dev_priv),
+	.priv_auto	= sizeof(struct serial_priv),
 };
 #endif
diff --git a/include/serial.h b/include/serial.h
index 2aba4c313c2..9ed3793b647 100644
--- a/include/serial.h
+++ b/include/serial.h
@@ -291,6 +291,17 @@  struct dm_serial_ops {
 	int (*getinfo)(struct udevice *dev, struct serial_device_info *info);
 };
 
+/**
+ * struct serial_priv - private data for serial uclass
+ *
+ * @rows:	Number of terminal rows (0 if unknown)
+ * @cols:	Number of terminal columns (0 if unknown)
+ */
+struct serial_priv {
+	int rows;
+	int cols;
+};
+
 /**
  * struct serial_dev_priv - information about a device used by the uclass
  *
@@ -400,4 +411,17 @@  int serial_tstc(void);
  */
 int serial_query_size(int *rowsp, int *colsp);
 
+/**
+ * serial_get_size() - get serial console size
+ *
+ * Get the terminal size, using cached values if available, or failing that,
+ * query the terminal
+ *
+ * @dev:	serial device to query (may be NULL)
+ * @rowsp:	returns number of rows
+ * @colsp:	returns number of columns
+ * Returns:	0 on success, -ve on error
+ */
+int serial_get_size(struct udevice *dev, int *rowsp, int *colsp);
+
 #endif