linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] counter: Remove struct counter_device::priv
@ 2021-12-21 10:45 Uwe Kleine-König
  2021-12-21 10:45 ` [PATCH 5/8] counter: microchip-tcp-capture: Use container_of instead of " Uwe Kleine-König
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Uwe Kleine-König @ 2021-12-21 10:45 UTC (permalink / raw)
  To: Alexandre Torgue, David Lechner, Fabrice Gasnier, Jarkko Nikula,
	Kamel Bouhara, Maxime Coquelin, Oleksij Rempel,
	Patrick Havelange, Syed Nayyar Waris, William Breathitt Gray
  Cc: linux-arm-kernel, linux-iio, linux-kernel, linux-stm32

Hello,

similar to patch
https://lore.kernel.org/r/4bde7cbd9e43a5909208102094444219d3154466.1640072891.git.vilhelm.gray@gmail.com
the usage of struct counter_device::priv can be replaced by
container_of which improves type safety and code size.

This series depends on above patch, converts the remaining drivers and
finally drops struct counter_device::priv.

This series was compile tested using ARCH=arm allmodconfig with the
following change:

 config 104_QUAD_8
        tristate "ACCES 104-QUAD-8 driver"
-       depends on PC104 && X86
+       depends on PC104 && X86 || COMPILE_TEST
        select ISA_BUS_API

in drivers/counter/Kconfig.

Best regards
Uwe

Uwe Kleine-König (8):
  counter: 104-quad-8: Use container_of instead of struct
    counter_device::priv
  counter: ftm-quaddec: Use container_of instead of struct
    counter_device::priv
  counter: intel-qeb: Use container_of instead of struct
    counter_device::priv
  counter: interrupt-cnt: Use container_of instead of struct
    counter_device::priv
  counter: microchip-tcp-capture: Use container_of instead of struct
    counter_device::priv
  counter: stm32-lptimer-cnt: Use container_of instead of struct
    counter_device::priv
  counter: stm32-timer-cnt: Use container_of instead of struct
    counter_device::priv
  counter: Remove unused member from struct counter_device

 drivers/counter/104-quad-8.c            | 64 +++++++++++++------------
 drivers/counter/ftm-quaddec.c           | 14 ++++--
 drivers/counter/intel-qep.c             | 24 ++++++----
 drivers/counter/interrupt-cnt.c         | 16 ++++---
 drivers/counter/microchip-tcb-capture.c | 18 ++++---
 drivers/counter/stm32-lptimer-cnt.c     | 24 ++++++----
 drivers/counter/stm32-timer-cnt.c       | 24 ++++++----
 drivers/counter/ti-eqep.c               |  1 -
 include/linux/counter.h                 |  3 --
 9 files changed, 106 insertions(+), 82 deletions(-)


base-commit: fa55b7dcdc43c1aa1ba12bca9d2dd4318c2a0dbf
prerequisite-patch-id: 9459ad8bc78190558df9123f8bebe28ca1c396ea
-- 
2.33.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 5/8] counter: microchip-tcp-capture: Use container_of instead of struct counter_device::priv
  2021-12-21 10:45 [PATCH 0/8] counter: Remove struct counter_device::priv Uwe Kleine-König
@ 2021-12-21 10:45 ` Uwe Kleine-König
  2021-12-21 10:45 ` [PATCH 6/8] counter: stm32-lptimer-cnt: " Uwe Kleine-König
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Uwe Kleine-König @ 2021-12-21 10:45 UTC (permalink / raw)
  To: Kamel Bouhara, William Breathitt Gray
  Cc: linux-arm-kernel, linux-iio, linux-kernel

Using counter->priv is a memory read and so more expensive than
container_of which is only an addition.

So container_of is expected to be a tad faster, it's type-safe, and
produces smaller code (ARCH=arm allmodconfig):

	add/remove: 0/0 grow/shrink: 1/6 up/down: 12/-68 (-56)
	Function                                     old     new   delta
	mchp_tc_count_function_write                1016    1028     +12
	mchp_tc_count_action_write                   204     196      -8
	mchp_tc_probe                               1376    1364     -12
	mchp_tc_count_signal_read                    360     348     -12
	mchp_tc_count_read                           264     252     -12
	mchp_tc_count_function_read                  108      96     -12
	mchp_tc_count_action_read                    392     380     -12
	Total: Before=5920, After=5864, chg -0.95%

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/counter/microchip-tcb-capture.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
index 0ab1b2716784..031e79f5f06a 100644
--- a/drivers/counter/microchip-tcb-capture.c
+++ b/drivers/counter/microchip-tcb-capture.c
@@ -32,6 +32,11 @@ struct mchp_tc_data {
 	bool trig_inverted;
 };
 
+static inline struct mchp_tc_data *mchp_tc_from_counter(struct counter_device *counter)
+{
+	return container_of(counter, struct mchp_tc_data, counter);
+}
+
 static const enum counter_function mchp_tc_count_functions[] = {
 	COUNTER_FUNCTION_INCREASE,
 	COUNTER_FUNCTION_QUADRATURE_X4,
@@ -72,7 +77,7 @@ static int mchp_tc_count_function_read(struct counter_device *counter,
 				       struct counter_count *count,
 				       enum counter_function *function)
 {
-	struct mchp_tc_data *const priv = counter->priv;
+	struct mchp_tc_data *const priv = mchp_tc_from_counter(counter);
 
 	if (priv->qdec_mode)
 		*function = COUNTER_FUNCTION_QUADRATURE_X4;
@@ -86,7 +91,7 @@ static int mchp_tc_count_function_write(struct counter_device *counter,
 					struct counter_count *count,
 					enum counter_function function)
 {
-	struct mchp_tc_data *const priv = counter->priv;
+	struct mchp_tc_data *const priv = mchp_tc_from_counter(counter);
 	u32 bmr, cmr;
 
 	regmap_read(priv->regmap, ATMEL_TC_BMR, &bmr);
@@ -148,7 +153,7 @@ static int mchp_tc_count_signal_read(struct counter_device *counter,
 				     struct counter_signal *signal,
 				     enum counter_signal_level *lvl)
 {
-	struct mchp_tc_data *const priv = counter->priv;
+	struct mchp_tc_data *const priv = mchp_tc_from_counter(counter);
 	bool sigstatus;
 	u32 sr;
 
@@ -169,7 +174,7 @@ static int mchp_tc_count_action_read(struct counter_device *counter,
 				     struct counter_synapse *synapse,
 				     enum counter_synapse_action *action)
 {
-	struct mchp_tc_data *const priv = counter->priv;
+	struct mchp_tc_data *const priv = mchp_tc_from_counter(counter);
 	u32 cmr;
 
 	regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), &cmr);
@@ -197,7 +202,7 @@ static int mchp_tc_count_action_write(struct counter_device *counter,
 				      struct counter_synapse *synapse,
 				      enum counter_synapse_action action)
 {
-	struct mchp_tc_data *const priv = counter->priv;
+	struct mchp_tc_data *const priv = mchp_tc_from_counter(counter);
 	u32 edge = ATMEL_TC_ETRGEDG_NONE;
 
 	/* QDEC mode is rising edge only */
@@ -230,7 +235,7 @@ static int mchp_tc_count_action_write(struct counter_device *counter,
 static int mchp_tc_count_read(struct counter_device *counter,
 			      struct counter_count *count, u64 *val)
 {
-	struct mchp_tc_data *const priv = counter->priv;
+	struct mchp_tc_data *const priv = mchp_tc_from_counter(counter);
 	u32 cnt;
 
 	regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CV), &cnt);
@@ -369,7 +374,6 @@ static int mchp_tc_probe(struct platform_device *pdev)
 	priv->counter.counts = mchp_tc_counts;
 	priv->counter.num_signals = ARRAY_SIZE(mchp_tc_count_signals);
 	priv->counter.signals = mchp_tc_count_signals;
-	priv->counter.priv = priv;
 
 	return devm_counter_register(&pdev->dev, &priv->counter);
 }
-- 
2.33.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 6/8] counter: stm32-lptimer-cnt: Use container_of instead of struct counter_device::priv
  2021-12-21 10:45 [PATCH 0/8] counter: Remove struct counter_device::priv Uwe Kleine-König
  2021-12-21 10:45 ` [PATCH 5/8] counter: microchip-tcp-capture: Use container_of instead of " Uwe Kleine-König
