--- /dev/null
+From 0774d19038c496f0c3602fb505c43e1b2d8eed85 Mon Sep 17 00:00:00 2001
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Date: Mon, 29 Apr 2024 14:50:41 -0700
+Subject: Input: try trimming too long modalias strings
+
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+
+commit 0774d19038c496f0c3602fb505c43e1b2d8eed85 upstream.
+
+If an input device declares too many capability bits then modalias
+string for such device may become too long and not fit into uevent
+buffer, resulting in failure of sending said uevent. This, in turn,
+may prevent userspace from recognizing existence of such devices.
+
+This is typically not a concern for real hardware devices as they have
+limited number of keys, but happen with synthetic devices such as
+ones created by xen-kbdfront driver, which creates devices as being
+capable of delivering all possible keys, since it doesn't know what
+keys the backend may produce.
+
+To deal with such devices input core will attempt to trim key data,
+in the hope that the rest of modalias string will fit in the given
+buffer. When trimming key data it will indicate that it is not
+complete by placing "+," sign, resulting in conversions like this:
+
+old: k71,72,73,74,78,7A,7B,7C,7D,8E,9E,A4,AD,E0,E1,E4,F8,174,
+new: k71,72,73,74,78,7A,7B,7C,+,
+
+This should allow existing udev rules continue to work with existing
+devices, and will also allow writing more complex rules that would
+recognize trimmed modalias and check input device characteristics by
+other means (for example by parsing KEY= data in uevent or parsing
+input device sysfs attributes).
+
+Note that the driver core may try adding more uevent environment
+variables once input core is done adding its own, so when forming
+modalias we can not use the entire available buffer, so we reduce
+it by somewhat an arbitrary amount (96 bytes).
+
+Reported-by: Jason Andryuk <jandryuk@gmail.com>
+Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+Tested-by: Jason Andryuk <jandryuk@gmail.com>
+Link: https://lore.kernel.org/r/ZjAWMQCJdrxZkvkB@google.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/input/input.c | 104 ++++++++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 89 insertions(+), 15 deletions(-)
+
+--- a/drivers/input/input.c
++++ b/drivers/input/input.c
+@@ -1378,19 +1378,19 @@ static int input_print_modalias_bits(cha
+ char name, const unsigned long *bm,
+ unsigned int min_bit, unsigned int max_bit)
+ {
+- int len = 0, i;
++ int bit = min_bit;
++ int len = 0;
+
+ len += snprintf(buf, max(size, 0), "%c", name);
+- for (i = min_bit; i < max_bit; i++)
+- if (bm[BIT_WORD(i)] & BIT_MASK(i))
+- len += snprintf(buf + len, max(size - len, 0), "%X,", i);
++ for_each_set_bit_from(bit, bm, max_bit)
++ len += snprintf(buf + len, max(size - len, 0), "%X,", bit);
+ return len;
+ }
+
+-static int input_print_modalias(char *buf, int size, const struct input_dev *id,
+- int add_cr)
++static int input_print_modalias_parts(char *buf, int size, int full_len,
++ const struct input_dev *id)
+ {
+- int len;
++ int len, klen, remainder, space;
+
+ len = snprintf(buf, max(size, 0),
+ "input:b%04Xv%04Xp%04Xe%04X-",
+@@ -1399,8 +1399,48 @@ static int input_print_modalias(char *bu
+
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'e', id->evbit, 0, EV_MAX);
+- len += input_print_modalias_bits(buf + len, size - len,
++
++ /*
++ * Calculate the remaining space in the buffer making sure we
++ * have place for the terminating 0.
++ */
++ space = max(size - (len + 1), 0);
++
++ klen = input_print_modalias_bits(buf + len, size - len,
+ 'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
++ len += klen;
++
++ /*
++ * If we have more data than we can fit in the buffer, check
++ * if we can trim key data to fit in the rest. We will indicate
++ * that key data is incomplete by adding "+" sign at the end, like
++ * this: * "k1,2,3,45,+,".
++ *
++ * Note that we shortest key info (if present) is "k+," so we
++ * can only try to trim if key data is longer than that.
++ */
++ if (full_len && size < full_len + 1 && klen > 3) {
++ remainder = full_len - len;
++ /*
++ * We can only trim if we have space for the remainder
++ * and also for at least "k+," which is 3 more characters.
++ */
++ if (remainder <= space - 3) {
++ /*
++ * We are guaranteed to have 'k' in the buffer, so
++ * we need at least 3 additional bytes for storing
++ * "+," in addition to the remainder.
++ */
++ for (int i = size - 1 - remainder - 3; i >= 0; i--) {
++ if (buf[i] == 'k' || buf[i] == ',') {
++ strcpy(buf + i + 1, "+,");
++ len = i + 3; /* Not counting '\0' */
++ break;
++ }
++ }
++ }
++ }
++
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'r', id->relbit, 0, REL_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+@@ -1416,12 +1456,25 @@ static int input_print_modalias(char *bu
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'w', id->swbit, 0, SW_MAX);
+
+- if (add_cr)
+- len += snprintf(buf + len, max(size - len, 0), "\n");
+-
+ return len;
+ }
+
++static int input_print_modalias(char *buf, int size, const struct input_dev *id)
++{
++ int full_len;
++
++ /*
++ * Printing is done in 2 passes: first one figures out total length
++ * needed for the modalias string, second one will try to trim key
++ * data in case when buffer is too small for the entire modalias.
++ * If the buffer is too small regardless, it will fill as much as it
++ * can (without trimming key data) into the buffer and leave it to
++ * the caller to figure out what to do with the result.
++ */
++ full_len = input_print_modalias_parts(NULL, 0, 0, id);
++ return input_print_modalias_parts(buf, size, full_len, id);
++}
++
+ static ssize_t input_dev_show_modalias(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+@@ -1429,7 +1482,9 @@ static ssize_t input_dev_show_modalias(s
+ struct input_dev *id = to_input_dev(dev);
+ ssize_t len;
+
+- len = input_print_modalias(buf, PAGE_SIZE, id, 1);
++ len = input_print_modalias(buf, PAGE_SIZE, id);
++ if (len < PAGE_SIZE - 2)
++ len += snprintf(buf + len, PAGE_SIZE - len, "\n");
+
+ return min_t(int, len, PAGE_SIZE);
+ }
+@@ -1641,6 +1696,23 @@ static int input_add_uevent_bm_var(struc
+ return 0;
+ }
+
++/*
++ * This is a pretty gross hack. When building uevent data the driver core
++ * may try adding more environment variables to kobj_uevent_env without
++ * telling us, so we have no idea how much of the buffer we can use to
++ * avoid overflows/-ENOMEM elsewhere. To work around this let's artificially
++ * reduce amount of memory we will use for the modalias environment variable.
++ *
++ * The potential additions are:
++ *
++ * SEQNUM=18446744073709551615 - (%llu - 28 bytes)
++ * HOME=/ (6 bytes)
++ * PATH=/sbin:/bin:/usr/sbin:/usr/bin (34 bytes)
++ *
++ * 68 bytes total. Allow extra buffer - 96 bytes
++ */
++#define UEVENT_ENV_EXTRA_LEN 96
++
+ static int input_add_uevent_modalias_var(struct kobj_uevent_env *env,
+ const struct input_dev *dev)
+ {
+@@ -1650,9 +1722,11 @@ static int input_add_uevent_modalias_var
+ return -ENOMEM;
+
+ len = input_print_modalias(&env->buf[env->buflen - 1],
+- sizeof(env->buf) - env->buflen,
+- dev, 0);
+- if (len >= (sizeof(env->buf) - env->buflen))
++ (int)sizeof(env->buf) - env->buflen -
++ UEVENT_ENV_EXTRA_LEN,
++ dev);
++ if (len >= ((int)sizeof(env->buf) - env->buflen -
++ UEVENT_ENV_EXTRA_LEN))
+ return -ENOMEM;
+
+ env->buflen += len;
--- /dev/null
+From 614a19b89ca43449196a8af1afac7d55c6781687 Mon Sep 17 00:00:00 2001
+From: Doug Berger <opendmb@gmail.com>
+Date: Wed, 24 Apr 2024 15:25:59 -0700
+Subject: serial: 8250_bcm7271: use default_mux_rate if possible
+
+From: Doug Berger <opendmb@gmail.com>
+
+commit 614a19b89ca43449196a8af1afac7d55c6781687 upstream.
+
+There is a scenario when resuming from some power saving states
+with no_console_suspend where console output can be generated
+before the 8250_bcm7271 driver gets the opportunity to restore
+the baud_mux_clk frequency. Since the baud_mux_clk is at its
+default frequency at this time the output can be garbled until
+the driver gets the opportunity to resume.
+
+Since this is only an issue with console use of the serial port
+during that window and the console isn't likely to use baud
+rates that require alternate baud_mux_clk frequencies, allow the
+driver to select the default_mux_rate if it is accurate enough.
+
+Fixes: 41a469482de2 ("serial: 8250: Add new 8250-core based Broadcom STB driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Doug Berger <opendmb@gmail.com>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Tested-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Link: https://lore.kernel.org/r/20240424222559.1844045-1-opendmb@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/8250/8250_bcm7271.c | 101 +++++++++++++++++++--------------
+ 1 file changed, 60 insertions(+), 41 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250_bcm7271.c
++++ b/drivers/tty/serial/8250/8250_bcm7271.c
+@@ -676,18 +676,46 @@ static void init_real_clk_rates(struct d
+ clk_set_rate(priv->baud_mux_clk, priv->default_mux_rate);
+ }
+
++static u32 find_quot(struct device *dev, u32 freq, u32 baud, u32 *percent)
++{
++ u32 quot;
++ u32 rate;
++ u64 hires_rate;
++ u64 hires_baud;
++ u64 hires_err;
++
++ rate = freq / 16;
++ quot = DIV_ROUND_CLOSEST(rate, baud);
++ if (!quot)
++ return 0;
++
++ /* increase resolution to get xx.xx percent */
++ hires_rate = div_u64((u64)rate * 10000, (u64)quot);
++ hires_baud = (u64)baud * 10000;
++
++ /* get the delta */
++ if (hires_rate > hires_baud)
++ hires_err = (hires_rate - hires_baud);
++ else
++ hires_err = (hires_baud - hires_rate);
++
++ *percent = (unsigned long)DIV_ROUND_CLOSEST_ULL(hires_err, baud);
++
++ dev_dbg(dev, "Baud rate: %u, MUX Clk: %u, Error: %u.%u%%\n",
++ baud, freq, *percent / 100, *percent % 100);
++
++ return quot;
++}
++
+ static void set_clock_mux(struct uart_port *up, struct brcmuart_priv *priv,
+ u32 baud)
+ {
+ u32 percent;
+ u32 best_percent = UINT_MAX;
+ u32 quot;
++ u32 freq;
+ u32 best_quot = 1;
+- u32 rate;
+- int best_index = -1;
+- u64 hires_rate;
+- u64 hires_baud;
+- u64 hires_err;
++ u32 best_freq = 0;
+ int rc;
+ int i;
+ int real_baud;
+@@ -696,44 +724,35 @@ static void set_clock_mux(struct uart_po
+ if (priv->baud_mux_clk == NULL)
+ return;
+
+- /* Find the closest match for specified baud */
+- for (i = 0; i < ARRAY_SIZE(priv->real_rates); i++) {
+- if (priv->real_rates[i] == 0)
+- continue;
+- rate = priv->real_rates[i] / 16;
+- quot = DIV_ROUND_CLOSEST(rate, baud);
+- if (!quot)
+- continue;
+-
+- /* increase resolution to get xx.xx percent */
+- hires_rate = (u64)rate * 10000;
+- hires_baud = (u64)baud * 10000;
+-
+- hires_err = div_u64(hires_rate, (u64)quot);
+-
+- /* get the delta */
+- if (hires_err > hires_baud)
+- hires_err = (hires_err - hires_baud);
+- else
+- hires_err = (hires_baud - hires_err);
+-
+- percent = (unsigned long)DIV_ROUND_CLOSEST_ULL(hires_err, baud);
+- dev_dbg(up->dev,
+- "Baud rate: %u, MUX Clk: %u, Error: %u.%u%%\n",
+- baud, priv->real_rates[i], percent / 100,
+- percent % 100);
+- if (percent < best_percent) {
+- best_percent = percent;
+- best_index = i;
+- best_quot = quot;
++ /* Try default_mux_rate first */
++ quot = find_quot(up->dev, priv->default_mux_rate, baud, &percent);
++ if (quot) {
++ best_percent = percent;
++ best_freq = priv->default_mux_rate;
++ best_quot = quot;
++ }
++ /* If more than 1% error, find the closest match for specified baud */
++ if (best_percent > 100) {
++ for (i = 0; i < ARRAY_SIZE(priv->real_rates); i++) {
++ freq = priv->real_rates[i];
++ if (freq == 0 || freq == priv->default_mux_rate)
++ continue;
++ quot = find_quot(up->dev, freq, baud, &percent);
++ if (!quot)
++ continue;
++
++ if (percent < best_percent) {
++ best_percent = percent;
++ best_freq = freq;
++ best_quot = quot;
++ }
+ }
+ }
+- if (best_index == -1) {
++ if (!best_freq) {
+ dev_err(up->dev, "Error, %d BAUD rate is too fast.\n", baud);
+ return;
+ }
+- rate = priv->real_rates[best_index];
+- rc = clk_set_rate(priv->baud_mux_clk, rate);
++ rc = clk_set_rate(priv->baud_mux_clk, best_freq);
+ if (rc)
+ dev_err(up->dev, "Error selecting BAUD MUX clock\n");
+
+@@ -742,8 +761,8 @@ static void set_clock_mux(struct uart_po
+ dev_err(up->dev, "Error, baud: %d has %u.%u%% error\n",
+ baud, percent / 100, percent % 100);
+
+- real_baud = rate / 16 / best_quot;
+- dev_dbg(up->dev, "Selecting BAUD MUX rate: %u\n", rate);
++ real_baud = best_freq / 16 / best_quot;
++ dev_dbg(up->dev, "Selecting BAUD MUX rate: %u\n", best_freq);
+ dev_dbg(up->dev, "Requested baud: %u, Actual baud: %u\n",
+ baud, real_baud);
+
+@@ -752,7 +771,7 @@ static void set_clock_mux(struct uart_po
+ i += (i / 2);
+ priv->char_wait = ns_to_ktime(i);
+
+- up->uartclk = rate;
++ up->uartclk = best_freq;
+ }
+
+ static void brcmstb_set_termios(struct uart_port *up,