Re: [PATCH 3/3] cyclic: make clients embed a struct cyclic_info in their own data structure

2024-05-16 Thread Stefan Roese

Hi Rasmus,

On 5/9/24 02:47, Rasmus Villemoes wrote:

There are of course not a whole lot of examples in-tree yet, but
before they appear, let's make this API change: Instead of separately
allocating a 'struct cyclic_info', make the users embed such an
instance in their own structure, and make the convention that the
callback simply receives the 'struct cyclic_info *', from which the
clients can get their own data using the container_of() macro.

This has a number of advantages.

First, it means cyclic_register() simply cannot fail, simplifying the
code. The necessary storage will simply be allocated automatically
when the client's own structure is allocated (often via
uclass_priv_auto or similar).

Second, code for which CONFIG_CYCLIC is just an option can more easily
be written without #ifdefs, if we just provide an empty struct
cyclic_info {}. For example, the nested CONFIG_IS_ENABLED()s in
https://lore.kernel.org/u-boot/20240316201416.211480-1-marek.vasut+rene...@mailbox.org/
are mostly due to the existence of the 'struct cyclic_info *' member
being guarded by #ifdef CONFIG_CYCLIC.

And we do probably want to avoid the extra memory overhead of that
member when !CONFIG_CYCLIC. But that is automatic if, instead of a
'struct cyclic_info *', one simply embeds a 'struct cyclic_info',
which will have size 0 when !CONFIG_CYCLIC. Also, the no-op
cyclic_register() function can just unconditionally be called, and the
compiler will see that (1) the callback is referenced, so not emit a
warning for a maybe-unused function and (2) see that it can actually
never be reached, so not emit any code for it.

Signed-off-by: Rasmus Villemoes 
---
  board/Marvell/octeon_nic23/board.c |  9 +---
  cmd/cyclic.c   | 12 +--
  common/cyclic.c| 22 +--
  doc/develop/cyclic.rst | 26 ++-
  drivers/watchdog/wdt-uclass.c  | 33 +
  include/cyclic.h   | 34 +++---
  6 files changed, 64 insertions(+), 72 deletions(-)


I like this approach. And would like to pull this in as well, perhaps
before leaving on a 2 week vacation mid of next week. Unfortunately
this patch 3/3 does not apply on TOT any more. Could you please rebase
and re-submit?

Reviewed-by: Stefan Roese 

Thanks,
Stefan


diff --git a/board/Marvell/octeon_nic23/board.c 
b/board/Marvell/octeon_nic23/board.c
index bc9332cb74a..74b9c741b7b 100644
--- a/board/Marvell/octeon_nic23/board.c
+++ b/board/Marvell/octeon_nic23/board.c
@@ -357,10 +357,13 @@ int board_late_init(void)
board_configure_qlms();
  
  	/* Register cyclic function for PCIe FLR fixup */

-   cyclic = cyclic_register(octeon_board_restore_pf, 100,
-"pcie_flr_fix", NULL);
-   if (!cyclic)
+   cyclic = calloc(1, sizeof(*cyclic));
+   if (cyclic) {
+   cyclic_register(cyclic, octeon_board_restore_pf, 100,
+   "pcie_flr_fix");
+   } else {
printf("Registering of cyclic function failed\n");
+   }
  
  	return 0;

  }
diff --git a/cmd/cyclic.c b/cmd/cyclic.c
index ad7fc3b975e..315546515f0 100644
--- a/cmd/cyclic.c
+++ b/cmd/cyclic.c
@@ -14,14 +14,16 @@
  #include 
  #include 
  #include 
+#include 
  
  struct cyclic_demo_info {

+   struct cyclic_info cyclic;
uint delay_us;
  };
  
-static void cyclic_demo(void *ctx)