@ 2021-12-21 10:45 ` Uwe Kleine-König
  2021-12-21 10:45 ` [PATCH 7/8] counter: stm32-timer-cnt: " Uwe Kleine-König
  2021-12-21 11:12 ` [PATCH 0/8] counter: Remove " Lars-Peter Clausen
  3 siblings, 0 replies; 10+ messages in thread
From: Uwe Kleine-König @ 2021-12-21 10:45 UTC (permalink / raw)
  To: Fabrice Gasnier, William Breathitt Gray, Maxime Coquelin,
	Alexandre Torgue
  Cc: linux-iio, linux-stm32, linux-arm-kernel, linux-kernel

Using counter->priv is a memory read and so more expensive than
container_of which is only an addition. (In this case even a noop
because the offset is 0.)

So container_of is expected to be a tad faster, it's type-safe, and
produces smaller code (ARCH=arm allmodconfig):

	add/remove: 0/0 grow/shrink: 0/10 up/down: 0/-140 (-140)
	Function                                     old     new   delta
	stm32_lptim_cnt_read                         272     260     -12
	stm32_lptim_cnt_probe                        528     516     -12
	stm32_lptim_cnt_function_write               420     408     -12
	stm32_lptim_cnt_function_read                184     172     -12
	stm32_lptim_cnt_enable_write                 436     424     -12
	stm32_lptim_cnt_enable_read                  312     300     -12
	stm32_lptim_cnt_ceiling_write                368     356     -12
	stm32_lptim_cnt_ceiling_read                  84      72     -12
	stm32_lptim_cnt_action_read                  388     376     -12
	stm32_lptim_cnt_action_write                 576     544     -32
	Total: Before=6458, After=6318, chg -2.17%

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/counter/stm32-lptimer-cnt.c | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/drivers/counter/stm32-lptimer-cnt.c b/drivers/counter/stm32-lptimer-cnt.c
index 5168833b1fdf..c6eb3071571f 100644
--- a/drivers/counter/stm32-lptimer-cnt.c
+++ b/drivers/counter/stm32-lptimer-cnt.c
@@ -30,6 +30,11 @@ struct stm32_lptim_cnt {
 	bool enabled;
 };
 
+static inline struct stm32_lptim_cnt *stm32_lptim_from_counter(struct counter_device *counter)
+{
+	return container_of(counter, struct stm32_lptim_cnt, counter);
+}
+
 static int stm32_lptim_is_enabled(struct stm32_lptim_cnt *priv)
 {
 	u32 val;
@@ -141,7 +146,7 @@ static const enum counter_synapse_action stm32_lptim_cnt_synapse_actions[] = {
 static int stm32_lptim_cnt_read(struct counter_device *counter,
 				struct counter_count *count, u64 *val)
 {
-	struct stm32_lptim_cnt *const priv = counter->priv;
+	struct stm32_lptim_cnt *const priv = stm32_lptim_from_counter(counter);
 	u32 cnt;
 	int ret;
 
@@ -158,7 +163,7 @@ static int stm32_lptim_cnt_function_read(struct counter_device *counter,
 					 struct counter_count *count,
 					 enum counter_function *function)
 {
-	struct stm32_lptim_cnt *const priv = counter->priv;
+	struct stm32_lptim_cnt *const priv = stm32_lptim_from_counter(counter);
 
 	if (!priv->quadrature_mode) {
 		*function = COUNTER_FUNCTION_INCREASE;
@@ -177,7 +182,7 @@ static int stm32_lptim_cnt_function_write(struct counter_device *counter,
 					  struct counter_count *count,
 					  enum counter_function function)
 {
-	struct stm32_lptim_cnt *const priv = counter->priv;
+	struct stm32_lptim_cnt *const priv = stm32_lptim_from_counter(counter);
 
 	if (stm32_lptim_is_enabled(priv))
 		return -EBUSY;
@@ -200,7 +205,7 @@ static int stm32_lptim_cnt_enable_read(struct counter_device *counter,
 				       struct counter_count *count,
 				       u8 *enable)
 {
-	struct stm32_lptim_cnt *const priv = counter->priv;
+	struct stm32_lptim_cnt *const priv = stm32_lptim_from_counter(counter);
 	int ret;
 
 	ret = stm32_lptim_is_enabled(priv);
@@ -216,7 +221,7 @@ static int stm32_lptim_cnt_enable_write(struct counter_device *counter,
 					struct counter_count *count,
 					u8 enable)
 {
-	struct stm32_lptim_cnt *const priv = counter->priv;
+	struct stm32_lptim_cnt *const priv = stm32_lptim_from_counter(counter);
 	int ret;
 
 	/* Check nobody uses the timer, or already disabled/enabled */
@@ -241,7 +246,7 @@ static int stm32_lptim_cnt_ceiling_read(struct counter_device *counter,
 					struct counter_count *count,
 					u64 *ceiling)
 {
-	struct stm32_lptim_cnt *const priv = counter->priv;
+	struct stm32_lptim_cnt *const priv = stm32_lptim_from_counter(counter);
 
 	*ceiling = priv->ceiling;
 
@@ -252,7 +257,7 @@ static int stm32_lptim_cnt_ceiling_write(struct counter_device *counter,
 					 struct counter_count *count,
 					 u64 ceiling)
 {
-	struct stm32_lptim_cnt *const priv = counter->priv;
+	struct stm32_lptim_cnt *const priv = stm32_lptim_from_counter(counter);
 
 	if (stm32_lptim_is_enabled(priv))
 		return -EBUSY;
@@ -277,7 +282,7 @@ static int stm32_lptim_cnt_action_read(struct counter_device *counter,
 				       struct counter_synapse *synapse,
 				       enum counter_synapse_action *action)
 {
-	struct stm32_lptim_cnt *const priv = counter->priv;
+	struct stm32_lptim_cnt *const priv = stm32_lptim_from_counter(counter);
 	enum counter_function function;
 	int err;
 
@@ -321,7 +326,7 @@ static int stm32_lptim_cnt_action_write(struct counter_device *counter,
 					struct counter_synapse *synapse,
 					enum counter_synapse_action action)
 {
-	struct stm32_lptim_cnt *const priv = counter->priv;
+	struct stm32_lptim_cnt *const priv = stm32_lptim_from_counter(counter);
 	enum counter_function function;
 	int err;
 
@@ -438,7 +443,6 @@ static int stm32_lptim_cnt_probe(struct platform_device *pdev)
 	}
 	priv->counter.num_counts = 1;
 	priv->counter.signals = stm32_lptim_cnt_signals;
-	priv->counter.priv = priv;
 
 	platform_set_drvdata(pdev, priv);
 
-- 
2.33.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 7/8] counter: stm32-timer-cnt: Use container_of instead of struct counter_device::priv
  2021-12-21 10:45 [PATCH 0/8] counter: Remove struct counter_device::priv Uwe Kleine-König
  2021-12-21 10:45 ` [PATCH 5/8] counter: microchip-tcp-capture: Use container_of instead of " Uwe Kleine-König
  2021-12-21 10:45 ` [PATCH 6/8] counter: stm32-lptimer-cnt: " Uwe Kleine-König
@ 2021-12-21 10:45 ` Uwe Kleine-König
  2021-12-21 11:12 ` [PATCH 0/8] counter: Remove " Lars-Peter Clausen
  3 siblings, 0 replies; 10+ messages in thread
From: Uwe Kleine-König @ 2021-12-21 10:45 UTC (permalink / raw)
  To: Fabrice Gasnier, William Breathitt Gray, Maxime Coquelin,
	Alexandre Torgue
  Cc: linux-iio, linux-stm32, linux-arm-kernel, linux-kernel

Using counter->priv is a memory read and so more expensive than
container_of which is only an addition. (In this case even a noop
because the offset is 0.)

So container_of is expected to be a tad faster, it's type-safe, and
produces smaller code (ARCH=arm allmodconfig):

	add/remove: 0/0 grow/shrink: 0/11 up/down: 0/-132 (-132)
	Function                                     old     new   delta
	stm32_timer_cnt_probe                        436     424     -12
	stm32_count_write                            312     300     -12
	stm32_count_read                             236     224     -12
	stm32_count_function_write                   492     480     -12
	stm32_count_function_read                    396     384     -12
	stm32_count_enable_write                     488     476     -12
	stm32_count_enable_read                      236     224     -12
	stm32_count_direction_read                   240     228     -12
	stm32_count_ceiling_write                    200     188     -12
	stm32_count_ceiling_read                     236     224     -12
	stm32_action_read                            492     480     -12
	Total: Before=5504, After=5372, chg -2.40%

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/counter/stm32-timer-cnt.c | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/drivers/counter/stm32-timer-cnt.c b/drivers/counter/stm32-timer-cnt.c
index 0546e932db0c..ac0bea6ce690 100644
--- a/drivers/counter/stm32-timer-cnt.c
+++ b/drivers/counter/stm32-timer-cnt.c
@@ -37,6 +37,11 @@ struct stm32_timer_cnt {
 	struct stm32_timer_regs bak;
 };
 
+static inline struct stm32_timer_cnt *stm32_count_from_counter(struct counter_device *counter)
+{
+	return container_of(counter, struct stm32_timer_cnt, counter);
+}
+
 static const enum counter_function stm32_count_functions[] = {
 	COUNTER_FUNCTION_INCREASE,
 	COUNTER_FUNCTION_QUADRATURE_X2_A,
@@ -47,7 +52,7 @@ static const enum counter_function stm32_count_functions[] = {
 static int stm32_count_read(struct counter_device *counter,
 			    struct counter_count *count, u64 *val)
 {
-	struct stm32_timer_cnt *const priv = counter->priv;
+	struct stm32_timer_cnt *const priv = stm32_count_from_counter(counter);
 	u32 cnt;
 
 	regmap_read(priv->regmap, TIM_CNT, &cnt);
@@ -59,7 +64,7 @@ static int stm32_count_read(struct counter_device *counter,
 static int stm32_count_write(struct counter_device *counter,
 			     struct counter_count *count, const u64 val)
 {
-	struct stm32_timer_cnt *const priv = counter->priv;
+	struct stm32_timer_cnt *const priv = stm32_count_from_counter(counter);
 	u32 ceiling;
 
 	regmap_read(priv->regmap, TIM_ARR, &ceiling);
@@ -73,7 +78,7 @@ static int stm32_count_function_read(struct counter_device *counter,
 				     struct counter_count *count,
 				     enum counter_function *function)
 {
-	struct stm32_timer_cnt *const priv = counter->priv;
+	struct stm32_timer_cnt *const priv = stm32_count_from_counter(counter);
 	u32 smcr;
 
 	regmap_read(priv->regmap, TIM_SMCR, &smcr);
@@ -100,7 +105,7 @@ static int stm32_count_function_write(struct counter_device *counter,
 				      struct counter_count *count,
 				      enum counter_function function)
 {
-	struct stm32_timer_cnt *const priv = counter->priv;
+	struct stm32_timer_cnt *const priv = stm32_count_from_counter(counter);
 	u32 cr1, sms;
 
 	switch (function) {
@@ -140,7 +145,7 @@ static int stm32_count_direction_read(struct counter_device *counter,
 				      struct counter_count *count,
 				      enum counter_count_direction *direction)
 {
-	struct stm32_timer_cnt *const priv = counter->priv;
+	struct stm32_timer_cnt *const priv = stm32_count_from_counter(counter);
 	u32 cr1;
 
 	regmap_read(priv->regmap, TIM_CR1, &cr1);
@@ -153,7 +158,7 @@ static int stm32_count_direction_read(struct counter_device *counter,
 static int stm32_count_ceiling_read(struct counter_device *counter,
 				    struct counter_count *count, u64 *ceiling)
 {
-	struct stm32_timer_cnt *const priv = counter->priv;
+	struct stm32_timer_cnt *const priv = stm32_count_from_counter(counter);
 	u32 arr;
 
 	regmap_read(priv->regmap, TIM_ARR, &arr);
@@ -166,7 +171,7 @@ static int stm32_count_ceiling_read(struct counter_device *counter,
 static int stm32_count_ceiling_write(struct counter_device *counter,
 				     struct counter_count *count, u64 ceiling)
 {
-	struct stm32_timer_cnt *const priv = counter->priv;
+	struct stm32_timer_cnt *const priv = stm32_count_from_counter(counter);
 
 	if (ceiling > priv->max_arr)
 		return -ERANGE;
@@ -181,7 +186,7 @@ static int stm32_count_ceiling_write(struct counter_device *counter,
 static int stm32_count_enable_read(struct counter_device *counter,
 				   struct counter_count *count, u8 *enable)
 {
-	struct stm32_timer_cnt *const priv = counter->priv;
+	struct stm32_timer_cnt *const priv = stm32_count_from_counter(counter);
 	u32 cr1;
 
 	regmap_read(priv->regmap, TIM_CR1, &cr1);
@@ -194,7 +199,7 @@ static int stm32_count_enable_read(struct counter_device *counter,
 static int stm32_count_enable_write(struct counter_device *counter,
 				    struct counter_count *count, u8 enable)
 {
-	struct stm32_timer_cnt *const priv = counter->priv;
+	struct stm32_timer_cnt *const priv = stm32_count_from_counter(counter);
 	u32 cr1;
 
 	if (enable) {
@@ -336,7 +341,6 @@ static int stm32_timer_cnt_probe(struct platform_device *pdev)
 	priv->counter.num_counts = 1;
 	priv->counter.signals = stm32_signals;
 	priv->counter.num_signals = ARRAY_SIZE(stm32_signals);
-	priv->counter.priv = priv;
 
 	platform_set_drvdata(pdev, priv);
 
-- 
2.33.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/8] counter: Remove struct counter_device::priv
  2021-12-21 10:45 [PATCH 0/8] counter: Remove struct counter_device::priv Uwe Kleine-König
                   ` (2 preceding siblings ...)
  2021-12-21 10:45 ` [PATCH 7/8] counter: stm32-timer-cnt: " Uwe Kleine-König
@ 2021-12-21 11:12 ` Lars-Peter Clausen
  2021-12-21 11:35   ` Uwe Kleine-König
  3 siblings, 1 reply; 10+ messages in thread
From: Lars-Peter Clausen @ 2021-12-21 11:12 UTC (permalink / raw)
  To: Uwe Kleine-König, Alexandre Torgue, David Lechner,
	Fabrice Gasnier, Jarkko Nikula, Kamel Bouhara, Maxime Coquelin,
	Oleksij Rempel, Patrick Havelange, Syed Nayyar Waris,
	William Breathitt Gray
  Cc: linux-arm-kernel, linux-iio, linux-kernel, linux-stm32

On 12/21/21 11:45 AM, Uwe Kleine-König wrote:
> Hello,
>
> similar to patch
> https://lore.kernel.org/r/4bde7cbd9e43a5909208102094444219d3154466.1640072891.git.vilhelm.gray@gmail.com
> the usage of struct counter_device::priv can be replaced by
> container_of which improves type safety and code size.
>
> This series depends on above patch, converts the remaining drivers and
> finally drops struct counter_device::priv.

Not sure if this is such a good idea. struct counter_device should not 
be embedded in the drivers state struct in the first place.

struct counter_device contains a struct device, which is a reference 
counted object. But by embedding it in the driver state struct the life 
time of both the struct counter_device and and struct device are bound 
to the life time of the driver state struct.

Which means the struct device memory can get freed before the last 
reference is dropped, which leads to a use-after-free and undefined 
behavior.

The framework should be changed to rather then embedding the struct 
counter_device in the state struct to just have a pointer to it. With 
the struct counter_device having its own allocation that will be freed 
when the last reference to the struct device is dropped.

- Lars


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/8] counter: Remove struct counter_device::priv
  2021-12-21 11:12 ` [PATCH 0/8] counter: Remove " Lars-Peter Clausen
