All of lore.kernel.org
 help / color / mirror / Atom feed
From: fabrizio.castro@bp.renesas.com (Fabrizio Castro)
To: cip-dev@lists.cip-project.org
Subject: [cip-dev] [PATCH 4.19.y 02/17] clocksource/drivers/sh_cmt: Fixup for 64-bit machines
Date: Mon,  1 Apr 2019 10:58:01 +0100	[thread overview]
Message-ID: <1554112696-20706-3-git-send-email-fabrizio.castro@bp.renesas.com> (raw)
In-Reply-To: <1554112696-20706-1-git-send-email-fabrizio.castro@bp.renesas.com>

From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>

commit 22627c6f3ed3d9d0df13eec3c831b08f8186c38e upstream.

When trying to use CMT for clockevents on R-Car gen3 SoCs, I noticed
that 'max_delta_ns' for the broadcast timer (CMT) was shown as 1000 in
/proc/timer_list. It turned out that when calculating it, the driver did
1 << 32 (causing what I think was undefined behavior) resulting in a zero
delta, later clamped to 1000 by cev_delta2ns(). The root cause turned out
to be that the driver abused *unsigned long* for the CMT register values
(which are 16/32-bit), so that the calculation of 'ch->max_match_value'
in sh_cmt_setup_channel() used the wrong branch. Using more proper 'u32'
instead fixed 'max_delta_ns' and even fixed the switching an active
clocksource to CMT (which caused the system to turn non-interactive
before).

Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
---
 drivers/clocksource/sh_cmt.c | 72 ++++++++++++++++++++------------------------
 1 file changed, 33 insertions(+), 39 deletions(-)

diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 6f65cf8..efaf00d 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -70,18 +70,17 @@ struct sh_cmt_info {
 	unsigned int channels_mask;
 
 	unsigned long width; /* 16 or 32 bit version of hardware block */
-	unsigned long overflow_bit;
-	unsigned long clear_bits;
+	u32 overflow_bit;
+	u32 clear_bits;
 
 	/* callbacks for CMSTR and CMCSR access */
-	unsigned long (*read_control)(void __iomem *base, unsigned long offs);
+	u32 (*read_control)(void __iomem *base, unsigned long offs);
 	void (*write_control)(void __iomem *base, unsigned long offs,
-			      unsigned long value);
+			      u32 value);
 
 	/* callbacks for CMCNT and CMCOR access */
-	unsigned long (*read_count)(void __iomem *base, unsigned long offs);
-	void (*write_count)(void __iomem *base, unsigned long offs,
-			    unsigned long value);
+	u32 (*read_count)(void __iomem *base, unsigned long offs);
+	void (*write_count)(void __iomem *base, unsigned long offs, u32 value);
 };
 
 struct sh_cmt_channel {
@@ -95,9 +94,9 @@ struct sh_cmt_channel {
 
 	unsigned int timer_bit;
 	unsigned long flags;
-	unsigned long match_value;
-	unsigned long next_match_value;
-	unsigned long max_match_value;
+	u32 match_value;
+	u32 next_match_value;
+	u32 max_match_value;
 	raw_spinlock_t lock;
 	struct clock_event_device ced;
 	struct clocksource cs;
@@ -152,24 +151,22 @@ struct sh_cmt_device {
 #define SH_CMT32_CMCSR_CKS_RCLK1	(7 << 0)
 #define SH_CMT32_CMCSR_CKS_MASK		(7 << 0)
 
-static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs)
+static u32 sh_cmt_read16(void __iomem *base, unsigned long offs)
 {
 	return ioread16(base + (offs << 1));
 }
 
-static unsigned long sh_cmt_read32(void __iomem *base, unsigned long offs)
+static u32 sh_cmt_read32(void __iomem *base, unsigned long offs)
 {
 	return ioread32(base + (offs << 2));
 }
 
-static void sh_cmt_write16(void __iomem *base, unsigned long offs,
-			   unsigned long value)
+static void sh_cmt_write16(void __iomem *base, unsigned long offs, u32 value)
 {
 	iowrite16(value, base + (offs << 1));
 }
 
-static void sh_cmt_write32(void __iomem *base, unsigned long offs,
-			   unsigned long value)
+static void sh_cmt_write32(void __iomem *base, unsigned long offs, u32 value)
 {
 	iowrite32(value, base + (offs << 2));
 }
@@ -234,7 +231,7 @@ static const struct sh_cmt_info sh_cmt_info[] = {
 #define CMCNT 1 /* channel register */
 #define CMCOR 2 /* channel register */
 
-static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_channel *ch)
+static inline u32 sh_cmt_read_cmstr(struct sh_cmt_channel *ch)
 {
 	if (ch->iostart)
 		return ch->cmt->info->read_control(ch->iostart, 0);
@@ -242,8 +239,7 @@ static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_channel *ch)
 		return ch->cmt->info->read_control(ch->cmt->mapbase, 0);
 }
 
-static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch,
-				      unsigned long value)
+static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch, u32 value)
 {
 	if (ch->iostart)
 		ch->cmt->info->write_control(ch->iostart, 0, value);
@@ -251,39 +247,35 @@ static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch,
 		ch->cmt->info->write_control(ch->cmt->mapbase, 0, value);
 }
 
