From patchwork Tue Sep 4 18:31:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergei Shtylyov X-Patchwork-Id: 10587757 X-Patchwork-Delegate: geert@linux-m68k.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id ED8CA5A4 for ; Tue, 4 Sep 2018 18:32:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DC24129F77 for ; Tue, 4 Sep 2018 18:32:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CF9FC29F9F; Tue, 4 Sep 2018 18:32:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4C42129F77 for ; Tue, 4 Sep 2018 18:32:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726437AbeIDW6V (ORCPT ); Tue, 4 Sep 2018 18:58:21 -0400 Received: from mail-lf1-f67.google.com ([209.85.167.67]:34264 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726507AbeIDW6U (ORCPT ); Tue, 4 Sep 2018 18:58:20 -0400 Received: by mail-lf1-f67.google.com with SMTP id c29-v6so3830324lfj.1 for ; Tue, 04 Sep 2018 11:32:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cogentembedded-com.20150623.gappssmtp.com; s=20150623; h=from:subject:to:cc:organization:message-id:date:user-agent :mime-version:content-language:content-transfer-encoding; bh=qGlQug73Ty0yRS6nLaZOlGFFbanmGjPXcwfOkTGKbyU=; b=PA5wyL8aG6zccZ1dT3me26BCDR5mTu8PZzPzdWYkN7qncLbmoRuaAf9vDYzof720u8 c2XHssCxbE9N+MBNWOs/Ria/6CZEdnAkCNGPp1Hq4YlTmINUShW6WTrP1qw9WRn+SJEX USIxYjrPFJfcRMS8i+zqPDpCkckdlBogT0T3DJWwuy36YE2uFHxKMuG4qa2g7uMjjnbM 2f6l9XqYHOegfkuVbTK3aMR1DIuzaLNKFJ6Bu+CH8DNPK8kBaQlwZYhz7h5klCfZ9G1D Dt+3mcxc6PFpyTRu7+v889+TJTIXNDE61zlI2Z8QWj1EnIO9SVpVfq/zp4skOtUwDmnP IHjA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:subject:to:cc:organization:message-id:date :user-agent:mime-version:content-language:content-transfer-encoding; bh=qGlQug73Ty0yRS6nLaZOlGFFbanmGjPXcwfOkTGKbyU=; b=pC3qjYlsG46KZPkSFGvzJOrwTVgQtuzbdgsjTLlnPd2IGsaOXfh7j4Ery2WmmNng5x ORTm/77gyuye2a9rTbOn5Y05JyG7WmwT/fxJEUCmsM6DBXwtJSQ9aMCSBoZM0Gm3ySm2 /ZJQbSOzYTSAvapaHcZlsh6BusB07teDzvTsEBHdT/8uwQnN2o4imPgDocBQ4Mmx7rxk V31qZz/k8tEBSvqwkF+jXbqcDmNyQhQf9QxOcu2gcEP9UZWbhd/1caoJF+Tuf1a1+l2f va/oLZ5UZF3CvG9jShIs3hkFH98ZzYCjQDUdYdZx0OzV0h7+rAbl7Z6y/lM79Bux1pHm rI4g== X-Gm-Message-State: APzg51DxxCxewCHAE4HR9YHmrpofSNaoYEVwUtm3/VsxPn1+1EMkKY+J w0n9WLd6vSkDcaZrn95q+IMhoQ== X-Google-Smtp-Source: ANB0VdaRIU99H6YHx+/w3nkJkI7WA8wqJ/0GguIlW+Mjv9+h7oW52/k7ocBuVI9tuc3IGKEI577CDA== X-Received: by 2002:a19:f20:: with SMTP id e32-v6mr20818584lfi.2.1536085919563; Tue, 04 Sep 2018 11:31:59 -0700 (PDT) Received: from wasted.cogentembedded.com ([31.173.82.52]) by smtp.gmail.com with ESMTPSA id b22-v6sm4030297ljj.93.2018.09.04.11.31.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Sep 2018 11:31:58 -0700 (PDT) From: Sergei Shtylyov Subject: [PATCH v2] clocksource: sh_cmt: fixup for 64-bit machines To: Daniel Lezcano , Thomas Gleixner , linux-renesas-soc@vger.kernel.org Cc: Vladimir Barinov , Andrey Gusakov , Mikhail Ulyanov , linux-sh@vger.kernel.org Organization: Cogent Embedded Message-ID: Date: Tue, 4 Sep 2018 21:31:52 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 MIME-Version: 1.0 Content-Language: en-MW Sender: linux-renesas-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 worng 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 --- This patch is against the 'tip.git' repo's 'timers/core' branch. The CMT driver wasn't ever used on SH64; on R-Car gen3 (ARM64) I'm only enabling building of this driver now, so not sure how urgent is this... Changes in version 2: - completely redid the patch, fixing abuse of *unsigned long* for the CMT register values. drivers/clocksource/sh_cmt.c | 56 +++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 30 deletions(-) Index: tip/drivers/clocksource/sh_cmt.c =================================================================== --- tip.orig/drivers/clocksource/sh_cmt.c +++ tip/drivers/clocksource/sh_cmt.c @@ -82,14 +82,13 @@ struct sh_cmt_info { unsigned long 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 { @@ -103,9 +102,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; @@ -160,24 +159,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)); } @@ -242,7 +239,7 @@ static const struct sh_cmt_info sh_cmt_i #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); @@ -259,30 +256,27 @@ static inline void sh_cmt_write_cmstr(st 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); } @@ -290,7 +284,7 @@ static inline void sh_cmt_write_cmcor(st static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch, int *has_wrapped) { - unsigned long v1, v2, v3; + u32 v1, v2, v3; int o1, o2; o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->info->overflow_bit; @@ -311,7 +305,8 @@ static unsigned long sh_cmt_get_counter( 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); @@ -418,10 +413,10 @@ static void sh_cmt_disable(struct sh_cmt 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; + u32 value = ch->next_match_value; + u32 new_match; + u32 delay = 0; + u32 now = 0; int has_wrapped; now = sh_cmt_get_counter(ch, &has_wrapped); @@ -619,9 +614,10 @@ static struct sh_cmt_channel *cs_to_sh_c 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 raw; raw_spin_lock_irqsave(&ch->lock, flags); value = ch->total_cycles;