@ 2021-12-21 11:35   ` Uwe Kleine-König
  2021-12-21 12:04     ` Lars-Peter Clausen
  0 siblings, 1 reply; 10+ messages in thread
From: Uwe Kleine-König @ 2021-12-21 11:35 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Alexandre Torgue, David Lechner, Fabrice Gasnier, Jarkko Nikula,
	Kamel Bouhara, Maxime Coquelin, Oleksij Rempel,
	Patrick Havelange, Syed Nayyar Waris, William Breathitt Gray,
	linux-arm-kernel, linux-iio, linux-kernel, linux-stm32


[-- Attachment #1.1: Type: text/plain, Size: 2012 bytes --]

Hello Lars,

On Tue, Dec 21, 2021 at 12:12:12PM +0100, Lars-Peter Clausen wrote:
> On 12/21/21 11:45 AM, Uwe Kleine-König wrote:
> > similar to patch
> > https://lore.kernel.org/r/4bde7cbd9e43a5909208102094444219d3154466.1640072891.git.vilhelm.gray@gmail.com
> > the usage of struct counter_device::priv can be replaced by
> > container_of which improves type safety and code size.
> > 
> > This series depends on above patch, converts the remaining drivers and
> > finally drops struct counter_device::priv.
> 
> Not sure if this is such a good idea. struct counter_device should not be
> embedded in the drivers state struct in the first place.

Just to mention it: My patch series didn't change this, this was already
broken before.

> struct counter_device contains a struct device, which is a reference counted
> object. But by embedding it in the driver state struct the life time of both
> the struct counter_device and and struct device are bound to the life time
> of the driver state struct.
> 
> Which means the struct device memory can get freed before the last reference
> is dropped, which leads to a use-after-free and undefined behavior.

Well, the driver struct is allocated using devm_kzalloc for all drivers.
So I think it's not *very* urgent to fix. Still you're right, this
should be addressed.
 
> The framework should be changed to rather then embedding the struct
> counter_device in the state struct to just have a pointer to it. With the
> struct counter_device having its own allocation that will be freed when the
> last reference to the struct device is dropped.

My favourite would be to implement a counter_device_alloc /
counter_device_add approach, similar to what spi_alloc_controller and
alloc_etherdev do. The downside is that this isn't typesafe either :-\

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | https://www.pengutronix.de/ |

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/8] counter: Remove struct counter_device::priv
  2021-12-21 11:35   ` Uwe Kleine-König
@ 2021-12-21 12:04     ` Lars-Peter Clausen
  2021-12-21 13:22       ` Uwe Kleine-König
  2021-12-22 17:51       ` Uwe Kleine-König
  0 siblings, 2 replies; 10+ messages in thread