-static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_channel *ch)
+static inline u32 sh_cmt_read_cmcsr(struct sh_cmt_channel *ch)
 {
 	return ch->cmt->info->read_control(ch->ioctrl, CMCSR);
 }
 
-static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch,
-				      unsigned long value)
+static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch, u32 value)
 {
 	ch->cmt->info->write_control(ch->ioctrl, CMCSR, value);
 }
 
-static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_channel *ch)
+static inline u32 sh_cmt_read_cmcnt(struct sh_cmt_channel *ch)
 {
 	return ch->cmt->info->read_count(ch->ioctrl, CMCNT);
 }
 
-static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch,
-				      unsigned long value)
+static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch, u32 value)
 {
 	ch->cmt->info->write_count(ch->ioctrl, CMCNT, value);
 }
 
-static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch,
-				      unsigned long value)
+static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch, u32 value)
 {
 	ch->cmt->info->write_count(ch->ioctrl, CMCOR, value);
 }
 
-static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch,
-					int *has_wrapped)
+static u32 sh_cmt_get_counter(struct sh_cmt_channel *ch, u32 *has_wrapped)
 {
-	unsigned long v1, v2, v3;
-	int o1, o2;
+	u32 v1, v2, v3;
+	u32 o1, o2;
 
 	o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->info->overflow_bit;
 
@@ -303,7 +295,8 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch,
 
 static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start)
 {
-	unsigned long flags, value;
+	unsigned long flags;
+	u32 value;
 
 	/* start stop register shared by multiple timer channels */
 	raw_spin_lock_irqsave(&ch->cmt->lock, flags);
@@ -410,11 +403,11 @@ static void sh_cmt_disable(struct sh_cmt_channel *ch)
 static void sh_cmt_clock_event_program_verify(struct sh_cmt_channel *ch,
 					      int absolute)
 {
-	unsigned long new_match;
-	unsigned long value = ch->next_match_value;
-	unsigned long delay = 0;
-	unsigned long now = 0;
-	int has_wrapped;
+	u32 value = ch->next_match_value;
+	u32 new_match;
+	u32 delay = 0;
+	u32 now = 0;
+	u32 has_wrapped;
 
 	now = sh_cmt_get_counter(ch, &has_wrapped);
 	ch->flags |= FLAG_REPROGRAM; /* force reprogram */
@@ -611,9 +604,10 @@ static struct sh_cmt_channel *cs_to_sh_cmt(struct clocksource *cs)
 static u64 sh_cmt_clocksource_read(struct clocksource *cs)
 {
 	struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
-	unsigned long flags, raw;
+	unsigned long flags;
 	unsigned long value;
-	int has_wrapped;
+	u32 has_wrapped;
+	u32 raw;
 
 	raw_spin_lock_irqsave(&ch->lock, flags);
 	value = ch->total_cycles;
-- 
2.7.4

  parent reply	other threads:[~2019-04-01  9:58 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-01  9:57 [cip-dev] [PATCH 4.19.y 00/17] Add CMT and TMU support to RZ/G2E Fabrizio Castro
2019-04-01  9:58 ` [cip-dev] [PATCH 4.19.y 01/17] clocksource/drivers/sh_cmt: Convert to SPDX identifiers Fabrizio Castro
2019-04-12  8:11   ` Pavel Machek
2019-04-01  9:58 ` Fabrizio Castro [this message]
2019-04-01  9:58 ` [cip-dev] [PATCH 4.19.y 03/17] clocksource/drivers/sh_cmt: Fix clocksource width for 32-bit machines Fabrizio Castro
2019-04-01  9:58 ` [cip-dev] [PATCH 4.19.y 04/17] clocksource/drivers/sh_cmt: Properly line-wrap sh_cmt_of_table[] initializer Fabrizio Castro
2019-04-01  9:58 ` [cip-dev] [PATCH 4.19.y 05/17] dt-bindings: timer: renesas: cmt: document R-Car gen3 support Fabrizio Castro
2019-04-01  9:58 ` [cip-dev] [PATCH 4.19.y 06/17] clocksource/drivers/sh_cmt: Add " Fabrizio Castro
2019-04-01  9:58 ` [cip-dev] [PATCH 4.19.y 07/17] dt-bindings: timer: renesas, cmt: Document r8a774a1 CMT support Fabrizio Castro
2019-04-01  9:58 ` [cip-dev] [PATCH 4.19.y 08/17] dt-bindings: timer: renesas, cmt: Document r8a774c0 " Fabrizio Castro
2019-04-01  9:58 ` [cip-dev] [PATCH 4.19.y 09/17] arm64: dts: renesas: r8a774c0: Add CMT device nodes Fabrizio Castro
2019-04-09 20:55   ` Pavel Machek
2019-04-10  0:55     ` nobuhiro1.iwamatsu at toshiba.co.jp
2019-04-01  9:58 ` [cip-dev] [PATCH 4.19.y 10/17] clk: renesas: r8a774c0: Add missing CANFD clock Fabrizio Castro
2019-04-01  9:58 ` [cip-dev] [PATCH 4.19.y 11/17] clk: renesas: r8a774c0: Correct parent clock of DU Fabrizio Castro
2019-04-01  9:58 ` [cip-dev] [PATCH 4.19.y 12/17] clk: renesas: r8a774c0: Add TMU clock Fabrizio Castro
2019-04-01  9:58 ` [cip-dev] [PATCH 4.19.y 13/17] clk: renesas: r8a774c0: Fix LAST_DT_CORE_CLK Fabrizio Castro
2019-04-01  9:58 ` [cip-dev] [PATCH 4.19.y 14/17] dt-bindings: timer: renesas: tmu: Document r8a774c0 bindings Fabrizio Castro
2019-04-01  9:58 ` [cip-dev] [PATCH 4.19.y 15/17] arm64: dts: renesas: r8a774c0: Add TMU device nodes Fabrizio Castro
2019-04-01  9:58 ` [cip-dev] [PATCH 4.19.y 16/17] clocksource/drivers/sh_tmu: Convert to SPDX identifiers Fabrizio Castro
2019-04-01  9:58 ` [cip-dev] [PATCH 4.19.y 17/17] arm64: enable CMT/TMU support for Renesas SoC Fabrizio Castro

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=1554112696-20706-3-git-send-email-fabrizio.castro@bp.renesas.com \
    --to=fabrizio.castro@bp.renesas.com \
    --cc=cip-dev@lists.cip-project.org \
    /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.