From d5808b5b17e807647850ea30cfe56a1b704b196f Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 10 Feb 2025 16:33:28 -0600 Subject: [PATCH 01/11] auxdisplay: seg-led-gpio: use gpiod_multi_set_value_cansleep Reduce verbosity by using gpiod_multi_set_value_cansleep() instead of gpiod_set_array_value_cansleep(). Acked-by: Andy Shevchenko Reviewed-by: Linus Walleij Reviewed-by: Geert Uytterhoeven Signed-off-by: David Lechner Signed-off-by: Andy Shevchenko --- drivers/auxdisplay/seg-led-gpio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/auxdisplay/seg-led-gpio.c b/drivers/auxdisplay/seg-led-gpio.c index f10c25e6bf12..dfb62e9ce9b4 100644 --- a/drivers/auxdisplay/seg-led-gpio.c +++ b/drivers/auxdisplay/seg-led-gpio.c @@ -36,8 +36,7 @@ static void seg_led_update(struct work_struct *work) bitmap_set_value8(values, map_to_seg7(&map->map.seg7, linedisp->buf[0]), 0); - gpiod_set_array_value_cansleep(priv->segment_gpios->ndescs, priv->segment_gpios->desc, - priv->segment_gpios->info, values); + gpiod_multi_set_value_cansleep(priv->segment_gpios, values); } static int seg_led_linedisp_get_map_type(struct linedisp *linedisp) From fce85f3da08b76c1b052f53a9f6f9c40a8a10660 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Feb 2025 08:48:42 +0100 Subject: [PATCH 02/11] auxdisplay: MAX6959 should select BITREVERSE If CONFIG_BITREVERSE is not enabled: max6959.c:(.text+0x92): undefined reference to `byte_rev_table' Fixes: a9bcd02fa42217c7 ("auxdisplay: Add driver for MAX695x 7-segment LED controllers") Reported-by: kernel test robot Closes: https://lore.kernel.org/202502161703.3Vr4M7qg-lkp@intel.com/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Andy Shevchenko --- drivers/auxdisplay/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig index 8934e6ad5772..bedc6133f970 100644 --- a/drivers/auxdisplay/Kconfig +++ b/drivers/auxdisplay/Kconfig @@ -503,6 +503,7 @@ config HT16K33 config MAX6959 tristate "Maxim MAX6958/6959 7-segment LED controller" depends on I2C + select BITREVERSE select REGMAP_I2C select LINEDISP help From 9b98a7d2e5f4e2beeff88f6571da0cdc5883c7fb Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Mon, 24 Feb 2025 18:15:27 +0800 Subject: [PATCH 03/11] auxdisplay: hd44780: Fix an API misuse in hd44780.c Variable allocated by charlcd_alloc() should be released by charlcd_free(). The following patch changed kfree() to charlcd_free() to fix an API misuse. Fixes: 718e05ed92ec ("auxdisplay: Introduce hd44780_common.[ch]") Cc: stable@vger.kernel.org Signed-off-by: Haoxiang Li Reviewed-by: Geert Uytterhoeven Signed-off-by: Andy Shevchenko --- drivers/auxdisplay/hd44780.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c index 0526f0d90a79..9d0ae9c02e9b 100644 --- a/drivers/auxdisplay/hd44780.c +++ b/drivers/auxdisplay/hd44780.c @@ -313,7 +313,7 @@ static int hd44780_probe(struct platform_device *pdev) fail3: kfree(hd); fail2: - kfree(lcd); + charlcd_free(lcd); fail1: kfree(hdc); return ret; @@ -328,7 +328,7 @@ static void hd44780_remove(struct platform_device *pdev) kfree(hdc->hd44780); kfree(lcd->drvdata); - kfree(lcd); + charlcd_free(lcd); } static const struct of_device_id hd44780_of_match[] = { From 72e1c440c848624ad4cfac93d69d8a999a20355b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 24 Feb 2025 14:36:25 +0200 Subject: [PATCH 04/11] auxdisplay: panel: Fix an API misuse in panel.c Variable allocated by charlcd_alloc() should be released by charlcd_free(). The following patch changed kfree() to charlcd_free() to fix an API misuse. Reviewed-by: Geert Uytterhoeven Fixes: 718e05ed92ec ("auxdisplay: Introduce hd44780_common.[ch]") Signed-off-by: Andy Shevchenko --- drivers/auxdisplay/panel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c index a731f28455b4..6dc8798d01f9 100644 --- a/drivers/auxdisplay/panel.c +++ b/drivers/auxdisplay/panel.c @@ -1664,7 +1664,7 @@ static void panel_attach(struct parport *port) if (lcd.enabled) charlcd_unregister(lcd.charlcd); err_unreg_device: - kfree(lcd.charlcd); + charlcd_free(lcd.charlcd); lcd.charlcd = NULL; parport_unregister_device(pprt); pprt = NULL; @@ -1692,7 +1692,7 @@ static void panel_detach(struct parport *port) charlcd_unregister(lcd.charlcd); lcd.initialized = false; kfree(lcd.charlcd->drvdata); - kfree(lcd.charlcd); + charlcd_free(lcd.charlcd); lcd.charlcd = NULL; } From 09965a142078080fe7807bab0f6f1890cb5987a4 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 24 Feb 2025 19:27:38 +0200 Subject: [PATCH 05/11] auxdisplay: charlcd: Partially revert "Move hwidth and bwidth to struct hd44780_common" Commit 2545c1c948a6 ("auxdisplay: Move hwidth and bwidth to struct hd44780_common") makes charlcd_alloc() argument-less effectively dropping the single allocation for the struct charlcd_priv object along with the driver specific one. Restore that behaviour here. Signed-off-by: Andy Shevchenko Reviewed-by: Geert Uytterhoeven --- drivers/auxdisplay/charlcd.c | 5 +++-- drivers/auxdisplay/charlcd.h | 5 +++-- drivers/auxdisplay/hd44780.c | 2 +- drivers/auxdisplay/lcd2s.c | 2 +- drivers/auxdisplay/panel.c | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c index 19b619376d48..09020bb8ad15 100644 --- a/drivers/auxdisplay/charlcd.c +++ b/drivers/auxdisplay/charlcd.c @@ -595,18 +595,19 @@ static int charlcd_init(struct charlcd *lcd) return 0; } -struct charlcd *charlcd_alloc(void) +struct charlcd *charlcd_alloc(unsigned int drvdata_size) { struct charlcd_priv *priv; struct charlcd *lcd; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); + priv = kzalloc(sizeof(*priv) + drvdata_size, GFP_KERNEL); if (!priv) return NULL; priv->esc_seq.len = -1; lcd = &priv->lcd; + lcd->drvdata = priv->drvdata; return lcd; } diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h index 4d4287209d04..d10b89740bca 100644 --- a/drivers/auxdisplay/charlcd.h +++ b/drivers/auxdisplay/charlcd.h @@ -51,7 +51,7 @@ struct charlcd { unsigned long y; } addr; - void *drvdata; + void *drvdata; /* Set by charlcd_alloc() */ }; /** @@ -95,7 +95,8 @@ struct charlcd_ops { }; void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on); -struct charlcd *charlcd_alloc(void); + +struct charlcd *charlcd_alloc(unsigned int drvdata_size); void charlcd_free(struct charlcd *lcd); int charlcd_register(struct charlcd *lcd); diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c index 9d0ae9c02e9b..1d67fe324341 100644 --- a/drivers/auxdisplay/hd44780.c +++ b/drivers/auxdisplay/hd44780.c @@ -226,7 +226,7 @@ static int hd44780_probe(struct platform_device *pdev) if (!hdc) return -ENOMEM; - lcd = charlcd_alloc(); + lcd = charlcd_alloc(0); if (!lcd) goto fail1; diff --git a/drivers/auxdisplay/lcd2s.c b/drivers/auxdisplay/lcd2s.c index a28daa4ffbf7..c71ebb925971 100644 --- a/drivers/auxdisplay/lcd2s.c +++ b/drivers/auxdisplay/lcd2s.c @@ -307,7 +307,7 @@ static int lcd2s_i2c_probe(struct i2c_client *i2c) if (err < 0) return err; - lcd = charlcd_alloc(); + lcd = charlcd_alloc(0); if (!lcd) return -ENOMEM; diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c index 6dc8798d01f9..4da142692d55 100644 --- a/drivers/auxdisplay/panel.c +++ b/drivers/auxdisplay/panel.c @@ -835,7 +835,7 @@ static void lcd_init(void) if (!hdc) return; - charlcd = charlcd_alloc(); + charlcd = charlcd_alloc(0); if (!charlcd) { kfree(hdc); return; From 68917dfc6bf90a037817bef9d1038220a07a9ea1 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 24 Feb 2025 19:27:39 +0200 Subject: [PATCH 06/11] auxdisplay: lcd2s: Allocate memory for custom data in charlcd_alloc() Allocate memory for custom data in charlcd_alloc() instead of doing that explicitly in the driver. Signed-off-by: Andy Shevchenko Reviewed-by: Geert Uytterhoeven --- drivers/auxdisplay/lcd2s.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/auxdisplay/lcd2s.c b/drivers/auxdisplay/lcd2s.c index c71ebb925971..045dbef49dee 100644 --- a/drivers/auxdisplay/lcd2s.c +++ b/drivers/auxdisplay/lcd2s.c @@ -298,20 +298,18 @@ static int lcd2s_i2c_probe(struct i2c_client *i2c) I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)) return -EIO; - lcd2s = devm_kzalloc(&i2c->dev, sizeof(*lcd2s), GFP_KERNEL); - if (!lcd2s) - return -ENOMEM; - /* Test, if the display is responding */ err = lcd2s_i2c_smbus_write_byte(i2c, LCD2S_CMD_DISPLAY_OFF); if (err < 0) return err; - lcd = charlcd_alloc(0); + lcd = charlcd_alloc(sizeof(*lcd2s)); if (!lcd) return -ENOMEM; - lcd->drvdata = lcd2s; + lcd->ops = &lcd2s_ops; + + lcd2s = lcd->drvdata; lcd2s->i2c = i2c; lcd2s->charlcd = lcd; @@ -326,8 +324,6 @@ static int lcd2s_i2c_probe(struct i2c_client *i2c) if (err) goto fail1; - lcd->ops = &lcd2s_ops; - err = charlcd_register(lcd2s->charlcd); if (err) goto fail1; From d5c7c273d28d3748e00860613f24458b948fb4e3 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 24 Feb 2025 19:27:40 +0200 Subject: [PATCH 07/11] auxdisplay: hd44780: Introduce hd44780_common_free() Introduce hd44780_common_free() for symmetrical operation to hd44780_common_alloc(). It will allow to modify both in the future without touching the users. Signed-off-by: Andy Shevchenko Reviewed-by: Geert Uytterhoeven --- drivers/auxdisplay/hd44780_common.c | 6 ++++++ drivers/auxdisplay/hd44780_common.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/drivers/auxdisplay/hd44780_common.c b/drivers/auxdisplay/hd44780_common.c index 4ef87c3118c0..3f8a496ccb8e 100644 --- a/drivers/auxdisplay/hd44780_common.c +++ b/drivers/auxdisplay/hd44780_common.c @@ -366,5 +366,11 @@ struct hd44780_common *hd44780_common_alloc(void) } EXPORT_SYMBOL_GPL(hd44780_common_alloc); +void hd44780_common_free(struct hd44780_common *hd) +{ + kfree(hd); +} +EXPORT_SYMBOL_GPL(hd44780_common_free); + MODULE_DESCRIPTION("Common functions for HD44780 (and compatibles) LCD displays"); MODULE_LICENSE("GPL"); diff --git a/drivers/auxdisplay/hd44780_common.h b/drivers/auxdisplay/hd44780_common.h index a16aa8c29c99..fe1386e3cf79 100644 --- a/drivers/auxdisplay/hd44780_common.h +++ b/drivers/auxdisplay/hd44780_common.h @@ -30,4 +30,6 @@ int hd44780_common_blink(struct charlcd *lcd, enum charlcd_onoff on); int hd44780_common_fontsize(struct charlcd *lcd, enum charlcd_fontsize size); int hd44780_common_lines(struct charlcd *lcd, enum charlcd_lines lines); int hd44780_common_redefine_char(struct charlcd *lcd, char *esc); + struct hd44780_common *hd44780_common_alloc(void); +void hd44780_common_free(struct hd44780_common *hd); From 33152d3660b8fe53763da1fa7715e2cdae910335 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 24 Feb 2025 19:27:41 +0200 Subject: [PATCH 08/11] auxdisplay: hd44780: Make use of hd44780_common_free() Use the symmetrical API to free the common resources. Signed-off-by: Andy Shevchenko Reviewed-by: Geert Uytterhoeven --- drivers/auxdisplay/hd44780.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c index 1d67fe324341..ef38cb7bf13d 100644 --- a/drivers/auxdisplay/hd44780.c +++ b/drivers/auxdisplay/hd44780.c @@ -315,7 +315,7 @@ static int hd44780_probe(struct platform_device *pdev) fail2: charlcd_free(lcd); fail1: - kfree(hdc); + hd44780_common_free(hdc); return ret; } @@ -326,8 +326,7 @@ static void hd44780_remove(struct platform_device *pdev) charlcd_unregister(lcd); kfree(hdc->hd44780); - kfree(lcd->drvdata); - + hd44780_common_free(hdc); charlcd_free(lcd); } From 664d2179c6e3d08d5e1180beddd79ca8f0663d89 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 24 Feb 2025 19:27:42 +0200 Subject: [PATCH 09/11] auxdisplay: panel: Make use of hd44780_common_free() Use the symmetrical API to free the common resources. Signed-off-by: Andy Shevchenko Reviewed-by: Geert Uytterhoeven --- drivers/auxdisplay/panel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c index 4da142692d55..aa1d03fef22e 100644 --- a/drivers/auxdisplay/panel.c +++ b/drivers/auxdisplay/panel.c @@ -837,7 +837,7 @@ static void lcd_init(void) charlcd = charlcd_alloc(0); if (!charlcd) { - kfree(hdc); + hd44780_common_free(hdc); return; } @@ -1691,7 +1691,7 @@ static void panel_detach(struct parport *port) if (lcd.enabled) { charlcd_unregister(lcd.charlcd); lcd.initialized = false; - kfree(lcd.charlcd->drvdata); + hd44780_common_free(lcd.charlcd->drvdata); charlcd_free(lcd.charlcd); lcd.charlcd = NULL; } From 65f095b2b1f2ae2e0919a24a6f6883b580b72602 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 24 Feb 2025 19:27:43 +0200 Subject: [PATCH 10/11] auxdisplay: hd44780: Call charlcd_alloc() from hd44780_common_alloc() HD44780 APIs all operate on struct charlcd objects. Moreover, the current users always call charlcd_alloc() and hd44780_common_alloc(). Make the latter call the former, so eliminate the additional allocation, to make it consistent with the rest of API and avoid duplication. Signed-off-by: Andy Shevchenko Reviewed-by: Geert Uytterhoeven --- drivers/auxdisplay/hd44780.c | 18 ++++++------------ drivers/auxdisplay/hd44780_common.c | 14 ++++++++------ drivers/auxdisplay/hd44780_common.h | 4 ++-- drivers/auxdisplay/panel.c | 17 +++++------------ 4 files changed, 21 insertions(+), 32 deletions(-) diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c index ef38cb7bf13d..cef42656c4b0 100644 --- a/drivers/auxdisplay/hd44780.c +++ b/drivers/auxdisplay/hd44780.c @@ -222,20 +222,17 @@ static int hd44780_probe(struct platform_device *pdev) return -EINVAL; } - hdc = hd44780_common_alloc(); - if (!hdc) - return -ENOMEM; - - lcd = charlcd_alloc(0); + lcd = hd44780_common_alloc(); if (!lcd) - goto fail1; + return -ENOMEM; hd = kzalloc(sizeof(*hd), GFP_KERNEL); if (!hd) goto fail2; + hdc = lcd->drvdata; hdc->hd44780 = hd; - lcd->drvdata = hdc; + for (i = 0; i < ifwidth; i++) { hd->pins[base + i] = devm_gpiod_get_index(dev, "data", i, GPIOD_OUT_LOW); @@ -313,9 +310,7 @@ static int hd44780_probe(struct platform_device *pdev) fail3: kfree(hd); fail2: - charlcd_free(lcd); -fail1: - hd44780_common_free(hdc); + hd44780_common_free(lcd); return ret; } @@ -326,8 +321,7 @@ static void hd44780_remove(struct platform_device *pdev) charlcd_unregister(lcd); kfree(hdc->hd44780); - hd44780_common_free(hdc); - charlcd_free(lcd); + hd44780_common_free(lcd); } static const struct of_device_id hd44780_of_match[] = { diff --git a/drivers/auxdisplay/hd44780_common.c b/drivers/auxdisplay/hd44780_common.c index 3f8a496ccb8e..fb340d18fcad 100644 --- a/drivers/auxdisplay/hd44780_common.c +++ b/drivers/auxdisplay/hd44780_common.c @@ -351,24 +351,26 @@ int hd44780_common_redefine_char(struct charlcd *lcd, char *esc) } EXPORT_SYMBOL_GPL(hd44780_common_redefine_char); -struct hd44780_common *hd44780_common_alloc(void) +struct charlcd *hd44780_common_alloc(void) { struct hd44780_common *hd; + struct charlcd *lcd; - hd = kzalloc(sizeof(*hd), GFP_KERNEL); - if (!hd) + lcd = charlcd_alloc(sizeof(*hd)); + if (!lcd) return NULL; + hd = lcd->drvdata; hd->ifwidth = 8; hd->bwidth = DEFAULT_LCD_BWIDTH; hd->hwidth = DEFAULT_LCD_HWIDTH; - return hd; + return lcd; } EXPORT_SYMBOL_GPL(hd44780_common_alloc); -void hd44780_common_free(struct hd44780_common *hd) +void hd44780_common_free(struct charlcd *lcd) { - kfree(hd); + charlcd_free(lcd); } EXPORT_SYMBOL_GPL(hd44780_common_free); diff --git a/drivers/auxdisplay/hd44780_common.h b/drivers/auxdisplay/hd44780_common.h index fe1386e3cf79..4c87f55722b6 100644 --- a/drivers/auxdisplay/hd44780_common.h +++ b/drivers/auxdisplay/hd44780_common.h @@ -31,5 +31,5 @@ int hd44780_common_fontsize(struct charlcd *lcd, enum charlcd_fontsize size); int hd44780_common_lines(struct charlcd *lcd, enum charlcd_lines lines); int hd44780_common_redefine_char(struct charlcd *lcd, char *esc); -struct hd44780_common *hd44780_common_alloc(void); -void hd44780_common_free(struct hd44780_common *hd); +struct charlcd *hd44780_common_alloc(void); +void hd44780_common_free(struct charlcd *lcd); diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c index aa1d03fef22e..91ccb9789d43 100644 --- a/drivers/auxdisplay/panel.c +++ b/drivers/auxdisplay/panel.c @@ -831,18 +831,12 @@ static void lcd_init(void) struct charlcd *charlcd; struct hd44780_common *hdc; - hdc = hd44780_common_alloc(); - if (!hdc) + charlcd = hd44780_common_alloc(); + if (!charlcd) return; - charlcd = charlcd_alloc(0); - if (!charlcd) { - hd44780_common_free(hdc); - return; - } - + hdc = charlcd->drvdata; hdc->hd44780 = &lcd; - charlcd->drvdata = hdc; /* * Init lcd struct with load-time values to preserve exact @@ -1664,7 +1658,7 @@ static void panel_attach(struct parport *port) if (lcd.enabled) charlcd_unregister(lcd.charlcd); err_unreg_device: - charlcd_free(lcd.charlcd); + hd44780_common_free(lcd.charlcd); lcd.charlcd = NULL; parport_unregister_device(pprt); pprt = NULL; @@ -1691,8 +1685,7 @@ static void panel_detach(struct parport *port) if (lcd.enabled) { charlcd_unregister(lcd.charlcd); lcd.initialized = false; - hd44780_common_free(lcd.charlcd->drvdata); - charlcd_free(lcd.charlcd); + hd44780_common_free(lcd.charlcd); lcd.charlcd = NULL; } From 2c4849a41326b37a33b91595cba81f1f0f6a62f7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 24 Feb 2025 19:27:44 +0200 Subject: [PATCH 11/11] auxdisplay: hd44780: Rename hd to hdc in hd44780_common_alloc() The hd44780_common_alloc() uses hd for local variable while the respective header uses hdc, rename to make it consistent and avoid potential confuse with the drivers that use both for different reasons. No functional changes intended. Signed-off-by: Andy Shevchenko --- drivers/auxdisplay/hd44780_common.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/auxdisplay/hd44780_common.c b/drivers/auxdisplay/hd44780_common.c index fb340d18fcad..1792fe2a4460 100644 --- a/drivers/auxdisplay/hd44780_common.c +++ b/drivers/auxdisplay/hd44780_common.c @@ -353,17 +353,17 @@ EXPORT_SYMBOL_GPL(hd44780_common_redefine_char); struct charlcd *hd44780_common_alloc(void) { - struct hd44780_common *hd; + struct hd44780_common *hdc; struct charlcd *lcd; - lcd = charlcd_alloc(sizeof(*hd)); + lcd = charlcd_alloc(sizeof(*hdc)); if (!lcd) return NULL; - hd = lcd->drvdata; - hd->ifwidth = 8; - hd->bwidth = DEFAULT_LCD_BWIDTH; - hd->hwidth = DEFAULT_LCD_HWIDTH; + hdc = lcd->drvdata; + hdc->ifwidth = 8; + hdc->bwidth = DEFAULT_LCD_BWIDTH; + hdc->hwidth = DEFAULT_LCD_HWIDTH; return lcd; } EXPORT_SYMBOL_GPL(hd44780_common_alloc);