From: Lars-Peter Clausen @ 2021-12-21 12:04 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Alexandre Torgue, David Lechner, Fabrice Gasnier, Jarkko Nikula,
	Kamel Bouhara, Maxime Coquelin, Oleksij Rempel,
	Patrick Havelange, Syed Nayyar Waris, William Breathitt Gray,
	linux-arm-kernel, linux-iio, linux-kernel, linux-stm32

On 12/21/21 12:35 PM, Uwe Kleine-König wrote:
> Hello Lars,
>
> On Tue, Dec 21, 2021 at 12:12:12PM +0100, Lars-Peter Clausen wrote:
>> On 12/21/21 11:45 AM, Uwe Kleine-König wrote:
>>> similar to patch
>>> https://lore.kernel.org/r/4bde7cbd9e43a5909208102094444219d3154466.1640072891.git.vilhelm.gray@gmail.com
>>> the usage of struct counter_device::priv can be replaced by
>>> container_of which improves type safety and code size.
>>>
>>> This series depends on above patch, converts the remaining drivers and
>>> finally drops struct counter_device::priv.
>> Not sure if this is such a good idea. struct counter_device should not be
>> embedded in the drivers state struct in the first place.
> Just to mention it: My patch series didn't change this, this was already
> broken before.
I know, but this series has to be reverted when the framework is fixed.
>
>> struct counter_device contains a struct device, which is a reference counted
>> object. But by embedding it in the driver state struct the life time of both
>> the struct counter_device and and struct device are bound to the life time
>> of the driver state struct.
>>
>> Which means the struct device memory can get freed before the last reference
>> is dropped, which leads to a use-after-free and undefined behavior.
> Well, the driver struct is allocated using devm_kzalloc for all drivers.

