Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp1677999ybl; Thu, 30 Jan 2020 04:10:11 -0800 (PST) X-Google-Smtp-Source: APXvYqy4JiZw7c7JNmwZLalPI5bsDl8wW9Y8ZvPG3w4BgyXp2epbx9J3JzmZzezCRGEO4IgFSKjz X-Received: by 2002:a05:6830:22cd:: with SMTP id q13mr3343857otc.224.1580386211524; Thu, 30 Jan 2020 04:10:11 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1580386211; cv=none; d=google.com; s=arc-20160816; b=eaWZpQVZcISAsRfpY0yH5sPTdyw3QIYscS+M4Z31mUc1M7aEmswWTafIXUhH3+abnm pM5XMHgO7P14nswWGkClDB2y2lHikhGMnUrQBKNYfIhcIlfzWDKhCzgDOVHHs8Hdhpdy IdfCHLDDQtQdgrNmI1Va08S4+5GOr8yVZlRXSzCEmzwtoRt8/HGoIQROdDaqSMvYE9Et N1O9cFDQQqAAB3X9KZYrQf/9whd37kFHH7BMeju0n5gOlmaZfuxFpgtQ/62pPi+EjiBf IyVzISejCRXtbl395fkgvCo6DrJ4V4VVQzuikLb4BRtpB+FulLtV93QgqVSzxq9vgmfe ssjQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=LrkIvDvrNXYWHApNqe3t61PUBGUIMYiDzggTQKjPxz0=; b=VbqCegxu3ecPY244DkPP5wQ/XQp/CgoJ9x2rHzTZKcRX5FVh+tAhuURTHwbGa8DsfZ Z7b99PPPgdvWKjo8C7QpQdzxN3UvT9kMuADuO6x0cQJQTscA8yf2rVIooe4rYCPmOhP4 FgxSziTb2dAlJqcUPx8i+FCu/vNtXIOSBwHLFCRI0DIo0NPY13brgbcBwX2OpotpQqBz JbIUi0Vh5EJFqGeKpwVH27CODwOZJ3dqkwlDlqtXJknpVkQM0V88+KfWaCdkeK++1HYb 0jO7hK6zKtdQzZSrKefsP+znzeNTGTacR5XGFNZbLvCK/Q9dfgdyxSzcriVNNv0RxT81 z4tw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=sFCCJFuW; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id x72si2435257oia.194.2020.01.30.04.09.58; Thu, 30 Jan 2020 04:10:11 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=sFCCJFuW; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727202AbgA3MHb (ORCPT + 99 others); Thu, 30 Jan 2020 07:07:31 -0500 Received: from mail-vs1-f65.google.com ([209.85.217.65]:43916 "EHLO mail-vs1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726980AbgA3MHb (ORCPT ); Thu, 30 Jan 2020 07:07:31 -0500 Received: by mail-vs1-f65.google.com with SMTP id 7so1873025vsr.10 for ; Thu, 30 Jan 2020 04:07:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=LrkIvDvrNXYWHApNqe3t61PUBGUIMYiDzggTQKjPxz0=; b=sFCCJFuWVSJeb5LMccXSELteBog3WeJAUjCP+M82bP5zcHgntWGf5eu98A+9HO4iFJ EVae15g3toaBDW44ND2EmfOMpKAofWS2XSfbVZqumZz75g0tE/wFnhbhXoEK+taNV2rS SyThsNgOT8H+jCROTyAg+K8vldBOLi7c4uKFAfH5MoC3IPUm7gfj27eynoDP5fLBcjhq oN/b4IZIGWABAUkVieVZJf5KFiHIof+0F1rGynGFjyIc9NQvdA+/tG8caQNmZ0p8x87t TW2VnuZcxFyn0EGijnwVueGbH5xMXJXm4UqLC3dF6hams4bXmHIPPiKeQjXhcMew4Jzd uR2w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=LrkIvDvrNXYWHApNqe3t61PUBGUIMYiDzggTQKjPxz0=; b=oVbSunbFWw7V8jWShmGlRfLXMsZ9SsLO/8agTyQYCHj9ZWdIAouGcqYbmGuZZxdC8A IgTLi7vJFEqRde8iiE6gZj8Bw4pmXjH6hEjVKfZsU63e0Om+0dl9/UOEG7oiL72+YODH VpDlbzNZl/91UEsDl4jcQPoYdkDv0ipQ3yy3D9fb1EIVvt86jFFrLqTCPTIWOeI5Thq2 nI0GGYdv1wSyVlGZKYm4fhBP6RZCXIepGcZob7BvXqJdDFyGI/pNR5cyxPMm9w2N0Pni wBEl1Pk7iRhXEsGwSzjttviyYXlpYhXnMMJAnyYfbJ/OSoklFiZFldBBtDzel6Z0MmyE uDMw== X-Gm-Message-State: APjAAAUP3haEoPIqaD+Exw7Bm9bHj6WNLjRFJX14A2dIMBjFXDduXuqk ZPiSm9Jun26ORCIJzsxsCAfly48UTOLGAvPRezau+Q== X-Received: by 2002:a67:e99a:: with SMTP id b26mr2815388vso.27.1580386049096; Thu, 30 Jan 2020 04:07:29 -0800 (PST) MIME-Version: 1.0 References: <9e3527ac0f6baa64aeda8eb634ca5020ea7478e5.1577976221.git.amit.kucheria@linaro.org> <20200102194552.GD988120@minitux> In-Reply-To: <20200102194552.GD988120@minitux> From: Amit Kucheria Date: Thu, 30 Jan 2020 17:37:18 +0530 Message-ID: Subject: Re: [PATCH v3 5/9] drivers: thermal: tsens: Add critical interrupt support To: Bjorn Andersson Cc: LKML , linux-arm-msm , Stephen Boyd , sivaa@codeaurora.org, Andy Gross , Linux PM list Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, Jan 3, 2020 at 1:15 AM Bjorn Andersson wrote: > > On Thu 02 Jan 06:54 PST 2020, Amit Kucheria wrote: > [..] > > @@ -189,6 +197,9 @@ static void tsens_set_interrupt_v1(struct tsens_priv *priv, u32 hw_id, > > case LOWER: > > index = LOW_INT_CLEAR_0 + hw_id; > > break; > > + case CRITICAL: > > + /* No critical interrupts before v2 */ > > + break; > > You need to break harder, right now you're just attempting to write > "enable" to VER_MAJOR in this case. Will fix. > > > } > > regmap_field_write(priv->rf[index], enable ? 0 : 1); > > } > [..] > > @@ -321,6 +357,64 @@ static inline u32 masked_irq(u32 hw_id, u32 mask, enum tsens_ver ver) > > return 0; > > } > > > > +/** > > + * tsens_critical_irq_thread - Threaded interrupt handler for critical interrupts > > () on the function name to denote it being a function. Will fix. > > > + * @irq: irq number > > + * @data: tsens controller private data > > + * > > + * Check all sensors to find ones that violated their critical threshold limits. > > + * Clear and then re-enable the interrupt. > > + * > > + * The level-triggered interrupt might deassert if the temperature returned to > > + * within the threshold limits by the time the handler got scheduled. We > > + * consider the irq to have been handled in that case. > > + * > > + * Return: IRQ_HANDLED > > + */ > > +irqreturn_t tsens_critical_irq_thread(int irq, void *data) > > +{ > > + struct tsens_priv *priv = data; > > + struct tsens_irq_data d; > > + unsigned long flags; > > + int temp, ret, i; > > + > > + for (i = 0; i < priv->num_sensors; i++) { > > + const struct tsens_sensor *s = &priv->sensor[i]; > > + u32 hw_id = s->hw_id; > > + > > + if (IS_ERR(s->tzd)) > > + continue; > > + if (!tsens_threshold_violated(priv, hw_id, &d)) > > + continue; > > + ret = get_temp_tsens_valid(s, &temp); > > + if (ret) { > > + dev_err(priv->dev, "[%u] %s: error reading sensor\n", hw_id, __func__); > > + continue; > > + } > > + > > + spin_lock_irqsave(&priv->ul_lock, flags); > > You meant crit_lock here? Good catch, will fix. > > But perhaps more importantly, why do you need a lock here? I'm reading and changing interrupt state registers in this section and there can be multiple interrupts occurring simultaneously. Without a lock, the interrupt threads could potentially stomp over each other's register state. Having said that, I think I found a potential problem in porting the downstream driver code. Basically, we only need critical interrupt to enable watchdog support. The critical interrupt HW line can be asserted by watchdog and by actual critical interrupts. One to one mapping of tsens critical interrupts to trip type CRITICAL in Linux leads to a HW shutdown. And we can use the trip type PASSIVE with multiple ranges of temperatures to handle several levels of trip. So I'll change the code below to mask the critical interrupts in the event it is triggered and only use the irq thread to handle watchdog interrupts. > > + > > + tsens_read_irq_state(priv, hw_id, s, &d); > > + > > + if (d.crit_viol && > > + !masked_irq(hw_id, d.crit_irq_mask, tsens_version(priv))) { > > + tsens_set_interrupt(priv, hw_id, CRITICAL, false); > > + if (d.crit_thresh > temp) { > > + dev_dbg(priv->dev, "[%u] %s: re-arm upper\n", > > + hw_id, __func__); > > + } else { > > + dev_dbg(priv->dev, "[%u] %s: TZ update trigger (%d mC)\n", > > + hw_id, __func__, temp); > > + } > > + tsens_set_interrupt(priv, hw_id, CRITICAL, true); > > + } > > + > > + spin_unlock_irqrestore(&priv->crit_lock, flags); > > + } > > + > > + return IRQ_HANDLED; > > +} > [..] > > @@ -125,6 +125,28 @@ static int tsens_register(struct tsens_priv *priv) > > goto err_put_device; > > } > > > > + if (priv->feat->crit_int) { > > + irq_crit = platform_get_irq_byname(pdev, "critical"); > > + if (irq_crit < 0) { > > + ret = irq_crit; > > + /* For old DTs with no IRQ defined */ > > + if (irq_crit == -ENXIO) > > + ret = 0; > > + goto err_crit_int; > > + } > > + ret = devm_request_threaded_irq(&pdev->dev, irq_crit, > > + NULL, tsens_critical_irq_thread, > > + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, > > You should omit the IRQF_TRIGGER_HIGH here, it will be provided by the > system configuration (DT). Will fix. > > > + dev_name(&pdev->dev), priv); > > + if (ret) { > > + dev_err(&pdev->dev, "%s: failed to get critical irq\n", __func__); > > + goto err_crit_int; > > + } > > + > > + enable_irq_wake(irq_crit); > > + } > > + > > +err_crit_int: > > enable_irq_wake(irq); > > > > err_put_device: > > diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h > [..] > > @@ -460,6 +526,8 @@ struct tsens_context { > > * @srot_map: pointer to SROT register address space > > * @tm_offset: deal with old device trees that don't address TM and SROT > > * address space separately > > + * @ul_lock: lock while processing upper/lower threshold interrupts > > This looks like an unrelated fixup to a previous patch? Please keep it > separate. Will remove. > > + * @crit_lock: lock while processing critical threshold interrupts > > * @rf: array of regmap_fields used to store value of the field > > * @ctx: registers to be saved and restored during suspend/resume > > * @feat: features of the IP > > @@ -479,6 +547,9 @@ struct tsens_priv { > > /* lock for upper/lower threshold interrupts */ > > spinlock_t ul_lock; > > > > + /* lock for critical threshold interrupts */ > > + spinlock_t crit_lock; > > You're lacking a spin_lock_init() of this. Will fix. > > + > > struct regmap_field *rf[MAX_REGFIELDS]; > > struct tsens_context ctx; > > struct tsens_features *feat; > > @@ -500,6 +571,7 @@ int tsens_enable_irq(struct tsens_priv *priv); > > void tsens_disable_irq(struct tsens_priv *priv); > > int tsens_set_trips(void *_sensor, int low, int high); > > irqreturn_t tsens_irq_thread(int irq, void *data); > > +irqreturn_t tsens_critical_irq_thread(int irq, void *data); > > I think you should squash tsens.c and tsens-common.c into one file, so > you don't need to keep adding these extern declarations for every > function - separate of this series of course. Agreed. The separation no longer makes sense. Thanks for the review.