Thread (34 messages) 34 messages, 6 authors, 2015-06-01

Re: [PATCH v3 5/6] Watchdog: introduce ARM SBSA watchdog driver

From: Fu Wei <hidden>
Date: 2015-05-29 10:17:55
Also in: linux-watchdog, lkml

Hi Timur,

On 27 May 2015 at 00:50, Timur Tabi [off-list ref] wrote:
On 05/25/2015 05:03 AM, fu.wei-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
quoted
+/*
+ * help functions for accessing 32bit registers of SBSA Generic Watchdog
+ */
+static void sbsa_gwdt_cf_write(unsigned int reg, u32 val,
+                              struct watchdog_device *wdd)
+{
+       struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+       writel_relaxed(val, gwdt->control_base + reg);
+}
+
+static void sbsa_gwdt_rf_write(unsigned int reg, u32 val,
+                              struct watchdog_device *wdd)
+{
+       struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+       writel_relaxed(val, gwdt->refresh_base + reg);
+}
+
+static u32 sbsa_gwdt_cf_read(unsigned int reg, struct watchdog_device
*wdd)
+{
+       struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+
+       return readl_relaxed(gwdt->control_base + reg);
+}

I don't understand the value of these functions.  You're just adding
overhead to each read and write by dereferencing wdd every time.  I would
get rid of them and just call readl_relaxed() and writel_relaxed() directly.
yes, that makes sense, sometimes , I also feel these functions are a
little redundant,
let me see if I can improve it.
quoted
+/*
+ * help functions for accessing 64bit WCV register
+ */
+static u64 sbsa_gwdt_get_wcv(struct watchdog_device *wdd)
+{
+       u32 wcv_lo, wcv_hi;
+
+       do {
+               wcv_hi = sbsa_gwdt_cf_read(SBSA_GWDT_WCV_HI, wdd);
+               wcv_lo = sbsa_gwdt_cf_read(SBSA_GWDT_WCV_LO, wdd);
+       } while (wcv_hi != sbsa_gwdt_cf_read(SBSA_GWDT_WCV_HI, wdd));

Please add a comment indicating that you're trying to read WCV atomically.
OK , that makes sense
quoted
+
+       return (((u64)wcv_hi << 32) | wcv_lo);
+}

How about defining this macro:

#define make64(high, low) (((u64)(high) << 32) | (low))

and using it instead?  That makes the code easier to read.
good idea, but it's  just  used once, not sure if it's worthy
Actually, I have seen some macro in some driver, but not in kernel header file.
quoted
+
+static void sbsa_gwdt_set_wcv(struct watchdog_device *wdd, u64 value)
+{
+       u32 wcv_lo, wcv_hi;
+
+       wcv_lo = value & U32_MAX;
+       wcv_hi = (value >> 32) & U32_MAX;

Use upper_32_bits() and lower_32_bits() instead.
cool, thanks ,  fixed it
quoted
+
+       sbsa_gwdt_cf_write(SBSA_GWDT_WCV_HI, wcv_hi, wdd);
+       sbsa_gwdt_cf_write(SBSA_GWDT_WCV_LO, wcv_lo, wdd);
+}
+
+static void reload_timeout_to_wcv(struct watchdog_device *wdd)

This should be sbsa_gwdt_reload_timeout_to_wcv()
quoted
+{
+       struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+       u64 wcv;
+
+       wcv = arch_counter_get_cntvct() +
+               (u64)(wdd->timeout - wdd->pretimeout) * gwdt->clk;
+
+       sbsa_gwdt_set_wcv(wdd, wcv);

Shouldn't you program WCV and WOR together?
why? WOR just for pretimeout in this driver.
quoted
+static int sbsa_gwdt_set_pretimeout(struct watchdog_device *wdd,
+                                   unsigned int pretimeout)
+{
+       struct sbsa_gwdt *gwdt = to_sbsa_gwdt(wdd);
+       u32 wor;
+
+       wdd->pretimeout = pretimeout;
+       sbsa_gwdt_update_limits(wdd);
+
+       if (!pretimeout)
+               /* gives sbsa_gwdt_start a chance to setup timeout */
+               wor = gwdt->clk;
+       else
+               wor = pretimeout * gwdt->clk;
+
+       /* refresh the WOR, that will cause an explicit watchdog refresh
*/
+       sbsa_gwdt_cf_write(SBSA_GWDT_WOR, wor, wdd);

Why not just ping the watchdog explicitely?
we just setup WOR, but we don't need to load pretimeout to WCV now, right ?
quoted
+static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
+{
+       struct sbsa_gwdt *gwdt = (struct sbsa_gwdt *)dev_id;
+       struct watchdog_device *wdd = &gwdt->wdd;
+       u32 status;
+
+       status = sbsa_gwdt_cf_read(SBSA_GWDT_WCS, wdd);
+
+       if (status & SBSA_GWDT_WCS_WS0)

This should always be true.  Instead of reading WCS, I think you should just
panic().
I thinks I need to confirm it , in case this has been cleaned.
quoted
+static int sbsa_gwdt_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct sbsa_gwdt *gwdt;
+       struct watchdog_device *wdd;
+       struct resource *res;
+       void *rf_base, *cf_base;
+       int irq;
+       u32 clk, status;
+       int ret = 0;
+       u64 first_period_max = U64_MAX;
+
+       /*
+        * Get the frequency of system counter from
+        * the cp15 interface of ARM Generic timer
+        */
+       clk = arch_timer_get_cntfrq();
+       if (!clk) {

You have

        depends on ARM_ARCH_TIMER

in your Kconfig, so you don't need to check the return of
arch_timer_get_cntfrq().  It can never be zero.

Also, I would not use the variable name 'clk', because that's usually used
for a "struct clk" object.  I would call this "freq" instead.
yes, I have fixed it .

--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.


-- 
Best regards,

Fu Wei
Software Engineer
Red Hat Software (Beijing) Co.,Ltd.Shanghai Branch
Ph: +86 21 61221326(direct)
Ph: +86 186 2020 4684 (mobile)
Room 1512, Regus One Corporate Avenue,Level 15,
One Corporate Avenue,222 Hubin Road,Huangpu District,
Shanghai,China 200021
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help