devm_kzalloc() doesn't make a difference. The managed memory is freed 
when the parent device is unbound/removed. There may very well be 
reference to the counter_device at this point.

> So I think it's not *very* urgent to fix. Still you're right, this
> should be addressed.

Yes and no, this can trivially be used for privilege escalation, but 
then again on systems with a counter_device probably everything runs as 
root anyway.

>   
>> The framework should be changed to rather then embedding the struct
>> counter_device in the state struct to just have a pointer to it. With the
>> struct counter_device having its own allocation that will be freed when the
>> last reference to the struct device is dropped.
> My favourite would be to implement a counter_device_alloc /
> counter_device_add approach, similar to what spi_alloc_controller and
> alloc_etherdev do. The downside is that this isn't typesafe either :-\



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/8] counter: Remove struct counter_device::priv
  2021-12-21 12:04     ` Lars-Peter Clausen
@ 2021-12-21 13:22       ` Uwe Kleine-König
  2021-12-21 14:12         ` Lars-Peter Clausen
  2021-12-22 17:51       ` Uwe Kleine-König
  1 sibling, 1 reply; 10+ messages in thread
From: Uwe Kleine-König @ 2021-12-21 13:22 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Alexandre Torgue, David Lechner, Fabrice Gasnier, Jarkko Nikula,
	Kamel Bouhara, Maxime Coquelin, Oleksij Rempel,
	Patrick Havelange, Syed Nayyar Waris, William Breathitt Gray,
	linux-arm-kernel, linux-iio, linux-kernel, linux-stm32