+static void cyclic_demo(struct cyclic_info *c)
  {
-   struct cyclic_demo_info *info = ctx;
+   struct cyclic_demo_info *info = container_of(c, struct 
cyclic_demo_info, cyclic);
  
  	/* Just a small dummy delay here */

udelay(info->delay_us);
@@ -31,7 +33,6 @@ static int do_cyclic_demo(struct cmd_tbl *cmdtp, int flag, 
int argc,
  char *const argv[])
  {
struct cyclic_demo_info *info;
-   struct cyclic_info *cyclic;
uint time_ms;
  
  	if (argc < 3)

@@ -47,10 +48,7 @@ static int do_cyclic_demo(struct cmd_tbl *cmdtp, int flag, 
int argc,
info->delay_us = simple_strtoul(argv[2], NULL, 0);
  
  	/* Register demo cyclic function */

-   cyclic = cyclic_register(cyclic_demo, time_ms * 1000, "cyclic_demo",
-info);
-   if (!cyclic)
-   printf("Registering of cyclic_demo failed\n");
+   cyclic_register(>cyclic, cyclic_demo, time_ms * 1000, 
"cyclic_demo");
  
  	printf("Registered function \"%s\" to be executed all %dms\n",

   "cyclic_demo", time_ms);
diff --git a/common/cyclic.c b/common/cyclic.c
index c62e7fa7d19..ec38fad6775 100644
--- a/common/cyclic.c
+++ b/common/cyclic.c
@@ -26,34 +26,22 @@ struct hlist_head *cyclic_get_list(void)
return (struct hlist_head *)>cyclic_list;
  }
  
-struct cyclic_info *cyclic_register(cyclic_func_t func, uint64_t delay_us,

-   const char *name, void *ctx)
+void cyclic_register(struct cyclic_info 

[PATCH 3/3] cyclic: make clients embed a struct cyclic_info in their own data structure

2024-05-08 Thread Rasmus Villemoes
There are of course not a whole lot of examples in-tree yet, but
before they appear, let's make this API change: Instead of separately
allocating a 'struct cyclic_info', make the users embed such an
instance in their own structure, and make the convention that the
callback simply receives the 'struct cyclic_info *', from which the
clients can get their own data using the container_of() macro.

This has a number of advantages.

First, it means cyclic_register() simply cannot fail, simplifying the
code. The necessary storage will simply be allocated automatically
when the client's own structure is allocated (often via
uclass_priv_auto or similar).

Second, code for which CONFIG_CYCLIC is just an option can more easily
be written without #ifdefs, if we just provide an empty struct
cyclic_info {}. For example, the nested CONFIG_IS_ENABLED()s in
https://lore.kernel.org/u-boot/20240316201416.211480-1-marek.vasut+rene...@mailbox.org/
are mostly due to the existence of the 'struct cyclic_info *' member
being guarded by #ifdef CONFIG_CYCLIC.

And we do probably want to avoid the extra memory overhead of that
member when !CONFIG_CYCLIC. But that is automatic if, instead of a
'struct cyclic_info *', one simply embeds a 'struct cyclic_info',
which will have size 0 when !CONFIG_CYCLIC. Also, the no-op
cyclic_register() function can just unconditionally be called, and the
compiler will see that (1) the callback is referenced, so not emit a
warning for a maybe-unused function and (2) see that it can actually
never be reached, so not emit any code for it.

Signed-off-by: Rasmus Villemoes 
---
 board/Marvell/octeon_nic23/board.c |  9 +---
 cmd/cyclic.c   | 12 +--
 common/cyclic.c| 22 +--
 doc/develop/cyclic.rst | 26 ++-
 drivers/watchdog/wdt-uclass.c  | 33 +
 include/cyclic.h   | 34 +++---
 6 files changed, 64 insertions(+), 72 deletions(-)

diff --git a/board/Marvell/octeon_nic23/board.c 
b/board/Marvell/octeon_nic23/board.c
index bc9332cb74a..74b9c741b7b 100644
--- a/board/Marvell/octeon_nic23/board.c
+++ b/board/Marvell/octeon_nic23/board.c
@@ -357,10 +357,13 @@ int board_late_init(void)
board_configure_qlms();
 
/* Register cyclic function for PCIe FLR fixup */
-   cyclic = cyclic_register(octeon_board_restore_pf, 100,
-"pcie_flr_fix", NULL);
-   if (!cyclic)
+   cyclic = calloc(1, sizeof(*cyclic));
+   if (cyclic) {
+   cyclic_register(cyclic, octeon_board_restore_pf, 100,
+   "pcie_flr_fix");
+   } else {
printf("Registering of cyclic function failed\n");
+   }
 
return 0;
 }
diff --git a/cmd/cyclic.c b/cmd/cyclic.c
index ad7fc3b975e..315546515f0 100644
--- a/cmd/cyclic.c
+++ b/cmd/cyclic.c
@@ -14,14 +14,16 @@
 #include 
 #include 
 #include 
+#include 
 
 struct cyclic_demo_info {
+   struct cyclic_info cyclic;
uint delay_us;
 };
 
-static void cyclic_demo(void *ctx)
+static void cyclic_demo(struct cyclic_info *c)
 {
-   struct cyclic_demo_info *info = ctx;
+   struct cyclic_demo_info *info = container_of(c, struct 
cyclic_demo_info, cyclic);
 
/* Just a small dummy delay here */
udelay(info->delay_us);
@@ -31,7 +33,6 @@ static int do_cyclic_demo(struct cmd_tbl *cmdtp, int flag, 
int argc,
  char *const argv[])
 {
struct cyclic_demo_info *info;
-   struct cyclic_info *cyclic;
uint time_ms;
 
if (argc < 3)
@@ -47,10 +48,7 @@ static int do_cyclic_demo(struct cmd_tbl *cmdtp, int flag, 
int argc,
info->delay_us = simple_strtoul(argv[2], NULL, 0);
 
/* Register demo cyclic function */
-   cyclic = cyclic_register(cyclic_demo, time_ms * 1000, "cyclic_demo",
-info);
-   if (!cyclic)
-   printf("Registering of cyclic_demo failed\n");
+   cyclic_register(>cyclic, cyclic_demo, time_ms * 1000, 
"cyclic_demo");
 
printf("Registered function \"%s\" to be executed all %dms\n",
   "cyclic_demo", time_ms);
diff --git a/common/cyclic.c b/common/cyclic.c
index c62e7fa7d19..ec38fad6775 100644
--- a/common/cyclic.c
+++ b/common/cyclic.c
@@ -26,34 +26,22 @@ struct hlist_head *cyclic_get_list(void)
return (struct hlist_head *)>cyclic_list;
 }
 
-struct cyclic_info *cyclic_register(cyclic_func_t func, uint64_t delay_us,
-   const char *name, void *ctx)
+void cyclic_register(struct cyclic_info *cyclic, cyclic_func_t func,
+uint64_t delay_us, const char *name)
 {
-   struct cyclic_info *cyclic;
-
-   cyclic = calloc(1, sizeof(struct cyclic_info));
-   if (!cyclic) {
-   pr_debug("Memory allocation error\n");
-   return NULL;
-   }
+   memset(cyclic, 0,