All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sean Young <sean@mess.org>
To: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
Cc: "Maíra Canal" <maira.canal@usp.br>,
	lkp@intel.com, mchehab@kernel.org, thierry.reding@gmail.com,
	lee.jones@linaro.org, llvm@lists.linux.dev,
	kbuild-all@lists.01.org, linux-media@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-pwm@vger.kernel.org
Subject: Re: [PATCH v4] media: rc: pwm-ir-tx: Switch to atomic PWM API
Date: Thu, 28 Oct 2021 13:26:10 +0100	[thread overview]
Message-ID: <20211028122610.GA18767@gofer.mess.org> (raw)
In-Reply-To: <20211028111535.x7xgz7domx2lpyfh@pengutronix.de>

Hi Uwe,

On Thu, Oct 28, 2021 at 01:15:35PM +0200, Uwe Kleine-König wrote:
> On Thu, Oct 28, 2021 at 10:14:42AM +0100, Sean Young wrote:
> > On Thu, Oct 28, 2021 at 08:45:13AM +0200, Uwe Kleine-König wrote:
> > > The conversion is right (I think),
> > 
> > We still have the problem that the pwm drivers calculate the period
> > incorrectly by rounding down (except pwm-bcm2835). So the period is not
> > as good as it could be in most cases, but this driver can't do anything
> > about that.
> 
> Yeah, some time ago I started coding a round_state function
> (wip at
> https://git.pengutronix.de/cgit/ukl/linux/commit/?h=pwm-wip&id=ae348eb6a55d6526f30ef4a49819197d9616391e)
> but this was pushed down on my todo-list by more important stuff.

That looks great, thank you for working on that!

> If you want to experiment with that ...

I will have a look.

> > > note this could be optimized a bit
> > > further: state.period only depends on carrier which rarely changes, so
> > > the calculation could be done in pwm_ir_set_carrier(). Ditto for duty
> > > which only depends on state.period and pwm_ir->duty_cycle. (This is for
> > > a separate commit though.)
> > 
> > I'm not sure what caching this is much of a win. The calculation is a few
> > instructions, so you're not winning in the way of speed. On the flip side
> > you use more memory since pwm_state has to be kmalloc() rather than existing
> 
> I tested a bit with this patch on top of Maíra's:
> 
> 	diff --git a/drivers/media/rc/pwm-ir-tx.c b/drivers/media/rc/pwm-ir-tx.c
> 	index 105a9c24f1e3..7585c21775bc 100644
> 	--- a/drivers/media/rc/pwm-ir-tx.c
> 	+++ b/drivers/media/rc/pwm-ir-tx.c
> 	@@ -17,7 +17,7 @@
> 	 
> 	 struct pwm_ir {
> 		struct pwm_device *pwm;
> 	-	unsigned int carrier;
> 	+	struct pwm_state state;
> 		unsigned int duty_cycle;
> 	 };
> 	 
> 	@@ -32,6 +32,7 @@ static int pwm_ir_set_duty_cycle(struct rc_dev *dev, u32 duty_cycle)
> 		struct pwm_ir *pwm_ir = dev->priv;
> 	 
> 		pwm_ir->duty_cycle = duty_cycle;
> 	+	pwm_set_relative_duty_cycle(&pwm_ir->state, pwm_ir->duty_cycle, 100);
> 	 
> 		return 0;
> 	 }
> 	@@ -43,7 +44,8 @@ static int pwm_ir_set_carrier(struct rc_dev *dev, u32 carrier)
> 		if (!carrier)
> 			return -EINVAL;
> 	 
> 	-	pwm_ir->carrier = carrier;
> 	+	pwm_ir->state.period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, carrier);
> 	+	pwm_set_relative_duty_cycle(&pwm_ir->state, pwm_ir->duty_cycle, 100);
> 	 
> 		return 0;
> 	 }
> 	@@ -53,21 +55,15 @@ static int pwm_ir_tx(struct rc_dev *dev, unsigned int *txbuf,
> 	 {
> 		struct pwm_ir *pwm_ir = dev->priv;
> 		struct pwm_device *pwm = pwm_ir->pwm;
> 	-	struct pwm_state state;
> 		int i;
> 		ktime_t edge;
> 		long delta;
> 	 
> 	-	pwm_init_state(pwm, &state);
> 	-
> 	-	state.period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, pwm_ir->carrier);
> 	-	pwm_set_relative_duty_cycle(&state, pwm_ir->duty_cycle, 100);
> 	-
> 		edge = ktime_get();
> 	 
> 		for (i = 0; i < count; i++) {
> 	-		state.enabled = !(i % 2);
> 	-		pwm_apply_state(pwm, &state);
> 	+		pwm_ir->state.enabled = !(i % 2);
> 	+		pwm_apply_state(pwm, &pwm_ir->state);
> 	 
> 			edge = ktime_add_us(edge, txbuf[i]);
> 			delta = ktime_us_delta(edge, ktime_get());
> 	@@ -75,8 +71,8 @@ static int pwm_ir_tx(struct rc_dev *dev, unsigned int *txbuf,
> 				usleep_range(delta, delta + 10);
> 		}
> 	 
> 	-	state.enabled = false;
> 	-	pwm_apply_state(pwm, &state);
> 	+	pwm_ir->state.enabled = false;
> 	+	pwm_apply_state(pwm, &pwm_ir->state);
> 	 
> 		return count;
> 	 }
> 	@@ -95,8 +91,9 @@ static int pwm_ir_probe(struct platform_device *pdev)
> 		if (IS_ERR(pwm_ir->pwm))
> 			return PTR_ERR(pwm_ir->pwm);
> 	 
> 	-	pwm_ir->carrier = 38000;
> 	-	pwm_ir->duty_cycle = 50;
> 	+	pwm_ir->state.duty_cycle = 50;
> 	+	pwm_init_state(pwm_ir->pwm, &pwm_ir->state);
> 	+	pwm_ir_set_carrier(rcdev, 38000);
> 	 
> 		rcdev = devm_rc_allocate_device(&pdev->dev, RC_DRIVER_IR_RAW_TX);
> 		if (!rcdev)
> 
> bloat-o-meter reports (for an arm allmodconfig build)
> 
> 	add/remove: 0/0 grow/shrink: 3/1 up/down: 644/-396 (248)
> 	Function                                     old     new   delta
> 	pwm_ir_probe                                 372     676    +304
> 	pwm_ir_set_carrier                           108     292    +184
> 	pwm_ir_set_duty_cycle                         68     224    +156
> 	pwm_ir_tx                                    908     512    -396
> 	Total: Before=2302, After=2550, chg +10.77%

So 248 bytes more after your changes.

> struct pwm_ir increases from 12 bytes to 40 bytes.
> 
> The stack space required by pwm_ir_tx decreases from 60 to 36
> 
> I don't know exactly how kmalloc works internally. Maybe allocating a
> structure of size 40 bytes doesn't need more memory than a structure of
> size 12?
> 
> I didn't check how runtimes change, but the size decrease of pwm_ir_tx()
> is nice and might save a bit of runtime.

I'm not following, how is this decreasing runtime? 

> Probably it depends on your focus if this change is good for you or not.

Decreasing size is of course a good thing.

> > just on the stack, and both ioctl handlers and the probe function need to
> > recalculate the period/duty cycle, so there is a slight increase in code size.
> > 
> > This change does not improve anything measurably and only increases code
> > complexity.
> 
> You did measure?

Thanks for prototyping this.


Sean

WARNING: multiple messages have this Message-ID (diff)
From: Sean Young <sean@mess.org>
To: kbuild-all@lists.01.org
Subject: Re: [PATCH v4] media: rc: pwm-ir-tx: Switch to atomic PWM API
Date: Thu, 28 Oct 2021 13:26:10 +0100	[thread overview]
Message-ID: <20211028122610.GA18767@gofer.mess.org> (raw)
In-Reply-To: <20211028111535.x7xgz7domx2lpyfh@pengutronix.de>

[-- Attachment #1: Type: text/plain, Size: 5493 bytes --]

Hi Uwe,

On Thu, Oct 28, 2021 at 01:15:35PM +0200, Uwe Kleine-König wrote:
> On Thu, Oct 28, 2021 at 10:14:42AM +0100, Sean Young wrote:
> > On Thu, Oct 28, 2021 at 08:45:13AM +0200, Uwe Kleine-König wrote:
> > > The conversion is right (I think),
> > 
> > We still have the problem that the pwm drivers calculate the period
> > incorrectly by rounding down (except pwm-bcm2835). So the period is not
> > as good as it could be in most cases, but this driver can't do anything
> > about that.
> 
> Yeah, some time ago I started coding a round_state function
> (wip at
> https://git.pengutronix.de/cgit/ukl/linux/commit/?h=pwm-wip&id=ae348eb6a55d6526f30ef4a49819197d9616391e)
> but this was pushed down on my todo-list by more important stuff.

That looks great, thank you for working on that!

> If you want to experiment with that ...

I will have a look.

> > > note this could be optimized a bit
> > > further: state.period only depends on carrier which rarely changes, so
> > > the calculation could be done in pwm_ir_set_carrier(). Ditto for duty
> > > which only depends on state.period and pwm_ir->duty_cycle. (This is for
> > > a separate commit though.)
> > 
> > I'm not sure what caching this is much of a win. The calculation is a few
> > instructions, so you're not winning in the way of speed. On the flip side
> > you use more memory since pwm_state has to be kmalloc() rather than existing
> 
> I tested a bit with this patch on top of Maíra's:
> 
> 	diff --git a/drivers/media/rc/pwm-ir-tx.c b/drivers/media/rc/pwm-ir-tx.c
> 	index 105a9c24f1e3..7585c21775bc 100644
> 	--- a/drivers/media/rc/pwm-ir-tx.c
> 	+++ b/drivers/media/rc/pwm-ir-tx.c
> 	@@ -17,7 +17,7 @@
> 	 
> 	 struct pwm_ir {
> 		struct pwm_device *pwm;
> 	-	unsigned int carrier;
> 	+	struct pwm_state state;
> 		unsigned int duty_cycle;
> 	 };
> 	 
> 	@@ -32,6 +32,7 @@ static int pwm_ir_set_duty_cycle(struct rc_dev *dev, u32 duty_cycle)
> 		struct pwm_ir *pwm_ir = dev->priv;
> 	 
> 		pwm_ir->duty_cycle = duty_cycle;
> 	+	pwm_set_relative_duty_cycle(&pwm_ir->state, pwm_ir->duty_cycle, 100);
> 	 
> 		return 0;
> 	 }
> 	@@ -43,7 +44,8 @@ static int pwm_ir_set_carrier(struct rc_dev *dev, u32 carrier)
> 		if (!carrier)
> 			return -EINVAL;
> 	 
> 	-	pwm_ir->carrier = carrier;
> 	+	pwm_ir->state.period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, carrier);
> 	+	pwm_set_relative_duty_cycle(&pwm_ir->state, pwm_ir->duty_cycle, 100);
> 	 
> 		return 0;
> 	 }
> 	@@ -53,21 +55,15 @@ static int pwm_ir_tx(struct rc_dev *dev, unsigned int *txbuf,
> 	 {
> 		struct pwm_ir *pwm_ir = dev->priv;
> 		struct pwm_device *pwm = pwm_ir->pwm;
> 	-	struct pwm_state state;
> 		int i;
> 		ktime_t edge;
> 		long delta;
> 	 
> 	-	pwm_init_state(pwm, &state);
> 	-
> 	-	state.period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, pwm_ir->carrier);
> 	-	pwm_set_relative_duty_cycle(&state, pwm_ir->duty_cycle, 100);
> 	-
> 		edge = ktime_get();
> 	 
> 		for (i = 0; i < count; i++) {
> 	-		state.enabled = !(i % 2);
> 	-		pwm_apply_state(pwm, &state);
> 	+		pwm_ir->state.enabled = !(i % 2);
> 	+		pwm_apply_state(pwm, &pwm_ir->state);
> 	 
> 			edge = ktime_add_us(edge, txbuf[i]);
> 			delta = ktime_us_delta(edge, ktime_get());
> 	@@ -75,8 +71,8 @@ static int pwm_ir_tx(struct rc_dev *dev, unsigned int *txbuf,
> 				usleep_range(delta, delta + 10);
> 		}
> 	 
> 	-	state.enabled = false;
> 	-	pwm_apply_state(pwm, &state);
> 	+	pwm_ir->state.enabled = false;
> 	+	pwm_apply_state(pwm, &pwm_ir->state);
> 	 
> 		return count;
> 	 }
> 	@@ -95,8 +91,9 @@ static int pwm_ir_probe(struct platform_device *pdev)
> 		if (IS_ERR(pwm_ir->pwm))
> 			return PTR_ERR(pwm_ir->pwm);
> 	 
> 	-	pwm_ir->carrier = 38000;
> 	-	pwm_ir->duty_cycle = 50;
> 	+	pwm_ir->state.duty_cycle = 50;
> 	+	pwm_init_state(pwm_ir->pwm, &pwm_ir->state);
> 	+	pwm_ir_set_carrier(rcdev, 38000);
> 	 
> 		rcdev = devm_rc_allocate_device(&pdev->dev, RC_DRIVER_IR_RAW_TX);
> 		if (!rcdev)
> 
> bloat-o-meter reports (for an arm allmodconfig build)
> 
> 	add/remove: 0/0 grow/shrink: 3/1 up/down: 644/-396 (248)
> 	Function                                     old     new   delta
> 	pwm_ir_probe                                 372     676    +304
> 	pwm_ir_set_carrier                           108     292    +184
> 	pwm_ir_set_duty_cycle                         68     224    +156
> 	pwm_ir_tx                                    908     512    -396
> 	Total: Before=2302, After=2550, chg +10.77%

So 248 bytes more after your changes.

> struct pwm_ir increases from 12 bytes to 40 bytes.
> 
> The stack space required by pwm_ir_tx decreases from 60 to 36
> 
> I don't know exactly how kmalloc works internally. Maybe allocating a
> structure of size 40 bytes doesn't need more memory than a structure of
> size 12?
> 
> I didn't check how runtimes change, but the size decrease of pwm_ir_tx()
> is nice and might save a bit of runtime.

I'm not following, how is this decreasing runtime? 

> Probably it depends on your focus if this change is good for you or not.

Decreasing size is of course a good thing.

> > just on the stack, and both ioctl handlers and the probe function need to
> > recalculate the period/duty cycle, so there is a slight increase in code size.
> > 
> > This change does not improve anything measurably and only increases code
> > complexity.
> 
> You did measure?

Thanks for prototyping this.


Sean

  reply	other threads:[~2021-10-28 12:26 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-27 15:34 [PATCH v4] media: rc: pwm-ir-tx: Switch to atomic PWM API Maíra Canal
2021-10-27 15:34 ` Maíra Canal
2021-10-28  6:45 ` Uwe Kleine-König
2021-10-28  6:45   ` Uwe Kleine-König
2021-10-28  9:14   ` Sean Young
2021-10-28  9:14     ` Sean Young
2021-10-28 11:15     ` Uwe Kleine-König
2021-10-28 11:15       ` Uwe Kleine-König
2021-10-28 12:26       ` Sean Young [this message]
2021-10-28 12:26         ` Sean Young
2021-10-28 18:05         ` Uwe Kleine-König
2021-10-28 18:05           ` Uwe Kleine-König
2021-10-29  7:16           ` Sean Young
2021-10-29  7:16             ` Sean Young
2021-10-29 11:06             ` Uwe Kleine-König
2021-10-29 11:06               ` Uwe Kleine-König
2021-10-29 11:54               ` Sean Young
2021-10-29 11:54                 ` Sean Young
2021-10-29 12:08                 ` Maíra Canal
2021-10-29 12:08                   ` Maíra Canal
2021-10-29 15:18                   ` Uwe Kleine-König
2021-10-29 15:18                     ` Uwe Kleine-König
2021-10-30  9:21                   ` Sean Young
2021-10-30  9:21                     ` Sean Young
2021-10-31 10:39       ` Sean Young
2021-10-31 17:40         ` Uwe Kleine-König

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211028122610.GA18767@gofer.mess.org \
    --to=sean@mess.org \
    --cc=kbuild-all@lists.01.org \
    --cc=lee.jones@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-pwm@vger.kernel.org \
    --cc=lkp@intel.com \
    --cc=llvm@lists.linux.dev \
    --cc=maira.canal@usp.br \
    --cc=mchehab@kernel.org \
    --cc=thierry.reding@gmail.com \
    --cc=u.kleine-koenig@pengutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.