[-- Attachment #1.1: Type: text/plain, Size: 1333 bytes --]

On Tue, Dec 21, 2021 at 01:04:50PM +0100, Lars-Peter Clausen wrote:
> On 12/21/21 12:35 PM, Uwe Kleine-König wrote:
> > On Tue, Dec 21, 2021 at 12:12:12PM +0100, Lars-Peter Clausen wrote:
> > > On 12/21/21 11:45 AM, Uwe Kleine-König wrote:
> > > > similar to patch
> > > > https://lore.kernel.org/r/4bde7cbd9e43a5909208102094444219d3154466.1640072891.git.vilhelm.gray@gmail.com
> > > > the usage of struct counter_device::priv can be replaced by
> > > > container_of which improves type safety and code size.
> > > > 
> > > > This series depends on above patch, converts the remaining drivers and
> > > > finally drops struct counter_device::priv.
> > > Not sure if this is such a good idea. struct counter_device should not be
> > > embedded in the drivers state struct in the first place.
> > Just to mention it: My patch series didn't change this, this was already
> > broken before.
> 
> I know, but this series has to be reverted when the framework is fixed.

All drivers have to be touched. With my patch series you have to modify
one function in each driver, without my patch you have touch nearly
every function.

*shrug*

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | https://www.pengutronix.de/ |

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/8] counter: Remove struct counter_device::priv
  2021-12-21 13:22       ` Uwe Kleine-König
@ 2021-12-21 14:12         ` Lars-Peter Clausen
  0 siblings, 0 replies; 10+ messages in thread
From: Lars-Peter Clausen @ 2021-12-21 14:12 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Alexandre Torgue, David Lechner, Fabrice Gasnier, Jarkko Nikula,
	Kamel Bouhara, Maxime Coquelin, Oleksij Rempel,
	Patrick Havelange, Syed Nayyar Waris, William Breathitt Gray,
	linux-arm-kernel, linux-iio, linux-kernel, linux-stm32

On 12/21/21 2:22 PM, Uwe Kleine-König wrote:
> On Tue, Dec 21, 2021 at 01:04:50PM +0100, Lars-Peter Clausen wrote:
>> On 12/21/21 12:35 PM, Uwe Kleine-König wrote:
>>> On Tue, Dec 21, 2021 at 12:12:12PM +0100, Lars-Peter Clausen wrote:
>>>> On 12/21/21 11:45 AM, Uwe Kleine-König wrote:
>>>>> similar to patch
>>>>> https://lore.kernel.org/r/4bde7cbd9e43a5909208102094444219d3154466.1640072891.git.vilhelm.gray@gmail.com
>>>>> the usage of struct counter_device::priv can be replaced by
>>>>> container_of which improves type safety and code size.
>>>>>
>>>>> This series depends on above patch, converts the remaining drivers and
>>>>> finally drops struct counter_device::priv.
>>>> Not sure if this is such a good idea. struct counter_device should not be
>>>> embedded in the drivers state struct in the first place.
>>> Just to mention it: My patch series didn't change this, this was already
>>> broken before.
>> I know, but this series has to be reverted when the framework is fixed.
> All drivers have to be touched. With my patch series you have to modify
> one function in each driver, without my patch you have touch nearly
> every function.
>
I'm not so sure. I don't see how you have to modify every function. 
You'd keep using priv to get a pointer to the state struct.

That said having a centralized function in each driver to get the state 
struct from the counter device doesn't hurt either.



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/8] counter: Remove struct counter_device::priv
  2021-12-21 12:04     ` Lars-Peter Clausen
  2021-12-21 13:22       ` Uwe Kleine-König
@ 2021-12-22 17:51       ` Uwe Kleine-König
  1 sibling, 0 replies; 10+ messages in thread
From: Uwe Kleine-König @ 2021-12-22 17:51 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Alexandre Torgue, David Lechner, Fabrice Gasnier, Jarkko Nikula,
	Kamel Bouhara, Maxime Coquelin, Oleksij Rempel,
	Patrick Havelange, Syed Nayyar Waris, William Breathitt Gray,
	linux-arm-kernel, linux-iio, linux-kernel, linux-stm32


[-- Attachment #1.1: Type: text/plain, Size: 2985 bytes --]

Hello,

On Tue, Dec 21, 2021 at 01:04:50PM +0100, Lars-Peter Clausen wrote:
> On 12/21/21 12:35 PM, Uwe Kleine-König wrote:
> > On Tue, Dec 21, 2021 at 12:12:12PM +0100, Lars-Peter Clausen wrote:
> > > On 12/21/21 11:45 AM, Uwe Kleine-König wrote:
> > > > similar to patch
> > > > https://lore.kernel.org/r/4bde7cbd9e43a5909208102094444219d3154466.1640072891.git.vilhelm.gray@gmail.com
> > > > the usage of struct counter_device::priv can be replaced by
> > > > container_of which improves type safety and code size.
> > > > 
> > > > This series depends on above patch, converts the remaining drivers and
> > > > finally drops struct counter_device::priv.
> > > Not sure if this is such a good idea. struct counter_device should not be
> > > embedded in the drivers state struct in the first place.
> > Just to mention it: My patch series didn't change this, this was already
> > broken before.
> I know, but this series has to be reverted when the framework is fixed.
> > 
> > > struct counter_device contains a struct device, which is a reference counted
> > > object. But by embedding it in the driver state struct the life time of both
> > > the struct counter_device and and struct device are bound to the life time
> > > of the driver state struct.
> > > 
> > > Which means the struct device memory can get freed before the last reference
> > > is dropped, which leads to a use-after-free and undefined behavior.
> > Well, the driver struct is allocated using devm_kzalloc for all drivers.
> 
> devm_kzalloc() doesn't make a difference. The managed memory is freed when
> the parent device is unbound/removed. There may very well be reference to
> the counter_device at this point.
> 
> > So I think it's not *very* urgent to fix. Still you're right, this
> > should be addressed.
> 
> Yes and no, this can trivially be used for privilege escalation, but then
> again on systems with a counter_device probably everything runs as root
> anyway.

I could provoke an oops with the following shell command:


	{ sleep 5; echo bang; } > /dev/counter0 & sleep 1; echo 40000000.timer:counter > /sys/bus/platform/drivers/stm32-timer-counter/unbind

I have a protype here to split counter_register() into counter_alloc() +
counter_add(), but I didn't convert a driver to it yet. If you want to
take a look, it's currently available from

	https://git.pengutronix.de/git/ukl/linux counter-dev-livetime

(or if you prefer a webif:

	https://git.pengutronix.de/cgit/ukl/linux/log/?h=counter-dev-livetime

). I planned to just invest a two or so hours to fix this. But the plan
failed (one reason is that v5.16-rc6 failed to boot on the stm32mp1 I
work on and I bisected that first.)

Maybe I find some time between the years to get this forward a bit.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | https://www.pengutronix.de/ |

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-12-22 17:53 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-21 10:45 [PATCH 0/8] counter: Remove struct counter_device::priv Uwe Kleine-König
2021-12-21 10:45 ` [PATCH 5/8] counter: microchip-tcp-capture: Use container_of instead of " Uwe Kleine-König
2021-12-21 10:45 ` [PATCH 6/8] counter: stm32-lptimer-cnt: " Uwe Kleine-König
2021-12-21 10:45 ` [PATCH 7/8] counter: stm32-timer-cnt: " Uwe Kleine-König
2021-12-21 11:12 ` [PATCH 0/8] counter: Remove " Lars-Peter Clausen
2021-12-21 11:35   ` Uwe Kleine-König
2021-12-21 12:04     ` Lars-Peter Clausen
2021-12-21 13:22       ` Uwe Kleine-König
2021-12-21 14:12         ` Lars-Peter Clausen
2021-12-22 17:51       ` Uwe Kleine-König

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).